当前位置: 首页 > 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.jsqmd.com/news/119820/

相关文章:

  • 实测 9 款 AI 写论文哪个好?这款工具凭 “真实文献 + 规范图表” 赢麻了!
  • LLM基础
  • 实用指南:把 Spring Boot 的启动时间从 3 秒打到 30 毫秒,内存砍掉 80%,让 Java 在 Serverless 时代横着走
  • 你是你吃出来的
  • 整体二分总结
  • [强网杯 2019]upload
  • 系统文件eapprovp.dll丢失或损坏 免费下载修复方法
  • Java毕设选题推荐:基于springboot的闲置资产管理系统的设计与实现基于SpringBoot的公司资产管理系统设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 最新ASNT七大无损检测技巧全解析(RT/UT/PA/MT/PT/ECT/VT实操指南)- 上海欧鑫 ASNT 认证培训
  • 基于深度学习的草莓健康度检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
  • 【git】企业级开发模型 - 实践
  • MATLAB电力系统继电保护之自动重合闸
  • CVE-2025-68079:ThemeNectar Salient Shortcodes插件中的跨站脚本漏洞解析
  • 复习——IPC(进程间通信)
  • 5 款 AI 写论文哪个好?深度实测后,这款 “学术实力派” 藏不住了!
  • 写论文软件哪个好?虎贲等考 AI:毕业论文创作的 “全能通关神器”
  • 降重 + 去 AIGC 痕迹双 buff!虎贲等考 AI:让论文原创性 “无可挑剔”
  • 8个AI论文工具,自考本科轻松搞定写作难题!
  • 10 个AI写作工具,助你轻松搞定继续教育论文!
  • 期刊投稿屡投屡拒?虎贲等考 AI:让学术成果精准叩开核心期刊大门
  • 虎贲等考 AI:AI 赋能学术创作,全流程论文辅助工具革新登场
  • 【开题答辩全过程】以 基于VUE的爱心捐赠物资信息管理系统为例,包含答辩的问题和答案
  • [Android] 高德地图V9.1车机版 (2025 年测试版)
  • 课程论文还在熬夜凑字数?虎贲等考 AI:让学术写作高效又拿分
  • 某能源AI应用架构师亲述:用成熟度模型推动AI节能落地
  • 问卷设计还在 “手动凑题”?虎贲等考 AI:30 分钟搞定专业级调研问卷,告别无效提问
  • [Windows] 自动小说生成工具AI_NovelGenerator_V1.4.4
  • 9 款 AI 写论文哪个好?实测对比后,这款全流程神器成学术党首选! 毕业论文写作季,AI 写作工具已成学子 “救命稻草”。市面上百度智能云千帆大模型、科大讯
  • win32创建内存映射文件
  • 解析 React 的 ‘Object Inlining’ 优化:如何减少虚拟 DOM 创建时的临时对象分配?