初识main函数

cpp 复制代码
int main(int argc, char *argv[])
{
    int a = 0;
    return a;
}

X64

MSVC编译器

Windows x64调用约定

cpp 复制代码
{
// 将第二个参数(rdx)保存到栈[rsp+0x10]位置
0x7ff6e54c2ad0                   mov     qword ptr [rsp+10h],rdx 
// 将第一个参数(ecx)保存到栈[rsp+8]位置
0x7ff6e54c2ad5  <+    5>         mov     dword ptr [rsp+8],ecx
//保存rdi寄存器(非易失性寄存器) 保存rdi是因为函数可能会修改它,遵循调用约定
0x7ff6e54c2ad9  <+    9>         push    rdi
0x7ff6e54c2ada  <+   10>         sub     rsp,10h
        4        int a = 0;
0x7ff6e54c2ade  <+   14>         mov     dword ptr [rsp],0
        5        return a;
0x7ff6e54c2ae5  <+   21>         mov     eax,dword ptr [rsp]
        6    
}
// 释放栈空间
0x7ff6e54c2ae8  <+   24>         add     rsp,10h
// 恢复rdi寄存器
0x7ff6e54c2aec  <+   28>         pop     rdi
0x7ff6e54c2aed  <+   29>         ret

GCC/MinGW

System V x64调用约定

cpp 复制代码
        4 [1]	{
0x4016a0                  55                    push   %rbp
0x4016a1  <+    1>        48 89 e5              mov    %rsp,%rbp
0x4016a4  <+    4>        48 83 ec 30           sub    $0x30,%rsp
0x4016a8  <+    8>        89 4d 10              mov    %ecx,0x10(%rbp)
0x4016ab  <+   11>        48 89 55 18           mov    %rdx,0x18(%rbp)
0x4016af  <+   15>        e8 bc 04 00 00        call   0x401b70 <__main>
        5 [1]	    int a = 0;
//局部变量 a 存储在 -0x4(%rbp)(栈帧内固定偏移)
0x4016b4  <+   20>        c7 45 fc 00 00 00 00  movl   $0x0,-0x4(%rbp)
        6 [1]	    return a;
0x4016bb  <+   27>        8b 45 fc              mov    -0x4(%rbp),%eax
        7 [1]	}
0x4016be  <+   30>        48 83 c4 30           add    $0x30,%rsp
0x4016c2  <+   34>        5d                    pop    %rbp
0x4016c3  <+   35>        c3                    ret

对比

特性 第一段代码(Windows x64) 第二段代码(System V x64)
调用约定 Windows x64 System V x64(Linux/macOS)
参数传递 ecx, rdx, r8, r9 rdi, rsi, rdx, rcx, r8, r9
栈帧管理 直接调整 rsp ,无 rbp 传统 push rbp / mov rbp, rsp
Shadow Space 通常 32 字节(此处仅 16 字节)
局部变量存储 [rsp] (栈顶) -0x4(%rbp) (栈帧偏移)
非易失寄存器保存 显式保存 rdi 调用者负责保存
函数返回 ret(或 ret 0 ret
典型使用场景 Windows 程序 Linux/macOS 程序
  1. 调用约定差异
    • Windows x64 和 System V x64 在参数传递、栈管理上完全不同。
    • Windows 需要 shadow space,System V 需要栈对齐。
  2. 栈帧管理
    • Windows x64 常省略 rbp,直接操作 rsp
    • System V x64 保留传统栈帧(rbp)。
  3. 寄存器保存
    • Windows x64 可能显式保存非易失寄存器(如 rdi)。
    • System V x64 由调用者保存非易失寄存器。
  4. 代码风格
    • Windows x64 更紧凑(如 [rsp+8] 直接寻址)。
    • System V x64 更传统(如 -0x4(%rbp) 偏移寻址)。
相关推荐
曼巴UE518 分钟前
UE5.3 C++ 接口初步使用
开发语言·jvm·c++
泛联新安25 分钟前
如何根据项目需求选择合适的软件测试工具?iUnit智能单元测试平台提供专业化解决方案
c++·测试工具·单元测试
曙曙学编程30 分钟前
stm32——NVIC,EXIT
c语言·c++·stm32·单片机·嵌入式硬件
liulilittle38 分钟前
UNIX/macOS路由表查询原理与实现
服务器·开发语言·c++·macos·unix·编程语言
Dovis(誓平步青云)2 小时前
《探索C++11:现代语法的性能优化策略(中篇)》
开发语言·c++
一个响当当的名号2 小时前
c++primer 个人学习总结-模板和泛型编程
开发语言·c++·学习
落羽的落羽2 小时前
【C++】C++11的可变参数模板、emplace接口、类的新功能
开发语言·c++·学习
小跌—3 小时前
Linux:进程信号理解
linux·c++·算法
liulilittle3 小时前
HTTP简易客户端实现
开发语言·网络·c++·网络协议·http·编程语言
微风扬!3 小时前
C++ Lambda 表达式完整指南
c++·lambda