Assembler, Part 2

April 18, 2014

Here’s our very simple simulator:

(define (sim mem)
  (let loop ((pc 0) (acc 0))
    (let ((addr (modulo (vector-ref mem pc) 1000))
          (code (quotient (vector-ref mem pc) 1000)))
      (case code
      ((1) (loop (+ pc 1) (read))) ; get
      ((2) (display acc) (newline) (loop (+ pc 1) acc)) ; put
      ((3) (loop (+ pc 1) (vector-ref mem addr))) ; ld
      ((4) (vector-set! mem addr acc) (loop (+ pc 1) acc)) ; st
      ((5) (loop (+ pc 1) (+ acc (vector-ref mem addr)))) ; add
      ((6) (loop (+ pc 1) (- acc (vector-ref mem addr)))) ; sub
      ((7) (loop (if (positive? acc) addr (+ pc 1)) acc)) ; jpos
      ((8) (loop (if (zero? acc) addr (+ pc 1)) acc)) ; jz
      ((9) (loop addr acc)) ; j
      ((10) (if #f #f)) ; halt
      (else (error 'sim "unrecognized command"))))))

The two loop control variables are the program counter and accumulator. At each step, the current memory location is split into address and opcode, then the program dispatches on opcode, performs the indicated action, then either advances the program counter or resets it for a jump. The (if #f #f) is the standard Scheme idiom for a no-op that does nothing and returns nothing; output is created by the put opcode, not by returning a value from the function. Here’s what a run of the sample program looks like:

> (sim (asm2 (asm1 "program.asm")))
17 
35
102
0
154

There is no prompt in the program, so the program pauses, waiting for input. At the first pause the user enters 17, at the second pause the user enters 35, at the third pause the user enters 102, and at the fourth pause the user enters 0 to stop the program. Then the program reports the result, 154, and exits.

You can run the program at http://programmingpraxis.codepad.org/gDjSzX9P.

About these ads

Pages: 1 2

2 Responses to “Assembler, Part 2”

  1. Mike said

    Simulator in python

    
    def run(memory):
        accumulator = 0
        pc = 0
    
        while True:
            op, arg = divmod(memory[pc], 1000)
    
            if 1 <= op <= 6:
                if   op == 1: accumulator = int(input('? '))
                elif op == 2: print(accumulator)
                elif op == 3: accumulator = memory[arg]
                elif op == 4: memory[arg] = accumulator
                elif op == 5: accumulator = (accumulator + memory[arg]) % 100000
                elif op == 6: accumulator = (accumulator - memory[arg]) % 100000
    
                pc = (pc + 1) % 1000
    
            elif 7 <= op <= 9:
                if   op == 7: test = 0 < accumulator < 50000 # 10's complement ?
                elif op == 8: test = accumulator == 0
                elif op == 9: test = True
    
                pc = arg if test else (pc + 1)
                
            elif op == 10: # halt
                break
    
            else:
                fmt = "Trap: invalid instruction '{:05}' at location '{:03}'."
                print(fmt.format(memory[pc], pc))
                break
    
    
  2. (defn delta [C]
      (let [pc (:pc C)
            instr (aget (:M C) pc)
            opc ((clojure.set/map-invert (:opc C)) (apply str (take 2 instr)))
            arg (Integer/parseInt (apply str (nthrest instr 2)))
            C (assoc C :pc (inc pc))]
        (condp = opc
          "get"   (assoc C :acc (Integer/parseInt (read-line)))
          "put"   (println (:acc C))
          "ld"    (assoc C :acc (aget (:M C) arg))
          "st"    (do
                    (aset (:M C) arg (str (:acc C)))
                    C)
          "add"   (assoc C :acc (+ (:acc C) (Integer/parseInt (aget (:M C) arg))))
          "sub"   (assoc C :acc (- (:acc C) (Integer/parseInt (aget (:M C) arg))))
          "jpos"  (if (< 0 (:acc C)) (assoc C :pc arg) C)
          "jz"    (if (= 0 (:acc C)) (assoc C :pc arg) C)
          "j"     (assoc C :pc arg)
          "halt"  (dissoc C :pc)
          :default C)))
    
    (defn run [C code]
      (loop [C (load-asm C code)]
        (if (:pc C)
          (recur (delta C))
          C)))
    

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 612 other followers

%d bloggers like this: