我目前正在64位机器上编写程序集NASM来打印给定输入的阶乘,然后返回输入。该程序可以正常打印出阶乘值,但返回值不会返回输入。是的,代码很糟糕,我不希望你简单地改写整个事情。 (这是我的作业。)我只是想让某人解释为什么我的返回寄存器(rax)不保留它从一开始就具有的值。
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
输出:
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)
我希望它返回我的输入,在这种情况下将是4.
任何见解都将受到赞赏。
答案 0 :(得分:2)
推送和弹出的顺序是错误的。
推动:
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
流行音乐:
pop rdi
pop rcx
pop rax ;restore trashed variables
...
pop rax
pop rcx
pop rdi ;clear stack
ret
最后rax
和rdi
被交换,哎呀。
答案 1 :(得分:1)
问题是,堆栈中的位置没有名称或标识符。你必须以相同的顺序推送和弹出。当你说pop rax
时,处理器不会说“push rax
最后一个条目在哪里?”,而是说“最新推送的内容在哪里?”。所以你的堆栈看起来像这样(假设rax 1,rbx 2,rcx 3):
0x0001 #push rax
0x0002 #push rbx
0x0003 #push rcx
|
\----- This is the value retrieved by pop rax
请遵循以下规则:除非您明确尝试切换值,否则请务必按照弹出它们的顺序推送内容(最好使用xchg
完成)。
注意:以错误的顺序执行操作可用于设置rflags
寄存器之类的值:
push 0x0000000000000000 ;New value for rflags
popf ;Pop it into rflags