0

我目前正在 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。

任何见解将不胜感激。

4

2 回答 2

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

最后raxrdi被交换,哎呀。

于 2012-09-29T02:05:20.927 回答
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
于 2012-09-29T02:11:40.743 回答