jmp main # takes ax: address to store result in # takes bx: first number to multiply # takes cx: second number to multiply # preserves only ax and bx multiply: movi 0x0 dx multiply_loop: testi 0x0 cx je multiply_done add bx dx subi 0x1 cx jmp multiply_loop multiply_done: sea ax dx ret # takes ax: address to store result in # takes bx: number to calculate the factorial of # preserves ax, dx (doesn't use it) factorial: push ax movi 0x1 cx factorial_loop: testi 0x1 bx je factorial_done mov sp ax addi 0x1 sp call multiply pop cx subi 0x1 bx jmp factorial_loop factorial_done: pop ax sea ax cx ret # takes ax: address to store result in # takes bx: number to calculate the factorial of # preserves ax, dx (doesn't use it) factorial_recursive: push ax movi 0x1 cx testi 0x1 bx je fac_rec_end push bx mov sp ax addi 0x1 sp subi 0x1 bx call factorial_recursive pop cx pop bx # bx = n # cx = f(n-1) mov sp ax addi 0x1 sp call multiply pop cx # cx = n*f(n-1) fac_rec_end: pop ax sea ax cx ret # ax -> pointer to steps accumulator, expects that *ax is initialized to zero # bx -> input number hailstone: testi 0x1 bx jne hailstone_cont ret hailstone_cont: mov bx cx andi 0x1 cx testi 0x0 cx je hailstone_even # was odd # preserve ax, cx push ax push cx # put result pointer in ax mov sp ax pushi 0x0 movi 0x3 cx call multiply # pop result pop bx # finish preserve ax, cx pop cx pop ax addi 0x1 bx jmp hailstone_handled hailstone_even: # was even rsi 0x1 bx # right shift by one bit, really divide by two hailstone_handled: # add 1 to the step counter lea ax cx addi 0x1 cx sea ax cx #call hailstone #ret # tail call recursion bitch jmp hailstone # ax -> pointer to where to store the result # bx -> input number # cx -> accumulator, expected to be set to 1 on the first call factorial_tcr: testi 0x1 bx jne factorial_tcr_cont sea ax cx ret factorial_tcr_cont: # multiply bx and cx, store result in cx # first preserve ax, bx push ax push bx mov sp ax pushi 0x0 call multiply # pop result pop cx # finish preserve pop bx pop ax subi 0x1 bx # tail call recursion jmp factorial_tcr main: # make space on the stack mov sp ax addi 0x1 sp # put 4 on bx and call factorial movi 0x4 bx call factorial # make more space on the stack mov sp ax addi 0x1 sp # put 5 on bx and call factorial_recursive movi 0x5 bx call factorial_recursive # make more space on the stack mov sp ax addi 0x1 sp # put 6 on bx and 1 on cx and call factorial_tcr movi 0x6 bx movi 0x1 cx call factorial_tcr # make even more space on the stack mov sp ax # the steps counter expects to be started at zero pushi 0x0 # 73 decimal movi 0x49 bx call hailstone # take the number of steps to hailstone 73 (should be 115) and puts it on ax # takes 6! (calculated using tail call recursion) and puts it on bx (should be 720) # takes 5! calculated using regular recursion and puts it on cx (should be 120) # takes 4! calculated iteratively and puts it on dx (should be 24) pop ax pop bx pop cx pop dx