解读一个简单的x64程序的反汇编结果

C语言代码的源码如下:
屏幕截图 2025-12-21 190052
以debug x64的方式编译为exe,随后使用IDA Pro反汇编,得到如下结果
Capture
对汇编代码做解读如下:
1.函数序言和栈帧建立
push rbp
push rdi
sub rsp, 138h
lea rbp, [rsp+30h]
建立栈帧:保存旧 rbp(基指针),保存 rdi(被调用者保存寄存器)
分配栈空间:分配 0x138 (312) 字节的栈空间
设置帧指针:rbp = rsp + 0x30,这是帧指针相对寻址的基础

2.调试检查
lea rcx, __091A7CE1_main@c ; JMC_flag
call j___CheckForDebuggerJustMyCode
nop
调用VS的 "Just My Code" 调试功能检查

3.调用addnum函数(整数版本)
mov [rsp+140h+f], 6 ; f, rsp+28h
mov [rsp+140h+e], 5 ; e, rsp+20h
mov r9d, 4 ; d
mov r8d, 3 ; c
mov edx, 2 ; b
mov ecx, 1 ; a
call j_addnum
参数传递(x64 调用约定):
前4个整数参数:rcx(1), rdx(2), r8(3), r9(4)
第5、6个参数通过栈传递:e=5, f=6(位于 [rsp+140h] 偏移处)
调用addnum函数(接收6个int参数)

4.保存整数结果
mov [rbp+110h+result], eax;rbp+4h;rsp+34h
将 addnum 的返回值(eax)保存到局部变量 result

5.调用addnum2函数(浮点数版本)
movsd xmm0, cs:__real@401a666666666666 ; 6.65 (f)
movsd qword ptr [rsp+140h+f], xmm0
movsd xmm0, cs:__real@4016000000000000 ; 5.5 (e)
movsd qword ptr [rsp+140h+e], xmm0
movsd xmm3, cs:__real@401199999999999a ; 4.4 (d)
movsd xmm2, cs:__real@400a666666666666 ; 3.3 (c)
movsd xmm1, cs:__real@400199999999999a ; 2.2 (b)
movsd xmm0, cs:__real@3ff199999999999a ; 1.1 (a)
call j_addnum2
浮点参数传递(x64 调用约定):
前 4 个浮点参数:xmm0(1.1), xmm1(2.2), xmm2(3.3), xmm3(4.4)
第 5、6 个浮点参数通过栈传递:e=5.5, f=6.65
调用 addnum2 函数(接收 6 个 double 参数)

6.保存浮点结果
movsd [rbp+110h+result2], xmm0
将addnum2的返回值(xmm0)保存到局部变量 result2

7.打印整数结果
mov edx, [rbp+110h+result]
lea rcx, _Format ; "result=%d\n"
call j_printf
从局部变量加载 result 到 edx(第二个参数)
rcx 指向格式字符串(第一个参数)
调用printf

8.打印浮点结果
movsd xmm1, [rbp+110h+result2]
movq rdx, xmm1
lea rcx, aResult2F ; "result2=%f"
call j_printf
从局部变量加载 result2 到 xmm1
将浮点数复制到 rdx(为了传递给 printf)
调用 printf 打印浮点数

9.函数尾声和返回
xor eax, eax
lea rsp, [rbp+108h]
pop rdi
pop rbp
retn
返回值设为 0(xor eax, eax)
恢复栈指针:rsp = rbp + 0x108
恢复保存的寄存器:rdi, rbp
返回

栈帧布局:

  • rbp 指向栈帧中间位置(rsp+0x30)
  • 局部变量通过 rbp+0x110 等偏移访问
    调用约定:
  • 整数:前 4 个在寄存器,其余在栈上
  • 浮点:前 4 个在 XMM 寄存器,其余在栈上
posted @ 2025-12-21 18:30  歌德巴赫猜想  阅读(2)  评论(0)    收藏  举报