• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2026-01-22 16:27 Aet 隐藏边栏 |   抢沙发  1 
文章评分 1 次,平均分 5.0

寄存器

问题

  1. 寄存器在写汇编的时候是随便用的吗
    1. 寄存器的使用有严格的规则和约定,违反这些规则会导致程序崩溃或出现难以调试的 bug

32位-常见调用约定对比

特性 GCC cdecl MSVC __cdecl MSVC __stdcall MSVC/GCC __fastcall
平台 Linux Windows Windows Windows/Linux
参数1 ecx
参数2 edx
参数3+
参数顺序 从右到左 从右到左 从右到左 从右到左
栈清理 调用者 调用者 被调用者 被调用者
返回值 eax eax eax eax
名字修饰 _func _func _func@bytes @func@bytes
可变参数 yes yes no no

64位-常见调用约定对比

特性 GCC (System V AMD64) MSVC (Microsoft x64)
平台 Linux/macOS Windows
参数1 rdi rcx
参数2 rsi rdx
参数3 rdx r8
参数4 rcx r9
参数5 r8
参数6 r9
参数7+
浮点参数1-4 xmm0-xmm3 xmm0-xmm3
浮点参数5-8 xmm4-xmm7
返回值 rax rax
栈清理 调用者 调用者
Shadow Space 必须预留32字节
栈对齐 16字节 16字节
XMM寄存器 xmm0-xmm15 全部调用者保存 xmm0-xmm5 调用者,xmm6-xmm15 被调用者

32Linux-完整调用约定

  1. gcc
调用约定 参数传递 栈清理 使用场景 语法
cdecl 全部栈 调用者 默认约定,C 函数 int func()
stdcall 全部栈 被调用者 Windows API 兼容 __attribute__((stdcall))
fastcall ecx, edx, 其余栈 被调用者 性能优化 __attribute__((fastcall))
regparm(n) 前n个用寄存器 调用者 GCC 特有,灵活优化 __attribute__((regparm(3)))
thiscall thisecx,其余栈 被调用者 C++ 成员函数 自动处理
pascal 全部栈(左到右) 被调用者 老式约定,很少用 __attribute__((pascal))

32Windows -完整调用约定

  1. msvc
调用约定 参数传递 栈清理 使用场景 语法
__cdecl 全部栈 调用者 默认约定,C 函数 int __cdecl func()
__stdcall 全部栈 被调用者 Windows API 标准 int __stdcall func()
__fastcall ecx, edx, 其余栈 被调用者 性能优化 int __fastcall func()
__thiscall thisecx,其余栈 被调用者 C++ 成员函数 自动处理
__vectorcall 向量寄存器优化 被调用者 SIMD 优化 int __vectorcall func()
__clrcall .NET CLR 特殊 .NET 互操作 int __clrcall func()

64Linux-调用约定

  1. Linux/macOS (GCC) - 64位
  2. 注意:64Linux 只有一种调用约定
调用约定 参数传递 特点 使用场景 语法
System V AMD64 rdi, rsi, rdx, rcx, r8, r9 唯一标准 所有函数 默认
ms_abi rcx, rdx, r8, r9 Windows 兼容 调用 Windows DLL __attribute__((ms_abi))

64Windows-完整调用约定

  1. 64Windows 也基本只有一种调用约定
调用约定 参数传递 特点 使用场景 语法
Microsoft x64 rcx, rdx, r8, r9 唯一标准 所有函数 默认
__vectorcall 向量寄存器优化 SIMD 增强 高性能计算 int __vectorcall func()
sysv_abi rdi, rsi, rdx, rcx, r8, r9 Linux 兼容 调用 Linux GCC: __attribute__((sysv_abi))

寄存器保存规则

寄存器 64Linux 64Windows 32Linux 32Windows
rax/eax 调用者 调用者 调用者 调用者
rcx/ecx 调用者 调用者 调用者 调用者
rdx/edx 调用者 调用者 调用者 调用者
rsi/esi 调用者 被调用者 被调用者 被调用者
rdi/edi 调用者 被调用者 被调用者 被调用者
rbx/ebx 被调用者 被调用者 被调用者 被调用者
rbp/ebp 被调用者 被调用者 被调用者 被调用者
rsp/esp 特殊 特殊 特殊 特殊
r8-r11 调用者 调用者 N/A N/A
r12-r15 被调用者 被调用者 N/A N/A

特殊用途的寄存器

  1. rsp(栈指针)
    1. 绝对不能随便改
    2. 必须始终指向有效的栈顶
    3. 改变它必须小心,且要恢复
  2. rbp(基址指针)
    1. 通常用于建立栈帧
    2. 属于被调用者保存寄存器
    3. 使用前必须先 push rbp
  3. rip(指令指针)
    1. 不能直接修改
    2. 只能通过 jmp, call, ret 等指令间接改变

参数传递规则

特性 gcc-32 msvc-32 gcc-64 msvc-64
参数1 cdecl-栈
fastcall-ecx
rdi rcx
参数2 cdecl-栈
fastcall-edx
rsi rdx
参数3 rdx r8
参数4 rcx r9
参数5 r8
参数6 r9
参数7+

栈清理规则

编译器 调用约定 栈清理
gcc cdecl 调用者
msvc cdecl 调用者
msvc stdcall 被调用者
msvc/gcc fastcall 被调用者

其他

基础算术运算

条件判断(if-else

循环结构(for/while

数组访问

函数调用和参数传递

递归(阶乘)

声明:本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享