Assembler, Part 3

April 23, 2014

The first phase of the assembler does nearly what we want. The only problem is that it discards empty lines or lines that consist of only a comment; of course, we need those lines for our listing. So we make two passes: the first pass is the same as the first pass of the assembler, and the second pass reads the assembly program a second time, creating output as it goes:

(define (listing file-name)
  (let* ((lines (asm1 file-name))
         (mem (asm2 lines))
         (widths (widths lines)))
    (define (wid n)
      (string-append "%-" (number->string (vector-ref widths n)) "s "))
    (with-input-from-file file-name
      (lambda ()
        (let loop ((k 0) (line (read-line)) (lines lines))
          (when (not (eof-object? line))
            (if (or (string=? line "")
                    (char=? (string-ref line 0) #\#))
                (begin (printf "%s\n" line) (loop k (read-line) lines))
                (begin (printf "%03d:  " k)
                       (printf "%05d   " (vector-ref mem k))
                       (printf (wid 0) (vector-ref (car lines) 1))
                       (printf (wid 1) (vector-ref (car lines) 2))
                       (printf (wid 2) (vector-ref (car lines) 3))
                       (printf (wid 3) (vector-ref (car lines) 4))
                       (printf "\n")
                       (loop (+ k 1) (read-line) (cdr lines))))))))))

We use an auxiliary function to compute the column widths:

(define (widths lines)
  (apply vector
    (map (lambda (xs) (apply max xs))
      (apply map list
        (map (lambda (line)
               (map string-length (cdr (vector->list line))))

To create the sample output on the first page of the exercise, say (listing "program.asm").

We used the printf function from a recent exercise. You can run the program at


Pages: 1 2

One Response to “Assembler, Part 3”

  1. (defn listing [C code]
      (let [mem (:M (load-asm C code))]
            (reduce (fn [[counter text] e]
                      (let [pref (if (whitespace? e)
                                   (format "%03d: %s\t" counter (aget (:M C) counter)))
                            new-counter (if (whitespace? e) counter (inc counter))]
                        [new-counter (str text "\n" pref e)]))
                    [0 ""]
                    (clojure.string/split code #"\n"))))))

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: