函数的汇编

默认分类 · 2024-04-28 · 38 人浏览

首先我们来看这样一个函数

int test(int i) {
    return i; 
}

它生成的汇编代码是这样的

test(int):
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     eax, DWORD PTR [rbp-4]
        pop     rbp
        ret

首先解释几个寄存器的定义

  • rbp 和 rsp 寄存器分别是栈帧基址指针(Base Pointer)和栈指针(Stack Pointer), 就是当前栈帧底的基地址,以及当前栈顶的地址。
  • edi 保存函数参数的寄存器
  • eax 保存函数返回值的寄存器

我们来逐行看一下这段汇编代码

  1. push rbp: 将当前栈帧基指针 rbp 压入栈中,用于保存上一个函数的栈帧。
  2. mov rbp, rsp: 将当前栈顶指针 rsp 赋值给 rbp,以建立当前函数的新栈帧。rsp现在是上一个栈帧的顶地址,让它作为当前栈帧的基地址。
  3. mov DWORD PTR [rbp-4], edi: 将函数参数 edi 中的值存储到当前栈帧的 4 字节偏移处,也就是局部变量 i 的位置。
  4. mov eax, DWORD PTR [rbp-4]: 将局部变量 [rbp-4] 的值加载到 eax 寄存器中,准备作为函数返回值。
  5. pop rbp: 恢复上一个函数的栈帧基指针 rbp
  6. ret: 函数返回,控制权转移到调用者。

其中1 2 5 6 基本每个函数都有,它们维护了函数调用栈的结构。

c 栈帧
Theme Jasmine by Kent Liao