当前位置: 首页 > news >正文

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

C语言代码的源码如下:
`#include <stdio.h>

int addnum(int a, int b, int c, int d, int e, int f)
{
int result = a + b + c + d + e + f;
return result;
}

double addnum2(double a, double b, double c, double d, double e, double f)
{
double result = a + b + c + d + e + f;
return result;
}

int main()
{
int result = addnum(1,2,3,4,5,6);
double result2 = addnum2(1.1 , 2.2 , 3.3 , 4.4 , 5.5 , 6.6);
printf("result=%d\n", result);
printf("result2=%f", result2);
return 0;
}`

以debug x64的方式编译为exe,随后使用IDA Pro反汇编,得到如下结果
.text:00000001400119C0 ; =============== S U B R O U T I N E =======================================
.text:00000001400119C0
.text:00000001400119C0 ; Attributes: bp-based frame fpd=110h
.text:00000001400119C0
.text:00000001400119C0 ; int main(...)
.text:00000001400119C0 main proc near ; CODE XREF: j_main↑j
.text:00000001400119C0 ; DATA XREF: .pdata:000000014001F830↓o
.text:00000001400119C0
.text:00000001400119C0 e = dword ptr -120h
.text:00000001400119C0 f = dword ptr -118h
.text:00000001400119C0 result = dword ptr -10Ch
.text:00000001400119C0 result2 = qword ptr -0E8h
.text:00000001400119C0
.text:00000001400119C0 push rbp
.text:00000001400119C2 push rdi
.text:00000001400119C3 sub rsp, 138h
.text:00000001400119CA lea rbp, [rsp+30h]
.text:00000001400119CF lea rcx, __091A7CE1_main@c ; JMC_flag
.text:00000001400119D6 call j___CheckForDebuggerJustMyCode
.text:00000001400119DB nop
.text:00000001400119DC mov [rsp+140h+f], 6 ; f
.text:00000001400119E4 mov [rsp+140h+e], 5 ; e
.text:00000001400119EC mov r9d, 4 ; d
.text:00000001400119F2 mov r8d, 3 ; c
.text:00000001400119F8 mov edx, 2 ; b
.text:00000001400119FD mov ecx, 1 ; a
.text:0000000140011A02 call j_addnum
.text:0000000140011A07 mov [rbp+110h+result], eax
.text:0000000140011A0A movsd xmm0, cs:__real@401a666666666666
.text:0000000140011A12 movsd qword ptr [rsp+140h+f], xmm0 ; f
.text:0000000140011A18 movsd xmm0, cs:__real@4016000000000000
.text:0000000140011A20 movsd qword ptr [rsp+140h+e], xmm0 ; e
.text:0000000140011A26 movsd xmm3, cs:__real@401199999999999a ; d
.text:0000000140011A2E movsd xmm2, cs:__real@400a666666666666 ; c
.text:0000000140011A36 movsd xmm1, cs:__real@400199999999999a ; b
.text:0000000140011A3E movsd xmm0, cs:__real@3ff199999999999a ; a
.text:0000000140011A46 call j_addnum2
.text:0000000140011A4B movsd [rbp+110h+result2], xmm0
.text:0000000140011A50 mov edx, [rbp+110h+result]
.text:0000000140011A53 lea rcx, _Format ; "result=%d\n"
.text:0000000140011A5A call j_printf
.text:0000000140011A5F nop
.text:0000000140011A60 movsd xmm1, [rbp+110h+result2]
.text:0000000140011A65 movq rdx, xmm1
.text:0000000140011A6A lea rcx, aResult2F ; "result2=%f"
.text:0000000140011A71 call j_printf
.text:0000000140011A76 nop
.text:0000000140011A77 xor eax, eax
.text:0000000140011A79 lea rsp, [rbp+108h]
.text:0000000140011A80 pop rdi
.text:0000000140011A81 pop rbp
.text:0000000140011A82 retn
.text:0000000140011A82 main endp
.text:0000000140011A82
.text:0000000140011A82 ; ---------------------------------------------------------------------------

对汇编代码做解读如下:
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 寄存器,其余在栈上
http://www.rkmt.cn/news/131913.html

相关文章:

  • 你是你吃出来的
  • 最新ASNT七大无损检测技巧全解析(RT/UT/PA/MT/PT/ECT/VT实操指南)- 上海欧鑫 ASNT 认证培训
  • 基于深度学习的草莓健康度检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
  • LLM基础
  • MATLAB电力系统继电保护之自动重合闸
  • CVE-2025-68079:ThemeNectar Salient Shortcodes插件中的跨站脚本漏洞解析
  • OKR 要不要考核?
  • 开题报告反复被打回?虎贲等考 AI:让研究起点精准踩中学术规范
  • 写论文软件哪个好?虎贲等考 AI:毕业论文创作的 “全能通关神器”
  • 9 款 AI 写论文哪个好?实测对比后,这款全流程神器成学术党首选! 毕业论文写作季,AI 写作工具已成学子 “救命稻草”。市面上百度智能云千帆大模型、科大讯
  • win32创建内存映射文件
  • 并发模式下的内存压力:如果同时启动 100 个 Transition 任务,React 堆内存会爆炸吗?
  • 删除Windows系统并安装Ubuntu系统
  • LeetCode 122. 买卖股票的最佳时机 II - 推荐贪心
  • cesium126,240308,Ce for Ue 加载ArcGIS WMTS Map:
  • AI 写论文哪个软件最好?虎贲等考 AI:从框架到定稿的全流程学术赋能
  • 第一章:从连续世界到可计算存在
  • AI 写论文哪个软件最好?虎贲等考 AI:让毕业论文创作告别 “卡壳” 与 “查重焦虑”
  • 学术创作革新!虎贲等考 AI 期刊论文功能:让专业写作告别低效与焦虑
  • Windows系统文件DWrite.dll丢失损坏问题 下载修复
  • 移动平均-loss函数平滑化
  • ARC115F Migration
  • 问卷设计还在 “拍脑袋”?虎贲等考 AI:让科研调研从 “盲目发问” 到 “精准赋能”
  • Windows系统文件dpx.dll损坏或丢失 下载修复
  • 2025年采购必看:高口碑快速卷帘门品牌榜单,洁净车间工程/洁净工作台/FFU/净化工作台/医疗装修工程/洁净棚/货淋室快速卷帘门厂商哪个好 - 品牌推荐师
  • still ace
  • CSP-J/S 2025 第一轮游记 _
  • 2025年实力盘点:引领行业趋势的家居装修公司,别墅装修/豪宅设计/家居装修/家居设计公司口碑推荐 - 品牌推荐师
  • 一文读懂字符与编码
  • Open-AutoGLM能否彻底取代SoapUI?基于12个真实场景的协同能力压测结果公布