skip to content

Search

x86-64 过程

3 min read Updated:
草地,山坡与蓝天

运行时栈,函数调用与返回,参数传递,ABI

栈

栈是一种后进先出(LIFO)的数据结构,用于存储函数调用的相关信息,如局部变量、返回地址和保存的寄存器值。

在x86-64架构中,栈通常向下增长,即从高地址向低地址扩展。

栈的结构

函数调用

函数调用涉及以下步骤:

  1. 参数传递:前六个整数或指针参数通过寄存器%rdi, %rsi, %rdx, %rcx, %r8, %r9传递,超过六个参数的通过栈传递(参数7位于栈顶)
  2. 保存返回地址:调用指令call执行两个操作:将返回地址(下一条指令的地址)压入栈中,并跳转到被调用函数的地址
  3. 函数体执行:被调用函数执行其代码,可能会使用栈来存储局部变量和保存寄存器
  4. 返回值传递:函数体执行完成后,返回值通过寄存器%rax传递回调用者
  5. 函数返回:调用指令ret执行两个操作:弹出(读取并释放)当前%rsp指向栈顶内存储的返回地址,并跳转到该地址执行(这要求函数必须释放所有其占用的栈空间,以将%rsp恢复到调用前的状态),

ABI

ABI(应用二进制接口)定义了函数调用约定,包括参数传递、返回值传递、寄存器使用和栈帧布局等规则。

  • callee-saved:被调用函数必须保存和恢复的寄存器(如%rbx, %rbp, %r12-%r15)。调用者可以认为这些寄存器在函数调用前后保持不变。
  • caller-saved:如%rax, %rcx, %rdx, %rsi, %rdi, %r8-%r11。被调用函数可以自由使用这些寄存器,不保证调用前后的值保持不变。