Assembler, Part 2
April 18, 2014
In the previous exercise we built an assembler for a hypothetical computer. Today we write a simulator for that hypothetical computer. The basic idea is simple: Start with a program counter at location 0, either perform the action at the location and advance the program counter to the next location, or set the program counter to the object of a jump instruction.
Your task is to write the simulator. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
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(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)))