I'm currently writing an assembly NASM on a 64 bit machine to print the factorial of a given input, and then return the input. The program works correctly for printing out the factorial values, but the return value is not returning the input. Yes, the code is horrible, and I don't want you to simply rewrite the whole thing. (This is my homework.) I just want someone to explain why my return register (rax) is NOT preserving the value it had from the start.
extern read_input
extern print_int
call read_input
push rax ;save n
mov rcx, 1 ;counter
push rcx ;save counter
push rdi ;save print int
jmp test
print:
pop rdi
imul rdi, rcx ;multiply by current counter
push rdi ;save our multiplication factor
call print_int
pop rdi
pop rcx
pop rax ;restore trashed variables
add rcx, 1 ;increment counter by 1
push rax ;push stuff back on stack
push rcx
push rdi
jmp test
test:
cmp rcx, rax
jle print
pop rax
pop rcx
pop rdi ;clear stack
ret
Output:
Please enter an input value:
read_input> Returning 4 (0x4)
Printing integer 1 (0x1)
Printing integer 2 (0x2)
Printing integer 6 (0x6)
Printing integer 24 (0x18)
Program complete. Return 24 (0x18)
I want it to return my input, which in this case would be 4.
Any insight would be appreciated.
The order of the pushes and pops is wrong.
The pushes:
push rax ;save n
mov rcx, 1 ;counter
push rcx ;save counter
push rdi ;save print int
...
push rax ;push stuff back on stack
push rcx
push rdi
The pops:
pop rdi
pop rcx
pop rax ;restore trashed variables
...
pop rax
pop rcx
pop rdi ;clear stack
ret
At the end rax
and rdi
are swapped, oops.