调用指令销毁堆栈

时间:2018-01-12 17:30:00

标签: assembly stack nasm x86-64 cpu-registers

我正在用汇编代码编写一个基本程序,用于打印数字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

1 个答案:

答案 0 :(得分:4)

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

仔细观察我认为你只是弄乱了基址寄存器,你想使用rbp而不是rsp进行寻址,因为你在堆栈帧中分配了空间。该空格低于rbp但高于rsp

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