From deaaef2bd1b1b6c02dc8ba1ccf231eead8181d31 Mon Sep 17 00:00:00 2001 From: BenHall-7 Date: Thu, 3 Dec 2020 01:00:16 -0500 Subject: [PATCH 1/8] Get it to print 8 --- ls8/cpu.py | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 9a307496e..d258d615d 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -2,12 +2,24 @@ import sys +HLT = 0b000001 +LDI = 0b000010 +PRN = 0b000111 + class CPU: """Main CPU class.""" def __init__(self): """Construct a new CPU.""" - pass + self.ram = [0] * 256 + self.reg = [0] * 8 + self.pc = 0 + + def ram_read(self, addr): + return self.ram[addr] + + def ram_write(self, val, addr): + self.ram[addr] += val def load(self): """Load a program into memory.""" @@ -61,5 +73,25 @@ def trace(self): print() def run(self): - """Run the CPU.""" - pass + while True: + ir = self.ram_read(self.pc) + + self.pc += 1 + instruction = ir & 0b00111111 + operand_count = ir >> 6 + op_position = self.pc + operands = (self.ram_read(op_position + i) for i in range(operand_count)) + self.pc += operand_count + + if instruction == HLT: + break + elif instruction == LDI: + a = next(operands) + b = next(operands) + self.reg[a] = b + elif instruction == PRN: + print(self.reg[next(operands)]) + else: + self.trace() + raise f"UNRECOGNIZED INSTRUCTION: {instruction:b}" + From fc089045ecf5751fee1fb42eac949c8cf8ae83db Mon Sep 17 00:00:00 2001 From: BenHall-7 Date: Thu, 3 Dec 2020 01:15:36 -0500 Subject: [PATCH 2/8] Support command line program loading --- ls8/cpu.py | 16 ++-------------- ls8/ls8.py | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index d258d615d..3d47292ed 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -21,23 +21,11 @@ def ram_read(self, addr): def ram_write(self, val, addr): self.ram[addr] += val - def load(self): + def load(self, program): """Load a program into memory.""" address = 0 - # For now, we've just hardcoded a program: - - program = [ - # From print8.ls8 - 0b10000010, # LDI R0,8 - 0b00000000, - 0b00001000, - 0b01000111, # PRN R0 - 0b00000000, - 0b00000001, # HLT - ] - for instruction in program: self.ram[address] = instruction address += 1 @@ -93,5 +81,5 @@ def run(self): print(self.reg[next(operands)]) else: self.trace() - raise f"UNRECOGNIZED INSTRUCTION: {instruction:b}" + raise Exception(f"UNRECOGNIZED INSTRUCTION: {instruction:b}") diff --git a/ls8/ls8.py b/ls8/ls8.py index 74128d36b..daeed0ec3 100755 --- a/ls8/ls8.py +++ b/ls8/ls8.py @@ -5,7 +5,20 @@ import sys from cpu import * +if len(sys.argv) > 1: + with open(sys.argv[1]) as program_file: + program = [] + for line in program_file.readlines(): + ir_str = line.strip().partition("#")[0] + if len(ir_str) == 0: + # there was a comment or blank line + continue + program.append(int(ir_str, 2)) +else: + print("Required argument: program file name") + + cpu = CPU() -cpu.load() +cpu.load(program) cpu.run() \ No newline at end of file From b1b3b0a8177cbfe8f3d9965e4cf90c1f6ed6fc62 Mon Sep 17 00:00:00 2001 From: BenHall-7 Date: Fri, 4 Dec 2020 17:58:57 -0500 Subject: [PATCH 3/8] Add ALU instructions --- ls8/cpu.py | 82 +++++++++++++++++++++++++++++++++++++++++++----------- ls8/ls8.py | 10 +++---- 2 files changed, 69 insertions(+), 23 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 3d47292ed..1e69b31cb 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -2,9 +2,24 @@ import sys -HLT = 0b000001 -LDI = 0b000010 -PRN = 0b000111 +HLT = 0b0001 +LDI = 0b0010 +PRN = 0b0111 + +ALU_ADD = 0b0000 +ALU_SUB = 0b0001 +ALU_MUL = 0b0010 +ALU_DIV = 0b0011 +ALU_MOD = 0b0100 +ALU_INC = 0b0101 +ALU_DEC = 0b0110 +ALU_CMP = 0b0111 +ALU_AND = 0b1000 +ALU_NOT = 0b1001 +ALU_OR = 0b1010 +ALU_XOR = 0b1011 +ALU_SHL = 0b1100 +ALU_SHR = 0b1101 class CPU: """Main CPU class.""" @@ -34,9 +49,35 @@ def load(self, program): def alu(self, op, reg_a, reg_b): """ALU operations.""" - if op == "ADD": - self.reg[reg_a] += self.reg[reg_b] - #elif op == "SUB": etc + def add(): self.reg[reg_a] += self.reg[reg_b] + def sub(): self.reg[reg_a] -= self.reg[reg_b] + def mul(): self.reg[reg_a] *= self.reg[reg_b] + def div(): + if reg_b == 0: + raise "Can't divide by 0" + self.reg[reg_a] //= self.reg[reg_b] + # def mod(a, b): self.reg[a] %= self.reg[b] + + + ALU_INSTRUCTIONS = { + ALU_ADD: add, + ALU_SUB: sub, + ALU_MUL: mul, + ALU_DIV: div, + # ALU_MOD: lambda a, b: self.reg[a] % self.reg[b], + # ALU_INC: lambda a: self.reg[a] + 1, + # ALU_DEC: lambda a: self.reg[a] - 1, + # ALU_CMP: lambda a, b: self.reg[a] == self.reg[b], + # ALU_AND: lambda _: , + # ALU_NOT: lambda _: , + # ALU_OR: lambda _: , + # ALU_XOR: lambda _: , + # ALU_SHL: lambda _: , + # ALU_SHR: lambda _: , + } + + if op in ALU_INSTRUCTIONS: + ALU_INSTRUCTIONS[op]() else: raise Exception("Unsupported ALU operation") @@ -65,21 +106,28 @@ def run(self): ir = self.ram_read(self.pc) self.pc += 1 - instruction = ir & 0b00111111 + + instruction = ir & 0b1111 + is_alu = (ir >> 5) & 1 + sets_pc = (ir >> 4) & 1 operand_count = ir >> 6 + op_position = self.pc operands = (self.ram_read(op_position + i) for i in range(operand_count)) self.pc += operand_count - if instruction == HLT: - break - elif instruction == LDI: - a = next(operands) - b = next(operands) - self.reg[a] = b - elif instruction == PRN: - print(self.reg[next(operands)]) + if is_alu: + self.alu(instruction, next(operands), next(operands)) else: - self.trace() - raise Exception(f"UNRECOGNIZED INSTRUCTION: {instruction:b}") + if instruction == HLT: + break + elif instruction == LDI: + a = next(operands) + b = next(operands) + self.reg[a] = b + elif instruction == PRN: + print(self.reg[next(operands)]) + else: + self.trace() + raise Exception(f"UNRECOGNIZED INSTRUCTION: {instruction:b}") diff --git a/ls8/ls8.py b/ls8/ls8.py index daeed0ec3..b263852c8 100755 --- a/ls8/ls8.py +++ b/ls8/ls8.py @@ -14,11 +14,9 @@ # there was a comment or blank line continue program.append(int(ir_str, 2)) + cpu = CPU() + cpu.load(program) + cpu.run() else: print("Required argument: program file name") - - -cpu = CPU() - -cpu.load(program) -cpu.run() \ No newline at end of file + \ No newline at end of file From f23c150f5be63584785a86e02aaa97b62d26e8c8 Mon Sep 17 00:00:00 2001 From: BenHall-7 Date: Sun, 6 Dec 2020 22:00:04 -0500 Subject: [PATCH 4/8] Implement push, pop, call, and ret instructions --- ls8/cpu.py | 89 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 1e69b31cb..6f8ee275e 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -1,11 +1,17 @@ """CPU functionality.""" import sys +import traceback HLT = 0b0001 LDI = 0b0010 +PUSH = 0b0101 +POP = 0b0110 PRN = 0b0111 +CALL = 0b0000 +RET = 0b0001 + ALU_ADD = 0b0000 ALU_SUB = 0b0001 ALU_MUL = 0b0010 @@ -29,6 +35,7 @@ def __init__(self): self.ram = [0] * 256 self.reg = [0] * 8 self.pc = 0 + self.sp = 0xf4 def ram_read(self, addr): return self.ram[addr] @@ -102,32 +109,60 @@ def trace(self): print() def run(self): - while True: - ir = self.ram_read(self.pc) - - self.pc += 1 - - instruction = ir & 0b1111 - is_alu = (ir >> 5) & 1 - sets_pc = (ir >> 4) & 1 - operand_count = ir >> 6 - - op_position = self.pc - operands = (self.ram_read(op_position + i) for i in range(operand_count)) - self.pc += operand_count - - if is_alu: - self.alu(instruction, next(operands), next(operands)) - else: - if instruction == HLT: + try: + while True: + ir = self.ram_read(self.pc) + + self.pc += 1 + + instruction = ir & 0b1111 + is_alu = (ir >> 5) & 1 + sets_pc = (ir >> 4) & 1 + operand_count = ir >> 6 + + op_position = self.pc + operands = (self.ram_read(op_position + i) for i in range(operand_count)) + self.pc += operand_count + + if is_alu: + self.alu(instruction, next(operands), next(operands)) + elif sets_pc: + if instruction == CALL: + self.sp -= 1 + self.ram[self.sp] = self.pc + self.pc = self.reg[next(operands)] + elif instruction == RET: + self.pc = self.ram[self.sp] + self.sp += 1 + else: + raise Exception(f"UNRECOGNIZED INSTRUCTION: {instruction:b}") + elif instruction == HLT: break - elif instruction == LDI: - a = next(operands) - b = next(operands) - self.reg[a] = b - elif instruction == PRN: - print(self.reg[next(operands)]) else: - self.trace() - raise Exception(f"UNRECOGNIZED INSTRUCTION: {instruction:b}") - + def ldi(): + a = next(operands) + b = next(operands) + self.reg[a] = b + def prn(): print(self.reg[next(operands)]) + def push(): + self.sp -= 1 + self.ram[self.sp] = self.reg[next(operands)] + def pop(): + self.reg[next(operands)] = self.ram[self.sp] + self.sp += 1 + + INSTRUCTIONS = { + LDI: ldi, + PRN: prn, + PUSH: push, + POP: pop, + } + + if instruction in INSTRUCTIONS: + INSTRUCTIONS[instruction]() + else: + raise Exception(f"UNRECOGNIZED INSTRUCTION: {instruction:b}") + except Exception as e: + print(f"ERROR OCCURED: {e}") + traceback.print_exc() + self.trace() From 84c68b93f99eb303d5746cd0150a1d66aa65fd6e Mon Sep 17 00:00:00 2001 From: BenHall-7 Date: Wed, 9 Dec 2020 00:22:22 -0500 Subject: [PATCH 5/8] Implement interrupt handling --- ls8/cpu.py | 95 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 13 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 6f8ee275e..904ac57db 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -1,16 +1,26 @@ """CPU functionality.""" import sys +import time import traceback +IM = 5 +IS = 6 +SP = 7 + HLT = 0b0001 LDI = 0b0010 +ST = 0b0100 PUSH = 0b0101 POP = 0b0110 PRN = 0b0111 +PRA = 0b1000 CALL = 0b0000 RET = 0b0001 +INT = 0b0010 +IRET = 0b0011 +JMP = 0b0100 ALU_ADD = 0b0000 ALU_SUB = 0b0001 @@ -34,14 +44,28 @@ def __init__(self): """Construct a new CPU.""" self.ram = [0] * 256 self.reg = [0] * 8 + self.reg[SP] = 0xf4 self.pc = 0 - self.sp = 0xf4 + self.fl = 0 + # these aren't mentioned in the spec + # but there didn't seem to be a suitable place to put them + self.start_time = 0 + self.time = 0 def ram_read(self, addr): return self.ram[addr] def ram_write(self, val, addr): self.ram[addr] += val + + def push(self, val): + self.reg[SP] -= 1 + self.ram[self.reg[SP]] = val + + def pop(self): + val = self.ram[self.reg[SP]] + self.reg[SP] += 1 + return val def load(self, program): """Load a program into memory.""" @@ -110,7 +134,33 @@ def trace(self): def run(self): try: + self.start_time = time.time() while True: + self.reg[IS] = 0 + # timer interrupt status + self.time = time.time() + if self.time >= self.start_time + 1: + self.start_time += ((self.time - self.start_time) // 1) + self.reg[IS] |= 1 # timer interrupt bit + + # keyboard interrupt status + # TODO + + # check interrupts + maskedInterrupts = self.reg[IS] & self.reg[IM] + for bit in range(8): + if (maskedInterrupts >> bit) & 1: + self.reg[IS] & ~(1 << bit) + self.push(self.pc) + self.push(self.fl) + for reg in range(7): + self.push(self.reg[reg]) + # go to interrupt handler from interrupt address table + self.pc = self.ram[0xf8 + bit] + # disable further interrupts + self.reg[IM] = 0 + break + ir = self.ram_read(self.pc) self.pc += 1 @@ -127,13 +177,29 @@ def run(self): if is_alu: self.alu(instruction, next(operands), next(operands)) elif sets_pc: - if instruction == CALL: - self.sp -= 1 - self.ram[self.sp] = self.pc + def call(): + self.push(self.pc) self.pc = self.reg[next(operands)] - elif instruction == RET: - self.pc = self.ram[self.sp] - self.sp += 1 + def ret(): self.pc = self.pop() + def jmp(): self.pc = self.reg[next(operands)] + def int_(): self.reg[IS] |= 1 << self.reg[next(operands)] + def iret(): + for reg in reversed(range(7)): + self.reg[reg] = self.pop() + self.fl = self.pop() + self.pc = self.pop() + self.reg[IM] = ~0 + + INSTRUCTIONS = { + CALL: call, + RET: ret, + JMP: jmp, + INT: int_, + IRET: iret + } + + if instruction in INSTRUCTIONS: + INSTRUCTIONS[instruction]() else: raise Exception(f"UNRECOGNIZED INSTRUCTION: {instruction:b}") elif instruction == HLT: @@ -144,18 +210,21 @@ def ldi(): b = next(operands) self.reg[a] = b def prn(): print(self.reg[next(operands)]) - def push(): - self.sp -= 1 - self.ram[self.sp] = self.reg[next(operands)] - def pop(): - self.reg[next(operands)] = self.ram[self.sp] - self.sp += 1 + def pra(): print(chr(self.reg[next(operands)])) + def push(): self.push(self.reg[next(operands)]) + def pop(): self.reg[next(operands)] = self.pop() + def st(): + a = next(operands) + b = next(operands) + self.ram[self.reg[a]] = self.reg[b] INSTRUCTIONS = { LDI: ldi, PRN: prn, + PRA: pra, PUSH: push, POP: pop, + ST: st, } if instruction in INSTRUCTIONS: From 5ca7073258eb287d041dc7dae4fd65328855ae2b Mon Sep 17 00:00:00 2001 From: BenHall-7 Date: Thu, 10 Dec 2020 23:11:58 -0500 Subject: [PATCH 6/8] Implement cmp and conditional jumps --- ls8/cpu.py | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 904ac57db..89d08c831 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -21,6 +21,12 @@ INT = 0b0010 IRET = 0b0011 JMP = 0b0100 +JEQ = 0b0101 +JNE = 0b0110 +JGT = 0b0111 +JLT = 0b1000 +JLE = 0b1001 +JGE = 0b1010 ALU_ADD = 0b0000 ALU_SUB = 0b0001 @@ -88,7 +94,15 @@ def div(): raise "Can't divide by 0" self.reg[reg_a] //= self.reg[reg_b] # def mod(a, b): self.reg[a] %= self.reg[b] - + def cmp(): + a = self.reg[reg_a] + b = self.reg[reg_b] + if a == b: + self.fl = 0b1 + elif a > b: + self.fl = 0b10 + else: + self.fl = 0b100 ALU_INSTRUCTIONS = { ALU_ADD: add, @@ -98,7 +112,7 @@ def div(): # ALU_MOD: lambda a, b: self.reg[a] % self.reg[b], # ALU_INC: lambda a: self.reg[a] + 1, # ALU_DEC: lambda a: self.reg[a] - 1, - # ALU_CMP: lambda a, b: self.reg[a] == self.reg[b], + ALU_CMP: cmp, # ALU_AND: lambda _: , # ALU_NOT: lambda _: , # ALU_OR: lambda _: , @@ -189,11 +203,29 @@ def iret(): self.fl = self.pop() self.pc = self.pop() self.reg[IM] = ~0 - + def jeq(): + if self.fl & 1: self.pc = self.reg[next(operands)] + def jne(): + if not self.fl & 1: self.pc = self.reg[next(operands)] + def jgt(): + if self.fl & 0b10: self.pc = self.reg[next(operands)] + def jge(): + if self.fl & 0b11: self.pc = self.reg[next(operands)] + def jlt(): + if self.fl & 0b100: self.pc = self.reg[next(operands)] + def jle(): + if self.fl & 0b101: self.pc = self.reg[next(operands)] + INSTRUCTIONS = { CALL: call, RET: ret, JMP: jmp, + JEQ: jeq, + JNE: jne, + JGT: jgt, + JLT: jlt, + JLE: jle, + JGE: jge, INT: int_, IRET: iret } @@ -209,8 +241,12 @@ def ldi(): a = next(operands) b = next(operands) self.reg[a] = b - def prn(): print(self.reg[next(operands)]) - def pra(): print(chr(self.reg[next(operands)])) + def prn(): + print(self.reg[next(operands)], end="") + sys.stdout.flush() + def pra(): + print(chr(self.reg[next(operands)]), end="") + sys.stdout.flush() def push(): self.push(self.reg[next(operands)]) def pop(): self.reg[next(operands)] = self.pop() def st(): From 704de9a5d8fc6174d08c93f78617725cddec60d2 Mon Sep 17 00:00:00 2001 From: BenHall-7 Date: Thu, 10 Dec 2020 23:19:07 -0500 Subject: [PATCH 7/8] Implement shl and shr --- ls8/cpu.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 89d08c831..99af892fc 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -103,6 +103,8 @@ def cmp(): self.fl = 0b10 else: self.fl = 0b100 + def shl(): self.reg[reg_a] <<= self.reg[reg_b] + def shr(): self.reg[reg_a] >>= self.reg[reg_b] ALU_INSTRUCTIONS = { ALU_ADD: add, @@ -117,8 +119,8 @@ def cmp(): # ALU_NOT: lambda _: , # ALU_OR: lambda _: , # ALU_XOR: lambda _: , - # ALU_SHL: lambda _: , - # ALU_SHR: lambda _: , + ALU_SHL: shl, + ALU_SHR: shr, } if op in ALU_INSTRUCTIONS: From 2b270da6544335f68f28b0f9478716a956e73a75 Mon Sep 17 00:00:00 2001 From: BenHall-7 Date: Fri, 11 Dec 2020 00:14:16 -0500 Subject: [PATCH 8/8] Implement inc/dec and write histogram stretch solution --- asm/stretch.asm | 59 +++++++++++++++++++++++++++ ls8/cpu.py | 14 +++++-- ls8/stretch.ls8 | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 asm/stretch.asm create mode 100644 ls8/stretch.ls8 diff --git a/asm/stretch.asm b/asm/stretch.asm new file mode 100644 index 000000000..644ff8984 --- /dev/null +++ b/asm/stretch.asm @@ -0,0 +1,59 @@ +LDI R1, 0 ; loop index +LDI R2, 7 ; number of lines to print + +MainLoopStart: + CMP R1, R2 + LDI R0, MainLoopEnd + JGE R0 + LDI R0, 1 + SHL R0, R1 ; number of chars to print + LDI R3, PrintN + CALL R3 + INC R1 + LDI R0, MainLoopStart + JMP R0 + +MainLoopEnd: + HLT + +; R0 arg corresponds to number of chars to print +PrintN: + PUSH R1 + PUSH R2 + PUSH R3 + LDI R1, 1 + + PrintNLoopStart: + CMP R1, R0 + LDI R2, PrintNLoopEnd + JGT R2 + LDI R2, PrintAsterisk + CALL R2 + INC R1 + LDI R2, PrintNLoopStart + JMP R2 + + PrintNLoopEnd: + LDI R3, Newline + LD R2, R3 + PRA R2 + POP R3 + POP R2 + POP R1 + RET + +PrintAsterisk: + PUSH R0 + PUSH R1 + LDI R0, Asterisk + LD R1, R0 ; load the * character into R0 + PRA R1 + POP R1 + POP R0 + RET + +Asterisk: + ds * + +Newline: + db 0x0a \ No newline at end of file diff --git a/ls8/cpu.py b/ls8/cpu.py index 99af892fc..8f8e16436 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -10,6 +10,7 @@ HLT = 0b0001 LDI = 0b0010 +LD = 0b0011 ST = 0b0100 PUSH = 0b0101 POP = 0b0110 @@ -105,6 +106,8 @@ def cmp(): self.fl = 0b100 def shl(): self.reg[reg_a] <<= self.reg[reg_b] def shr(): self.reg[reg_a] >>= self.reg[reg_b] + def inc(): self.reg[reg_a] += 1 + def dec(): self.reg[reg_a] -= 1 ALU_INSTRUCTIONS = { ALU_ADD: add, @@ -112,8 +115,8 @@ def shr(): self.reg[reg_a] >>= self.reg[reg_b] ALU_MUL: mul, ALU_DIV: div, # ALU_MOD: lambda a, b: self.reg[a] % self.reg[b], - # ALU_INC: lambda a: self.reg[a] + 1, - # ALU_DEC: lambda a: self.reg[a] - 1, + ALU_INC: inc, + ALU_DEC: dec, ALU_CMP: cmp, # ALU_AND: lambda _: , # ALU_NOT: lambda _: , @@ -191,7 +194,7 @@ def run(self): self.pc += operand_count if is_alu: - self.alu(instruction, next(operands), next(operands)) + self.alu(instruction, next(operands), next(operands, 0)) elif sets_pc: def call(): self.push(self.pc) @@ -243,6 +246,10 @@ def ldi(): a = next(operands) b = next(operands) self.reg[a] = b + def ld(): + a = next(operands) + b = next(operands) + self.reg[a] = self.ram[self.reg[b]] def prn(): print(self.reg[next(operands)], end="") sys.stdout.flush() @@ -258,6 +265,7 @@ def st(): INSTRUCTIONS = { LDI: ldi, + LD: ld, PRN: prn, PRA: pra, PUSH: push, diff --git a/ls8/stretch.ls8 b/ls8/stretch.ls8 new file mode 100644 index 000000000..1012cb0c6 --- /dev/null +++ b/ls8/stretch.ls8 @@ -0,0 +1,104 @@ +10000010 # LDI R1,0 +00000001 +00000000 +10000010 # LDI R2,7 +00000010 +00000111 +# MAINLOOPSTART (address 6): +10100111 # CMP R1,R2 +00000001 +00000010 +10000010 # LDI R0,MAINLOOPEND +00000000 +00100000 +01011010 # JGE R0 +00000000 +10000010 # LDI R0,1 +00000000 +00000001 +10101100 # SHL R0,R1 +00000000 +00000001 +10000010 # LDI R3,PRINTN +00000011 +00100001 +01010000 # CALL R3 +00000011 +01100101 # INC R1 +00000001 +10000010 # LDI R0,MAINLOOPSTART +00000000 +00000110 +01010100 # JMP R0 +00000000 +# MAINLOOPEND (address 32): +00000001 # HLT +# PRINTN (address 33): +01000101 # PUSH R1 +00000001 +01000101 # PUSH R2 +00000010 +01000101 # PUSH R3 +00000011 +10000010 # LDI R1,1 +00000001 +00000001 +# PRINTNLOOPSTART (address 42): +10100111 # CMP R1,R0 +00000001 +00000000 +10000010 # LDI R2,PRINTNLOOPEND +00000010 +00111110 +01010111 # JGT R2 +00000010 +10000010 # LDI R2,PRINTASTERISK +00000010 +01001101 +01010000 # CALL R2 +00000010 +01100101 # INC R1 +00000001 +10000010 # LDI R2,PRINTNLOOPSTART +00000010 +00101010 +01010100 # JMP R2 +00000010 +# PRINTNLOOPEND (address 62): +10000010 # LDI R3,NEWLINE +00000011 +01011111 +10000011 # LD R2,R3 +00000010 +00000011 +01001000 # PRA R2 +00000010 +01000110 # POP R3 +00000011 +01000110 # POP R2 +00000010 +01000110 # POP R1 +00000001 +00010001 # RET +# PRINTASTERISK (address 77): +01000101 # PUSH R0 +00000000 +01000101 # PUSH R1 +00000001 +10000010 # LDI R0,ASTERISK +00000000 +01011110 +10000011 # LD R1,R0 +00000001 +00000000 +01001000 # PRA R1 +00000001 +01000110 # POP R1 +00000001 +01000110 # POP R0 +00000000 +00010001 # RET +# ASTERISK (address 94): +00101010 # * +# NEWLINE (address 95): +00001010 # 0x0a