为什么 x86 汇编函数调用第一个参数是 rbp - 4 而不是 rbp + 4

问题描述 投票:0回答:2
int square(int num, int i2) {
    return num * num;
}
square(int, int):
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     DWORD PTR [rbp-8], esi
        mov     eax, DWORD PTR [rbp-4]
        imul    eax, eax
        pop     rbp
        ret

我们知道堆栈是从高地址向低地址增长的,我看到书上当函数调用发生时,堆栈可能像函数参数,然后返回地址,然后是旧的ebp。但为什么 rbp - 4 是第一个参数地址,而不是 rbp + 4,因为参数保留在高地址

你能为我解释一下吗?

c assembly x86 x86-64
2个回答
0
投票

寄存器

rbp
存储堆栈的当前地址。正如你自己写的那样

我们知道栈是从高地址向低地址增长的

因此,要为函数的局部变量参数分配内存,寄存器

rbp
会按参数类型的大小递减

    push    rbp
    mov     rbp, rsp
    mov     DWORD PTR [rbp-4], edi
    mov     DWORD PTR [rbp-8], esi

rbp + 4
寻址不属于该函数的调用者的内存。可以看出,参数通过存储在函数参数(局部变量)中的寄存器
edi
esi
传递给函数。


0
投票

64 位 ABI - 前 6 个参数在 寄存器 中传递,而不是在堆栈上。

因此要查看如何从堆栈中获取参数,您需要有更多参数:

int goo(int n1, int n2, int n3, int n4, int n5, int n6, int n7) {
    return n1 + n2 + n3 + n4 + n5 + n6 +n7;
}

和代码:

        add     edi, esi
        add     edi, edx
        add     edi, ecx
        add     edi, r8d
        lea     eax, [rdi+r9]
        add     eax, DWORD PTR [rsp+8]
        ret

如您所见,参数

n7
正在从堆栈中获取
DWORD PTR [rsp+8]

在 32 位系统上:

goo:
        mov     eax, DWORD PTR [esp+8]
        add     eax, DWORD PTR [esp+4]
        add     eax, DWORD PTR [esp+12]
        add     eax, DWORD PTR [esp+16]
        add     eax, DWORD PTR [esp+20]
        add     eax, DWORD PTR [esp+24]
        add     eax, DWORD PTR [esp+28]
        ret

所有参数均从堆栈中获取。

为什么 x86 汇编函数调用第一个参数是 rbp - 4 而不是 rbp + 4

因为你编译它时没有优化,并且编译器已经为寄存器中传递的那些参数提供了自动存储。

针对 x86-64 编译的相同代码,未进行优化:

goo:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     DWORD PTR [rbp-8], esi
        mov     DWORD PTR [rbp-12], edx
        mov     DWORD PTR [rbp-16], ecx
        mov     DWORD PTR [rbp-20], r8d
        mov     DWORD PTR [rbp-24], r9d
        mov     edx, DWORD PTR [rbp-4]
        mov     eax, DWORD PTR [rbp-8]
        add     edx, eax
        mov     eax, DWORD PTR [rbp-12]
        add     edx, eax
        mov     eax, DWORD PTR [rbp-16]
        add     edx, eax
        mov     eax, DWORD PTR [rbp-20]
        add     edx, eax
        mov     eax, DWORD PTR [rbp-24]
        add     edx, eax
        mov     eax, DWORD PTR [rbp+16]
        add     eax, edx
        pop     rbp
        ret
© www.soinside.com 2019 - 2024. All rights reserved.