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)))) lines)))))
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 http://programmingpraxis.codepad.org/Ep7u8l1h.
One Response to “Assembler, Part 3”