def p(computer: Computer, a: Assembler): """ count by 3 """ computer.ram.memory[0] = a.m(ASM.LDI, 3) computer.ram.memory[1] = a.m(ASM.STA, 15) computer.ram.memory[2] = a.m(ASM.LDI, 0) computer.ram.memory[3] = a.m(ASM.ADD, 15) computer.ram.memory[4] = a.m(ASM.OUT, 0) computer.ram.memory[5] = a.m(ASM.JMP, 3)
def p(computer: Computer, a: Assembler): """ add 28 + 14 """ computer.ram.memory[0] = a.m(ASM.LDA, 14) computer.ram.memory[1] = a.m(ASM.ADD, 15) computer.ram.memory[2] = a.m(ASM.OUT, 0) computer.ram.memory[3] = a.m(ASM.HLT, 0) computer.ram.memory[14] = 28 computer.ram.memory[15] = 14
def p(computer: Computer, a: Assembler): """ bit shift left """ computer.ram.memory[0] = a.m(ASM.LDI, 1) computer.ram.memory[1] = a.m(ASM.STA, 15) computer.ram.memory[2] = a.m(ASM.LDA, 15) computer.ram.memory[3] = a.m(ASM.ADD, 15) computer.ram.memory[4] = a.m(ASM.STA, 15) computer.ram.memory[5] = a.m(ASM.JC, 0) computer.ram.memory[6] = a.m(ASM.JMP, 2)
def p(computer: Computer, a: Assembler): """ 5 + 6 - 7 """ computer.ram.memory[0] = a.m(ASM.LDA, 15) computer.ram.memory[1] = a.m(ASM.ADD, 14) computer.ram.memory[2] = a.m(ASM.SUB, 13) computer.ram.memory[3] = a.m(ASM.OUT, 0) computer.ram.memory[4] = a.m(ASM.HLT, 0) computer.ram.memory[13] = 7 computer.ram.memory[14] = 6 computer.ram.memory[15] = 5
def p(computer: Computer, a: Assembler): """ bounce between signed ints -127 and 127 - remember to flip the 2s complement switch """ computer.ram.memory[0] = a.m(ASM.LDA, 14) computer.ram.memory[1] = a.m(ASM.OUT, 0) computer.ram.memory[2] = a.m(ASM.ADD, 15) computer.ram.memory[3] = a.m(ASM.STA, 14) computer.ram.memory[4] = a.m(ASM.SUB, 13) computer.ram.memory[5] = a.m(ASM.JZ, 7) computer.ram.memory[6] = a.m(ASM.JMP, 0) computer.ram.memory[7] = a.m(ASM.SUB, 15) computer.ram.memory[8] = a.m(ASM.STA, 15) computer.ram.memory[9] = a.m(ASM.LDA, 14) computer.ram.memory[10] = a.m(ASM.ADD, 15) computer.ram.memory[11] = a.m(ASM.STA, 14) computer.ram.memory[12] = a.m(ASM.JMP, 0) computer.ram.memory[13] = 128 # const computer.ram.memory[14] = 0 # number counted computer.ram.memory[15] = 1 # step size
def p(computer: Computer, a: Assembler): """ Ben Eater's fibonacci """ computer.ram.memory[0] = a.m(ASM.LDI, 1) computer.ram.memory[1] = a.m(ASM.STA, 14) computer.ram.memory[2] = a.m(ASM.LDI, 0) computer.ram.memory[3] = a.m(ASM.OUT, 0) computer.ram.memory[4] = a.m(ASM.ADD, 14) computer.ram.memory[5] = a.m(ASM.STA, 15) computer.ram.memory[6] = a.m(ASM.LDA, 14) computer.ram.memory[7] = a.m(ASM.STA, 13) computer.ram.memory[8] = a.m(ASM.LDA, 15) computer.ram.memory[9] = a.m(ASM.STA, 14) computer.ram.memory[10] = a.m(ASM.LDA, 13) computer.ram.memory[11] = a.m(ASM.JC, 0) computer.ram.memory[12] = a.m(ASM.JMP, 3)
def p(computer: Computer, a: Assembler): """ jump indirect """ computer.ram.memory[0] = a.m(ASM.LDI, 3) computer.ram.memory[1] = a.m(ASM.STA, 15) computer.ram.memory[2] = a.m(ASM.JMP, 10) computer.ram.memory[3] = a.m(ASM.LDI, 6) computer.ram.memory[4] = a.m(ASM.STA, 15) computer.ram.memory[5] = a.m(ASM.JMP, 10) computer.ram.memory[6] = a.m(ASM.LDI, 9) computer.ram.memory[7] = a.m(ASM.STA, 15) computer.ram.memory[8] = a.m(ASM.JMP, 10) computer.ram.memory[9] = a.m(ASM.HLT, 0) computer.ram.memory[10] = a.m(ASM.LDA, 15) computer.ram.memory[11] = a.m(ASM.OUT, 0) computer.ram.memory[12] = a.m(ASM.JI, 15)
def p(computer: Computer, a: Assembler): """ load and store indirect (1 13 1) """ computer.ram.memory[0] = a.m(ASM.LIN, 13) computer.ram.memory[1] = a.m(ASM.OUT, 0) # 1 computer.ram.memory[2] = a.m(ASM.LDA, 13) computer.ram.memory[3] = a.m(ASM.ADD, 14) computer.ram.memory[4] = a.m(ASM.SIN, 15) computer.ram.memory[5] = a.m(ASM.LIN, 13) computer.ram.memory[6] = a.m(ASM.OUT, 0) # 13 computer.ram.memory[7] = a.m(ASM.LDA, 13) computer.ram.memory[8] = a.m(ASM.SUB, 14) computer.ram.memory[9] = a.m(ASM.STA, 13) computer.ram.memory[10] = a.m(ASM.LIN, 13) computer.ram.memory[11] = a.m(ASM.OUT, 0) # 1 computer.ram.memory[12] = a.m(ASM.HLT, 0) computer.ram.memory[13] = 14 computer.ram.memory[14] = 1 computer.ram.memory[15] = 13
def p(computer: Computer, a: Assembler): """ use divide subroutine to test negative division """ computer.ram.memory[0] = a.m(ASM.LDA, 15) computer.ram.memory[1] = a.m(ASM.STA, 2250) # a operand computer.ram.memory[2] = a.m(ASM.LDI, 2) computer.ram.memory[3] = a.m(ASM.STA, 2251) # b operand computer.ram.memory[4] = a.m(ASM.LDI, 7) computer.ram.memory[5] = a.m(ASM.STA, 2252) # return program counter computer.ram.memory[6] = a.m(ASM.JMP, 2200) # divide subroutine computer.ram.memory[7] = a.m(ASM.LDA, 2253) # result computer.ram.memory[8] = a.m(ASM.OUT, 0) computer.ram.memory[9] = a.m(ASM.HLT, 0) computer.ram.memory[15] = 0b1111111111110111 # -9
def p(computer: Computer, a: Assembler): """ floored sqrt: sqrt(50) """ computer.ram.memory[0] = a.m(ASM.LDA, 14) computer.ram.memory[1] = a.m(ASM.ADD, 13) computer.ram.memory[2] = a.m(ASM.STA, 14) computer.ram.memory[3] = a.m(ASM.LDA, 13) computer.ram.memory[4] = a.m(ASM.SUB, 14) computer.ram.memory[5] = a.m(ASM.SUB, 14) computer.ram.memory[6] = a.m(ASM.ADD, 15) computer.ram.memory[7] = a.m(ASM.STA, 15) computer.ram.memory[8] = a.m(ASM.JC, 0) computer.ram.memory[9] = a.m(ASM.LDA, 14) computer.ram.memory[10] = a.m(ASM.SUB, 13) computer.ram.memory[11] = a.m(ASM.OUT, 0) computer.ram.memory[12] = a.m(ASM.HLT, 0) computer.ram.memory[13] = 1 # const computer.ram.memory[14] = 0 # result computer.ram.memory[15] = 50 # input
def main(): a = Assembler(ADDRESS_LENGTH) print("initializing computer...") computer = Computer(ADDRESS_LENGTH, True) print("programming computer...") p1(computer, a) p2(computer, a) p4(computer, a) p5(computer, a) p6(computer, a) bern(computer, a) computer.ram.memory[267] = a.m(ASM.JMP, 4) # reset instead of halt to compute next print("running") computer.clock.go()
def p(computer: Computer, a: Assembler): """ integer division: 42 / 6 """ computer.ram.memory[0] = a.m(ASM.LDA, 14) computer.ram.memory[1] = a.m(ASM.SUB, 15) computer.ram.memory[2] = a.m(ASM.JC, 6) # if subtraction didn't go below 0 computer.ram.memory[3] = a.m(ASM.LDA, 13) computer.ram.memory[4] = a.m(ASM.OUT, 0) computer.ram.memory[5] = a.m(ASM.HLT, 0) computer.ram.memory[6] = a.m(ASM.STA, 14) computer.ram.memory[7] = a.m(ASM.LDA, 13) computer.ram.memory[8] = a.m(ASM.ADD, 12) computer.ram.memory[9] = a.m(ASM.STA, 13) computer.ram.memory[10] = a.m(ASM.JMP, 0) computer.ram.memory[11] = a.m(ASM.NOP, 0) computer.ram.memory[12] = 1 # const computer.ram.memory[13] = 0 # count subtractions computer.ram.memory[14] = 42 # x = 42 computer.ram.memory[15] = 6 # y = 6
def p(computer: Computer, a: Assembler): """ Ben Eater's multiplication """ computer.ram.memory[0] = a.m(ASM.LDA, 14) computer.ram.memory[1] = a.m(ASM.SUB, 12) computer.ram.memory[2] = a.m(ASM.JC, 6) computer.ram.memory[3] = a.m(ASM.LDA, 13) computer.ram.memory[4] = a.m(ASM.OUT, 0) computer.ram.memory[5] = a.m(ASM.HLT, 0) computer.ram.memory[6] = a.m(ASM.STA, 14) computer.ram.memory[7] = a.m(ASM.LDA, 13) computer.ram.memory[8] = a.m(ASM.ADD, 15) computer.ram.memory[9] = a.m(ASM.STA, 13) computer.ram.memory[10] = a.m(ASM.JMP, 0) computer.ram.memory[11] = a.m(ASM.NOP, 0) computer.ram.memory[12] = 1 computer.ram.memory[13] = 0 # product = 0 computer.ram.memory[14] = 7 # x = 7 computer.ram.memory[15] = 6 # y = 6
def p(computer: Computer, a: Assembler): """ pseudo- bit shift right """ computer.ram.memory[0] = a.m(ASM.LDA, 9) computer.ram.memory[1] = a.m(ASM.LDA, 10) computer.ram.memory[2] = a.m(ASM.LDA, 11) computer.ram.memory[3] = a.m(ASM.LDA, 12) computer.ram.memory[4] = a.m(ASM.LDI, 8) computer.ram.memory[5] = a.m(ASM.LDI, 4) computer.ram.memory[6] = a.m(ASM.LDI, 2) computer.ram.memory[7] = a.m(ASM.LDI, 1) computer.ram.memory[8] = a.m(ASM.JMP, 0) computer.ram.memory[9] = 128 computer.ram.memory[10] = 64 computer.ram.memory[11] = 32 computer.ram.memory[12] = 16
def p(computer: Computer, a: Assembler): """ add fractions subroutine at 2100 """ # global utility constants bit_count = computer.bit_count computer.ram.memory[4000] = 1 << (bit_count - 1) # min signed computer.ram.memory[4001] = 1 computer.ram.memory[4002] = (2**bit_count) - 1 # -1 in two's complement add_fractions_subroutine = [ a.m(ASM.LDA, 2140), a.m(ASM.STA, 2147), a.m(ASM.LDA, 2142), a.m(ASM.STA, 2145), a.m(ASM.LDA, 2141), a.m(ASM.STA, 2148), a.m(ASM.LDA, 2143), a.m(ASM.STA, 2144), a.m(ASM.LDA, 2148), # address 2108 a.m(ASM.SUB, 2144), a.m(ASM.JZ, 2127), a.m(ASM.ADD, 4000), a.m(ASM.JC, 2120), a.m(ASM.LDA, 2144), a.m(ASM.ADD, 2143), a.m(ASM.STA, 2144), a.m(ASM.LDA, 2145), a.m(ASM.ADD, 2142), a.m(ASM.STA, 2145), a.m(ASM.JMP, 2108), a.m(ASM.LDA, 2148), # address 2120 a.m(ASM.ADD, 2141), a.m(ASM.STA, 2148), a.m(ASM.LDA, 2147), a.m(ASM.ADD, 2140), a.m(ASM.STA, 2147), a.m(ASM.JMP, 2108), a.m(ASM.LDA, 2147), # address 2127 a.m(ASM.ADD, 2145), a.m(ASM.STA, 2147), a.m(ASM.JI, 2146) ] """ parameters: 2140 an operand a numerator 2141 ad operand a denominator 2142 bn operand b numerator 2143 bd operand b denominator 2146 pc return location working variables: 2144 blcd 2145 bnm result locations: 2147 anm result numerator 2148 alcd result denominator """ address = 2100 for instruction in add_fractions_subroutine: computer.ram.memory[address] = instruction address += 1 # use the add fractions subroutine computer.ram.memory[0] = a.m(ASM.LDI, 1) computer.ram.memory[1] = a.m(ASM.STA, 2140) # a operand numer computer.ram.memory[2] = a.m(ASM.LDI, 4) computer.ram.memory[3] = a.m(ASM.STA, 2141) # a operand denom computer.ram.memory[4] = a.m(ASM.LDI, 7) computer.ram.memory[5] = a.m(ASM.STA, 2142) # b operand numer computer.ram.memory[6] = a.m(ASM.LDI, 12) computer.ram.memory[7] = a.m(ASM.STA, 2143) # b operand denom computer.ram.memory[8] = a.m(ASM.LDI, 11) computer.ram.memory[9] = a.m(ASM.STA, 2146) # return program counter computer.ram.memory[10] = a.m(ASM.JMP, 2100) # add fractions subroutine computer.ram.memory[11] = a.m(ASM.LDA, 2147) # result numer computer.ram.memory[12] = a.m(ASM.OUT, 0) computer.ram.memory[13] = a.m(ASM.LDA, 2148) # result denom computer.ram.memory[14] = a.m(ASM.OUT, 0) computer.ram.memory[15] = a.m(ASM.HLT, 0)
def p(computer: Computer, a: Assembler): """ divide subroutine at 2200 - requires multiply at 2000 """ # global utility constants bit_count = computer.bit_count computer.ram.memory[4000] = 1 << (bit_count - 1) # min signed computer.ram.memory[4001] = 1 computer.ram.memory[4002] = (2**bit_count) - 1 # -1 in two's complement divide_subroutine = [ a.m(ASM.LDI, 1), a.m(ASM.STA, 2254), a.m(ASM.LDA, 2250), a.m(ASM.ADD, 4000), a.m(ASM.JC, 2206), a.m(ASM.JMP, 2211), a.m(ASM.LDA, 4002), # address 2206 a.m(ASM.STA, 2254), a.m(ASM.LDI, 0), a.m(ASM.SUB, 2250), a.m(ASM.STA, 2250), a.m(ASM.LDI, 0), # address 2211 a.m(ASM.STA, 2255), a.m(ASM.LDA, 2250), # address 2213 a.m(ASM.SUB, 2251), a.m(ASM.ADD, 4000), a.m(ASM.JC, 2224), a.m(ASM.LDA, 2250), a.m(ASM.SUB, 2251), a.m(ASM.STA, 2250), a.m(ASM.LDA, 2255), a.m(ASM.ADD, 4001), a.m(ASM.STA, 2255), a.m(ASM.JMP, 2213), a.m(ASM.LDA, 2254), # address 2224 a.m(ASM.STA, 2080), a.m(ASM.LDA, 2255), a.m(ASM.STA, 2081), a.m(ASM.LDI, 2231), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 2231 a.m(ASM.STA, 2253), a.m(ASM.JI, 2252) ] """ integer division parameters: 2250 a 2251 b must be positive - divide by 0 makes infinite loop 2252 pcreturnlocation output: 2253 result working variables: 2254 a_sign 2255 count """ address = 2200 for instruction in divide_subroutine: computer.ram.memory[address] = instruction address += 1 # use the divide subroutine computer.ram.memory[0] = a.m(ASM.LDI, 1764) computer.ram.memory[1] = a.m(ASM.STA, 2250) # a operand computer.ram.memory[2] = a.m(ASM.LDI, 42) computer.ram.memory[3] = a.m(ASM.STA, 2251) # b operand computer.ram.memory[4] = a.m(ASM.LDI, 7) computer.ram.memory[5] = a.m(ASM.STA, 2252) # return program counter computer.ram.memory[6] = a.m(ASM.JMP, 2200) # divide subroutine computer.ram.memory[7] = a.m(ASM.LDA, 2253) # result computer.ram.memory[8] = a.m(ASM.OUT, 0) computer.ram.memory[9] = a.m(ASM.HLT, 0)
def p(computer: Computer, a: Assembler): """ gcd subroutine at 2300 """ # global utility constants bit_count = computer.bit_count computer.ram.memory[4000] = 1 << (bit_count - 1) # min signed computer.ram.memory[4001] = 1 computer.ram.memory[4002] = (2**bit_count) - 1 # -1 in two's complement gcd_subroutine = [ a.m(ASM.LDA, 2350), a.m(ASM.SUB, 2351), a.m(ASM.JZ, 2313), a.m(ASM.ADD, 4000), a.m(ASM.JC, 2309), a.m(ASM.LDA, 2350), a.m(ASM.SUB, 2351), a.m(ASM.STA, 2350), a.m(ASM.JMP, 2300), a.m(ASM.LDA, 2351), # address 2309 a.m(ASM.SUB, 2350), a.m(ASM.STA, 2351), a.m(ASM.JMP, 2300), a.m(ASM.JI, 2352) # address 2313 ] """ parameters: 2350 a must be positive 2351 b must be positive 2352 pc return location output: 2350 result """ address = 2300 for instruction in gcd_subroutine: computer.ram.memory[address] = instruction address += 1 # use the gcd subroutine computer.ram.memory[0] = a.m(ASM.LDI, 210) computer.ram.memory[1] = a.m(ASM.STA, 2350) # a operand computer.ram.memory[2] = a.m(ASM.LDI, 546) computer.ram.memory[3] = a.m(ASM.STA, 2351) # b operand computer.ram.memory[4] = a.m(ASM.LDI, 7) computer.ram.memory[5] = a.m(ASM.STA, 2352) # return program counter computer.ram.memory[6] = a.m(ASM.JMP, 2300) # gcd subroutine computer.ram.memory[7] = a.m(ASM.LDA, 2350) # result computer.ram.memory[8] = a.m(ASM.OUT, 0) computer.ram.memory[9] = a.m(ASM.HLT, 0)
def p(computer: Computer, a: Assembler): """ reduce fraction subroutine at 2400 - requires divide and gcd """ # global utility constants bit_count = computer.bit_count computer.ram.memory[4000] = 1 << (bit_count - 1) # min signed computer.ram.memory[4001] = 1 computer.ram.memory[4002] = (2**bit_count) - 1 # -1 in two's complement reduce_subroutine = [ a.m(ASM.LDA, 2451), a.m(ASM.ADD, 4000), a.m(ASM.JC, 2404), a.m(ASM.JMP, 2410), a.m(ASM.LDI, 0), # address 2404 a.m(ASM.SUB, 2450), a.m(ASM.STA, 2450), a.m(ASM.LDI, 0), a.m(ASM.SUB, 2451), a.m(ASM.STA, 2451), a.m(ASM.LDA, 2450), # address 2410 a.m(ASM.STA, 2453), a.m(ASM.ADD, 4000), a.m(ASM.JC, 2415), a.m(ASM.JMP, 2418), a.m(ASM.LDI, 0), # address 2415 a.m(ASM.SUB, 2453), a.m(ASM.STA, 2453), a.m(ASM.LDA, 2453), # address 2418 a.m(ASM.STA, 2350), a.m(ASM.LDA, 2451), a.m(ASM.STA, 2351), a.m(ASM.LDI, 2425), a.m(ASM.STA, 2352), a.m(ASM.JMP, 2300), a.m(ASM.LDA, 2350), # address 2425 a.m(ASM.STA, 2453), a.m(ASM.LDA, 2450), a.m(ASM.STA, 2250), a.m(ASM.LDA, 2453), a.m(ASM.STA, 2251), a.m(ASM.LDI, 2434), a.m(ASM.STA, 2252), a.m(ASM.JMP, 2200), a.m(ASM.LDA, 2253), # address 2434 a.m(ASM.STA, 2450), a.m(ASM.LDA, 2451), a.m(ASM.STA, 2250), a.m(ASM.LDA, 2453), a.m(ASM.STA, 2251), a.m(ASM.LDI, 2443), a.m(ASM.STA, 2252), a.m(ASM.JMP, 2200), a.m(ASM.LDA, 2253), # address 2443 a.m(ASM.STA, 2451), a.m(ASM.JI, 2452) ] """ parameters: 2450 n numerator 2451 d denominator 2452 pc return location working variables: 2453 n_positive and divisor result locations: 2450 n result numerator 2451 d result denominator """ address = 2400 for instruction in reduce_subroutine: computer.ram.memory[address] = instruction address += 1 # use the reduce subroutine computer.ram.memory[0] = a.m(ASM.LDI, 10) computer.ram.memory[1] = a.m(ASM.STA, 2450) # n computer.ram.memory[2] = a.m(ASM.LDI, 12) computer.ram.memory[3] = a.m(ASM.STA, 2451) # d computer.ram.memory[4] = a.m(ASM.LDI, 7) computer.ram.memory[5] = a.m(ASM.STA, 2452) # return program counter computer.ram.memory[6] = a.m(ASM.JMP, 2400) # gcd subroutine computer.ram.memory[7] = a.m(ASM.LDA, 2450) # result computer.ram.memory[8] = a.m(ASM.OUT, 0) computer.ram.memory[9] = a.m(ASM.LDA, 2451) # result computer.ram.memory[10] = a.m(ASM.OUT, 0) computer.ram.memory[11] = a.m(ASM.HLT, 0)
def p(computer: Computer, a: Assembler): """ multiply subroutine at 2000 faster for big numbers slower for small numbers """ # global utility constants bit_count = computer.bit_count computer.ram.memory[4000] = 1 << (bit_count - 1) # min signed computer.ram.memory[4001] = 1 computer.ram.memory[4002] = (2**bit_count) - 1 # -1 in two's complement multiply_subroutine = [ a.m(ASM.LDA, 2080), a.m(ASM.ADD, 4000), a.m(ASM.JC, 2004), a.m(ASM.JMP, 2010), a.m(ASM.LDI, 0), a.m(ASM.SUB, 2080), a.m(ASM.STA, 2080), a.m(ASM.LDI, 0), a.m(ASM.SUB, 2081), a.m(ASM.STA, 2081), a.m(ASM.LDI, 0), a.m(ASM.STA, 2083), a.m(ASM.LDI, 0), a.m(ASM.ADD, 2080), a.m(ASM.JZ, 2076), a.m(ASM.LDI, 1), a.m(ASM.STA, 2086), a.m(ASM.STA, 2088), a.m(ASM.LDA, 2081), a.m(ASM.STA, 2083), a.m(ASM.SIN, 2084), a.m(ASM.LDI, 2), a.m(ASM.STA, 2089), a.m(ASM.LDA, 2080), a.m(ASM.SUB, 2089), a.m(ASM.JC, 2027), a.m(ASM.JMP, 2045), a.m(ASM.LDA, 2083), a.m(ASM.ADD, 2083), a.m(ASM.STA, 2083), a.m(ASM.LDA, 2088), a.m(ASM.ADD, 2088), a.m(ASM.STA, 2088), a.m(ASM.LDA, 2086), a.m(ASM.ADD, 2084), a.m(ASM.STA, 2087), a.m(ASM.LDA, 2083), a.m(ASM.SIN, 2087), a.m(ASM.LDA, 2088), a.m(ASM.ADD, 2088), a.m(ASM.STA, 2089), a.m(ASM.LDI, 1), a.m(ASM.ADD, 2086), a.m(ASM.STA, 2086), a.m(ASM.JMP, 2023), a.m(ASM.LDA, 2086), a.m(ASM.SUB, 2090), a.m(ASM.STA, 2086), a.m(ASM.ADD, 4000), a.m(ASM.JC, 2076), a.m(ASM.LDA, 2086), a.m(ASM.ADD, 2085), a.m(ASM.STA, 2087), a.m(ASM.LIN, 2087), a.m(ASM.ADD, 2088), a.m(ASM.STA, 2087), a.m(ASM.LDA, 2080), a.m(ASM.SUB, 2087), a.m(ASM.JC, 2060), a.m(ASM.JMP, 2072), a.m(ASM.LDA, 2086), a.m(ASM.ADD, 2084), a.m(ASM.STA, 2087), a.m(ASM.LIN, 2087), a.m(ASM.ADD, 2083), a.m(ASM.STA, 2083), a.m(ASM.LDA, 2086), a.m(ASM.ADD, 2085), a.m(ASM.STA, 2087), a.m(ASM.LIN, 2087), a.m(ASM.ADD, 2088), a.m(ASM.STA, 2088), a.m(ASM.LDA, 2086), a.m(ASM.SUB, 4001), a.m(ASM.STA, 2086), a.m(ASM.JMP, 2048), a.m(ASM.JI, 2082) ] """ 2080 a operand 2081 b operand 2082 pc return location 2083 result 2084 powers (pointer) 2085 addition counts (pointer) 2086 cache index 2087 pointer (temp) 2088 additions done 2089 double 2090 2 const 400 powers 500-564 addition counts """ # place those constants ^ computer.ram.memory[2084] = 400 computer.ram.memory[2085] = 500 computer.ram.memory[2090] = 2 for i in range(500, 565): computer.ram.memory[i] = 2**(i - 500) address = 2000 for instruction in multiply_subroutine: computer.ram.memory[address] = instruction address += 1 # use the multiply subroutine computer.ram.memory[0] = a.m(ASM.LDI, 7) computer.ram.memory[1] = a.m(ASM.STA, 2080) # a operand computer.ram.memory[2] = a.m(ASM.LDI, 6) computer.ram.memory[3] = a.m(ASM.STA, 2081) # b operand computer.ram.memory[4] = a.m(ASM.LDI, 7) computer.ram.memory[5] = a.m(ASM.STA, 2082) # return program counter computer.ram.memory[6] = a.m(ASM.JMP, 2000) # multiply subroutine computer.ram.memory[7] = a.m(ASM.LDA, 2083) # result computer.ram.memory[8] = a.m(ASM.OUT, 0) computer.ram.memory[9] = a.m(ASM.HLT, 0)
def p(computer: Computer, a: Assembler): """ Ada Lovelace's Bernoulli number calculator """ bernoulli = [ a.m(ASM.LDI, 1), a.m(ASM.STA, 1010), a.m(ASM.LDI, 2), a.m(ASM.STA, 1020), a.m(ASM.LDI, 0), a.m(ASM.STA, 1070), a.m(ASM.STA, 1130), # op1 v4,v5,v6 = v2 * v3 a.m(ASM.LDA, 1020), a.m(ASM.STA, 2080), a.m(ASM.LDA, 1030), a.m(ASM.STA, 2081), a.m(ASM.LDI, 14), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 14 a.m(ASM.STA, 1040), a.m(ASM.STA, 1050), a.m(ASM.STA, 1060), # op2 v4 = v4 - v1 a.m(ASM.LDA, 1040), a.m(ASM.SUB, 1010), a.m(ASM.STA, 1040), # op3 v5 = v5 + v1 a.m(ASM.LDA, 1050), a.m(ASM.ADD, 1010), a.m(ASM.STA, 1050), # op4 v11f = v4 / v5 a.m(ASM.STA, 1111), a.m(ASM.LDA, 1040), a.m(ASM.STA, 1110), # op5 v11 = v11 / v2 -> v11d = multiply(v11d, v2i) a.m(ASM.LDA, 1111), a.m(ASM.STA, 2081), # better when a is lower number a.m(ASM.LDA, 1020), a.m(ASM.STA, 2080), a.m(ASM.LDI, 34), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 34 a.m(ASM.STA, 1111), # op6 v13 = v13 - v11 # v13n = v13n - v11n; v13d = v11d # v13n, v13d = reduce(v13n, v13d) # TODO: remove this reduce, there's no way this isn't already reduced a.m(ASM.LDA, 1130), a.m(ASM.SUB, 1110), a.m(ASM.STA, 2450), # store in reduce parameter a.m(ASM.LDA, 1111), a.m(ASM.STA, 2451), a.m(ASM.LDI, 44), a.m(ASM.STA, 2452), a.m(ASM.JMP, 2400), a.m(ASM.LDA, 2450), # address 44 a.m(ASM.STA, 1130), a.m(ASM.LDA, 2451), a.m(ASM.STA, 1131), # op7 v10i = v3i - v1i a.m(ASM.LDA, 1030), a.m(ASM.SUB, 1010), a.m(ASM.STA, 1100), # on first run, v10 is now 1 # op8 v7i = v2i + v7i a.m(ASM.LDA, 1020), a.m(ASM.ADD, 1070), a.m(ASM.STA, 1070), # op9 v11 = v6 / v7 ~ v11n = v6i; v11d = v7i a.m(ASM.STA, 1111), a.m(ASM.LDA, 1060), a.m(ASM.STA, 1110), # op10 v12 = v20[1] * v11 # v12n = multiply(v20n[1], v11n) # v12d = multiply(v20d[1], v11d) a.m(ASM.LDA, 1210), a.m(ASM.STA, 2080), a.m(ASM.LDA, 1110), a.m(ASM.STA, 2081), a.m(ASM.LDI, 64), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 64 a.m(ASM.STA, 1120), a.m(ASM.LDA, 1211), a.m(ASM.STA, 2080), a.m(ASM.LDA, 1111), a.m(ASM.STA, 2081), a.m(ASM.LDI, 73), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 73 a.m(ASM.STA, 1121), # op11 v13 = v12 + v13 # v13n, v13d = add_f(v12n, v12d, v13n, v13d) # v13n, v13d = red(v13n, v13d) a.m(ASM.LDA, 1120), a.m(ASM.STA, 2140), a.m(ASM.LDA, 1121), a.m(ASM.STA, 2141), a.m(ASM.LDA, 1130), a.m(ASM.STA, 2142), a.m(ASM.LDA, 1131), a.m(ASM.STA, 2143), a.m(ASM.LDI, 86), a.m(ASM.STA, 2146), a.m(ASM.JMP, 2100), a.m(ASM.LDA, 2147), # address 86 - from output of add a.m(ASM.STA, 2450), # to input of reduce a.m(ASM.LDA, 2148), a.m(ASM.STA, 2451), a.m(ASM.LDI, 93), a.m(ASM.STA, 2452), a.m(ASM.JMP, 2400), a.m(ASM.LDA, 2450), # address 93 a.m(ASM.STA, 1130), a.m(ASM.LDA, 2451), a.m(ASM.STA, 1131), # op12 v10i = v10i - v1i a.m(ASM.LDA, 1100), a.m(ASM.SUB, 1010), a.m(ASM.STA, 1100), # first run v10 is now 0 # while v10i > 0 # both here and before I jump back here, # v10 in reg A, zero flag set if 0 a.m(ASM.JZ, 245), # address 100 # op13 v6i = v6i - v1i a.m(ASM.LDA, 1060), a.m(ASM.SUB, 1010), a.m(ASM.STA, 1060), # op14 v7i = v1i + v7i a.m(ASM.LDA, 1010), a.m(ASM.ADD, 1070), a.m(ASM.STA, 1070), # op15 v8 = v6 / v7 # v8n = v6i # v8d = v7i # v8n, v8d = reduce(v8n, v8d) a.m(ASM.STA, 2451), # v7 already in mem, to reduce param a.m(ASM.LDA, 1060), a.m(ASM.STA, 2450), a.m(ASM.LDI, 113), a.m(ASM.STA, 2452), a.m(ASM.JMP, 2400), a.m(ASM.LDA, 2451), # address 113 a.m(ASM.STA, 1081), a.m(ASM.LDA, 2450), a.m(ASM.STA, 1080), # op16 v11 = v8 * v11 ~ mult n; mult d; then reduce a.m(ASM.STA, 2080), # v8n already in reg A a.m(ASM.LDA, 1110), a.m(ASM.STA, 2081), a.m(ASM.LDI, 123), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 123 - numer to be reduced a.m(ASM.STA, 2450), # leave that there for a bit a.m(ASM.LDA, 1081), a.m(ASM.STA, 2080), a.m(ASM.LDA, 1111), a.m(ASM.STA, 2081), a.m(ASM.LDI, 132), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 132 - denom a.m(ASM.STA, 2451), # to be reduced a.m(ASM.LDI, 137), a.m(ASM.STA, 2452), a.m(ASM.JMP, 2400), a.m(ASM.LDA, 2450), # address 137 a.m(ASM.STA, 1110), a.m(ASM.LDA, 2451), a.m(ASM.STA, 1111), # op17 v6i = v6i - v1i a.m(ASM.LDA, 1060), a.m(ASM.SUB, 1010), a.m(ASM.STA, 1060), # op18 v7i = v1i + v7i a.m(ASM.LDA, 1010), a.m(ASM.ADD, 1070), a.m(ASM.STA, 1070), # op19 v9 = v6i / v7i ~ reduce then put in v9 a.m(ASM.STA, 2451), # v7 already in reg A a.m(ASM.LDA, 1060), a.m(ASM.STA, 2450), a.m(ASM.LDI, 153), a.m(ASM.STA, 2452), a.m(ASM.JMP, 2400), a.m(ASM.LDA, 2451), # address 153 - denom first a.m(ASM.STA, 1091), a.m(ASM.LDA, 2450), a.m(ASM.STA, 1090), # op20 v11 = v9 * v11 # mult n; mult d; then reduce ~ copy paste from op16 a.m(ASM.STA, 2080), # v9n already in reg A a.m(ASM.LDA, 1110), a.m(ASM.STA, 2081), a.m(ASM.LDI, 163), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 163 - numer to be reduced a.m(ASM.STA, 2450), # leave that there for a bit a.m(ASM.LDA, 1091), a.m(ASM.STA, 2080), a.m(ASM.LDA, 1111), a.m(ASM.STA, 2081), a.m(ASM.LDI, 172), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 172 - denom a.m(ASM.STA, 2451), # to be reduced a.m(ASM.LDI, 177), a.m(ASM.STA, 2452), a.m(ASM.JMP, 2400), a.m(ASM.LDA, 2450), # address 177 a.m(ASM.STA, 1110), a.m(ASM.LDA, 2451), a.m(ASM.STA, 1111), # op21 v12 = v20[v3i - v10i] * v11 # mult(v20n[v3i - v10i], v11n); then d; then reduce a.m(ASM.NOP, 0), # for safety - wiggle room for fixing mistakes # about to make address for v20n[v3i - v10i] a.m(ASM.LDA, 1030), # v3i a.m(ASM.SUB, 1100), # - v10i a.m(ASM.STA, 2080), a.m(ASM.LDI, 10), a.m(ASM.STA, 2081), a.m(ASM.LDI, 190), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDI, 1200), # address 190 a.m(ASM.ADD, 2083), # 1200 + (v3i - v10i) * 10 a.m(ASM.STA, 900), # address of v20n[v3i - v10i] a.m(ASM.ADD, 1010), a.m(ASM.STA, 901), # address of v20d[v3i - v10i] a.m(ASM.LIN, 900), a.m(ASM.STA, 2080), a.m(ASM.LDA, 1110), a.m(ASM.STA, 2081), a.m(ASM.LDI, 202), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 202 - numer to be reduced a.m(ASM.STA, 2450), # leave that there for a bit a.m(ASM.LIN, 901), a.m(ASM.STA, 2080), a.m(ASM.LDA, 1111), a.m(ASM.STA, 2081), a.m(ASM.LDI, 211), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDA, 2083), # address 211 - denom to be reduced a.m(ASM.STA, 2451), a.m(ASM.LDI, 216), a.m(ASM.STA, 2452), a.m(ASM.JMP, 2400), a.m(ASM.LDA, 2451), # address 216 - d first to have n in register a.m(ASM.STA, 1121), a.m(ASM.LDA, 2450), a.m(ASM.STA, 1120), # op22 v13 = v12 + v13 ~ add fractions and reduce a.m(ASM.STA, 2140), # v12n already in register a.m(ASM.LDA, 1121), a.m(ASM.STA, 2141), a.m(ASM.LDA, 1130), a.m(ASM.STA, 2142), a.m(ASM.LDA, 1131), a.m(ASM.STA, 2143), a.m(ASM.LDI, 230), a.m(ASM.STA, 2146), a.m(ASM.JMP, 2100), a.m(ASM.LDA, 2147), # address 230 a.m(ASM.STA, 2450), a.m(ASM.LDA, 2148), a.m(ASM.STA, 2451), a.m(ASM.LDI, 237), a.m(ASM.STA, 2452), a.m(ASM.JMP, 2400), a.m(ASM.LDA, 2450), # address 237 a.m(ASM.STA, 1130), a.m(ASM.LDA, 2451), a.m(ASM.STA, 1131), # op23 v10i = v10i - v1i a.m(ASM.LDA, 1100), a.m(ASM.SUB, 1010), # this will set zero flag if v10 == 0 a.m(ASM.STA, 1100), a.m(ASM.JMP, 100), # op24 v20[v3i] = v20[v3i] - v13 # v20n[v3i] = v20n[v3i] - v13n; v20d[v3i] = v13d a.m(ASM.LDA, 1030), # address 245 a.m(ASM.STA, 2080), a.m(ASM.LDI, 10), a.m(ASM.STA, 2081), a.m(ASM.LDI, 252), a.m(ASM.STA, 2082), a.m(ASM.JMP, 2000), a.m(ASM.LDI, 1200), # address 252 a.m(ASM.ADD, 2083), a.m(ASM.STA, 900), # v20n[v3i] a.m(ASM.ADD, 1010), a.m(ASM.STA, 901), # v20d[v3i] a.m(ASM.LIN, 900), a.m(ASM.SUB, 1130), a.m(ASM.OUT, 0), # numerator of bern a.m(ASM.SIN, 900), a.m(ASM.LDA, 1131), a.m(ASM.SIN, 901), a.m(ASM.OUT, 0), # denominator of bern # op25 v3i = v1i + v3i a.m(ASM.LDA, 1010), a.m(ASM.ADD, 1030), a.m(ASM.STA, 1030), a.m(ASM.HLT, 0) # [267] or JMP, 0 (or JMP, 4 don't need 0-3) ] address = 0 for instruction in bernoulli: computer.ram.memory[address] = instruction address += 1 # data initializations: computer.ram.memory[1030] = 2 # will increment with each run of the program # this is which bernoulli number is being calculated computer.ram.memory[1210] = 1 # the numerator of the first bern number computer.ram.memory[1211] = 6 # the denominator of the first bern number # all of the v20n need to be initialized to 0 # (1220, 1230, 1240, ...) as far as we want to go for i in range(1220, 2000, 10): computer.ram.memory[i] = 0