调用指令破坏堆栈

call instruction destroying stack

我正在用汇编代码编写一个基本程序,旨在打印数字 1-10。我的目标是在堆栈上分配两个变量,一个是计数器,另一个是最终目的地。我想比较它们,打印它们,增加计数器。

我遇到的问题是,当我调用函数 printf 时,returns 它正在清除堆栈。我没有做任何类型的堆栈溢出或任何事情。我不明白为什么调用 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

您只能在叶函数(不调用其他函数)中使用红色区域。很明显,如果你发出一个 call ,它本身已经把一个 return 地址放在堆栈上,然后被调用的函数也可以使用堆栈,就像你被允许使用它一样。

仔细一看,我认为您只是搞砸了基址寄存器,您想使用 rbp 而不是 rsp 进行寻址,因为您在堆栈帧中分配了 space。 space 低于 rbp 但高于 rsp

PS:rbx是一个被调用者保存的寄存器,你应该保留它的值。 PS #2:根据调用约定,可变参数函数期望 al 中使用的向量寄存器数量的上限。由于 printf 是这样一个函数,因此在调用它之前应将 al 归零。