我正在用汇编代码编写一个基本程序,用于打印数字1-10。我的目标是在堆栈上分配两个变量,一个是计数器,另一个是最终目的地。我想比较它们,打印它们,增加计数器。
我遇到的问题是,当我调用函数printf时,当它返回时它正在擦除堆栈干净。我没有做任何堆栈溢出或任何东西。我不明白为什么调用printf
会破坏$rsp-0x10
和$rsp-0x20
的堆栈
global main
extern printf
section .text
main:
push rbp
mov rbp, rsp
sub rsp, 0x20
mov qword [rsp-0x10], 0x0
mov qword [rsp-0x20], 0xA
looper:
mov rax, [rsp-0x10] ; load the value on the stack (var 1) into the rax register
inc rax ; increment the register
mov qword [rsp-0x10],rax ; copy the new value back to the stack
mov rdi, message ; load the address of the message string
mov rsi, rax ; load the second parameter which is the value of the counter var
call printf ; call printf. After this instruction the values at $rsp-0x10 and $rsp-0x20 are zero
mov rax, [rsp-0x10] ; ideally I would load the vars back up into rax and rbx
mov rbx, [rsp-0x20]
cmp rax, rbx ; then compare the variables and loop if they are not equal
jne looper
done:
leave
ret
section .data
message: db “%d”, 10, 0
答案 0 :(得分:4)
您只能在叶子函数中使用红色区域(不调用其他函数)。显然,如果你发出一个call
本身已经在堆栈上放了一个返回地址,那么被调用的函数也可以使用堆栈,就像你被允许使用它一样。
仔细观察我认为你只是弄乱了基址寄存器,你想使用rbp
而不是rsp
进行寻址,因为你在堆栈帧中分配了空间。该空格低于rbp
但高于rsp
。
PS:rbx
是被调用者保存的寄存器,您应该保留其值。
PS#2:根据调用约定,varargs函数期望al
中使用的向量寄存器数量的上限。由于printf
就是这样一个函数,因此在调用它之前应该将al
归零。