【汇编逆向系列】七、函数调用包含多个参数之浮点型- XMM0-3寄存器

目录

1. 汇编代码

1.1 debug编译

1.2 release编译

2. 汇编分析

2.1 浮点参数传递规则

2.2 栈帧rsp的变化时序

2.3 参数的访问逻辑

2.4 返回值XMM0寄存器

3. 汇编转化

3.1 Debug编译

3.2 Release 编译

3.3 C语言转化


1. 汇编代码

上一节介绍了整型的函数传参,那么浮点型有什么不同,将在这一节介绍,包含float和double的浮点型都是类似的传参方式。这一节将不再区分少数参数和多个参数,直接使用多个参数浮点型的汇编代码例子。

1.1 debug编译

many_double_params:0000000000000A20: F2 0F 11 5C 24 20  movsd       mmword ptr [rsp+20h],xmm30000000000000A26: F2 0F 11 54 24 18  movsd       mmword ptr [rsp+18h],xmm20000000000000A2C: F2 0F 11 4C 24 10  movsd       mmword ptr [rsp+10h],xmm10000000000000A32: F2 0F 11 44 24 08  movsd       mmword ptr [rsp+8],xmm00000000000000A38: 57                 push        rdi0000000000000A39: 48 83 EC 10        sub         rsp,10h0000000000000A3D: 48 8B FC           mov         rdi,rsp0000000000000A40: B9 04 00 00 00     mov         ecx,40000000000000A45: B8 CC CC CC CC     mov         eax,0CCCCCCCCh0000000000000A4A: F3 AB              rep stos    dword ptr [rdi]0000000000000A4C: F2 0F 10 44 24 20  movsd       xmm0,mmword ptr [rsp+20h]0000000000000A52: F2 0F 58 44 24 28  addsd       xmm0,mmword ptr [rsp+28h]0000000000000A58: F2 0F 58 44 24 30  addsd       xmm0,mmword ptr [rsp+30h]0000000000000A5E: F2 0F 58 44 24 38  addsd       xmm0,mmword ptr [rsp+38h]0000000000000A64: F2 0F 58 44 24 40  addsd       xmm0,mmword ptr [rsp+40h]0000000000000A6A: F2 0F 58 44 24 48  addsd       xmm0,mmword ptr [rsp+48h]0000000000000A70: F2 0F 5E 05 00 00  divsd       xmm0,mmword ptr [__real@4018000000000000]00 000000000000000A78: 48 83 C4 10        add         rsp,10h0000000000000A7C: 5F                 pop         rdi0000000000000A7D: C3                 ret0000000000000A7E: CC                 int         30000000000000A7F: CC                 int         30000000000000A80: CC                 int         3

1.2 release编译


many_double_params:0000000000000000: F2 0F 58 C1        addsd       xmm0,xmm10000000000000004: F2 0F 58 C2        addsd       xmm0,xmm20000000000000008: F2 0F 58 C3        addsd       xmm0,xmm3000000000000000C: F2 0F 58 44 24 28  addsd       xmm0,mmword ptr [rsp+28h]0000000000000012: F2 0F 58 44 24 30  addsd       xmm0,mmword ptr [rsp+30h]0000000000000018: F2 0F 5E 05 00 00  divsd       xmm0,mmword ptr [__real@4018000000000000]00 000000000000000020: C3                 ret

2. 汇编分析

2.1 浮点参数传递规则

在 Windows x64 调用约定中:

  • 前 4 个浮点参数​​通过 XMM0-XMM3 寄存器传递
  • 第 5 个及以上参数​​通过栈传递(从右向左压栈)
  • 调用者需预留 ​​32 字节影子空间​​(Shadow Space),用于被调函数保存寄存器参数

2.2 栈帧rsp的变化时序

在栈帧变化上浮点型与整型保持着完全一致的逻辑

; 1. 保存前4个浮点参数到影子空间
movsd [rsp+20h], xmm3   ; 参数4 → [影子空间+0x20]
movsd [rsp+18h], xmm2   ; 参数3 → [影子空间+0x18]
movsd [rsp+10h], xmm1   ; 参数2 → [影子空间+0x10]
movsd [rsp+8],   xmm0   ; 参数1 → [影子空间+0x08]; 2. 保存非易失寄存器
push rdi                 ; RSP -= 8; 3. 分配局部变量空间
sub rsp, 10h             ; RSP -= 16 (0x10); 4. 初始化局部空间(调试版行为)
mov rdi, rsp
mov ecx, 4
mov eax, 0CCCCCCCCh      ; 填充未初始化数据标记
rep stosd                ; 用 0xCC 填充 16 字节

 在call指令调用函数时,栈帧rsp-=8, 所以影子空间的位置都要+0x08, 由[rsp]-[rsp+0x20]变化为[rsp+8]-[rsp+0x28]所以movsd [rsp+8], xmm0 ; 参数1 → [影子空间+0x08],第一个参数是放在[rsp+8]。

在push rdi 后, 再次 rsp-=8, 此时所有参数位置要再次+ 0x08

在sub rsp 10h之后,再次 rsp -= 0x10, 所以所有参数位置再次+ 0x10h

这里也充分说明了局部变量的地址是向下增长的

2.3 参数的访问逻辑

; 加载并累加参数(偏移基于当前 RSP)
movsd xmm0, [rsp+20h]   ; 加载参数1 (当前 RSP+0x20 = 原始影子空间+0x08)
addsd xmm0, [rsp+28h]   ; + 参数2 (原始影子空间+0x10)
addsd xmm0, [rsp+30h]   ; + 参数3 (原始影子空间+0x18)
addsd xmm0, [rsp+38h]   ; + 参数4 (原始影子空间+0x20)
addsd xmm0, [rsp+40h]   ; + 参数5 (调用者压栈的第1个额外参数)
addsd xmm0, [rsp+48h]   ; + 参数6 (调用者压栈的第2个额外参数)

由于栈是向下增长的,从参数六开始压栈,参数1 的地址其实是最低的

2.4 返回值XMM0寄存器

在x64架构下,浮点计算的返回值统一使用 ​​XMM0 寄存器​​作为传递载体。这一规则适用于单精度(float)和双精度(double)浮点数,且是跨操作系统(如 Windows 和 Linux)的标准约定

浮点类型​​(包括 floatdouble):结果存储在 XMM0 的低位部分:

  • ​单精度​​(32位):使用 XMM0 的低32位
  • 双精度​​(64位):使用 XMM0 的低64位

3. 汇编转化

3.1 Debug编译

movsd [rsp+20h], xmm3   ; 保存第4个参数(xmm3 → [影子空间+0x20])[1](@ref)
movsd [rsp+18h], xmm2   ; 保存第3个参数(xmm2 → [影子空间+0x18])
movsd [rsp+10h], xmm1   ; 保存第2个参数(xmm1 → [影子空间+0x10])
movsd [rsp+8], xmm0     ; 保存第1个参数(xmm0 → [影子空间+0x08])
push rdi                ; 保存非易失寄存器 RDI(RSP -= 8)
sub rsp, 10h            ; 分配 16 字节局部空间(RSP -= 16)
mov rdi, rsp
mov ecx, 4             ; 循环4次(4×4字节=16字节)
mov eax, 0CCCCCCCCh    ; 未初始化内存标记(调试用)
rep stosd              ; 用 0xCC 填充局部空间
movsd xmm0, [rsp+20h]   ; 加载第1个参数(原始 xmm0)
addsd xmm0, [rsp+28h]   ; + 第2个参数(原始 xmm1)
addsd xmm0, [rsp+30h]   ; + 第3个参数(原始 xmm2)
addsd xmm0, [rsp+38h]   ; + 第4个参数(原始 xmm3)
addsd xmm0, [rsp+40h]   ; + 第5个参数(栈传递)
addsd xmm0, [rsp+48h]   ; + 第6个参数(栈传递)
divsd xmm0, [__real@4018000000000000]  ; xmm0 /= 6.0
add rsp, 10h            ; 释放局部空间(RSP += 16)
pop rdi                 ; 恢复 RDI(RSP += 8)
ret                     ; 返回结果(xmm0 作为返回值)

3.2 Release 编译

; 函数入口点,参数通过寄存器和栈传递
0000000000000000: 8D 04 11           lea         eax, [rcx+rdx]   ; EAX = 参数1(RCX) + 参数2(RDX)
0000000000000003: 41 03 C0           add         eax, r8d          ; EAX += 参数3(R8D)
0000000000000006: 41 03 C1           add         eax, r9d          ; EAX += 参数4(R9D)
0000000000000009: 03 44 24 28        add         eax, dword ptr [rsp+28h] ; EAX += 参数5(栈偏移0x28)
000000000000000D: 03 44 24 30        add         eax, dword ptr [rsp+30h] ; EAX += 参数6(栈偏移0x30)
0000000000000011: 03 44 24 38        add         eax, dword ptr [rsp+38h] ; EAX += 参数7(栈偏移0x38)
0000000000000015: 03 44 24 40        add         eax, dword ptr [rsp+40h] ; EAX += 参数8(栈偏移0x40)
0000000000000019: 03 44 24 48        add         eax, dword ptr [rsp+48h] ; EAX += 参数9(栈偏移0x48)
000000000000001D: 03 44 24 50        add         eax, dword ptr [rsp+50h] ; EAX += 参数10(栈偏移0x50)
0000000000000021: C3                 ret                          ; 返回结果(EAX为返回值)

3.3 C语言转化

#include <stdint.h>// 函数原型(6个 double 参数)
double many_double_params(double p1, double p2, double p3, double p4,double p5, double p6
) {// 累加所有参数double sum = p1 + p2 + p3 + p4 + p5 + p6;// 除以 6.0 后返回return sum / 6.0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/86529.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为云Flexus+DeepSeek征文 | 从零到一:用Flexus云服务打造低延迟联网搜索Agent

作者简介 我是摘星&#xff0c;一名专注于云计算和AI技术的开发者。本次通过华为云MaaS平台体验DeepSeek系列模型&#xff0c;将实际使用经验分享给大家&#xff0c;希望能帮助开发者快速掌握华为云AI服务的核心能力。 目录 作者简介 前言 1. 项目背景与技术选型 1.1 项目…

【多智能体】受木偶戏启发实现多智能体协作编排

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本专栏《人工智能》旨在记录最新的科研前沿&#xff0c;包括大模型、具身智能、智能体等相关领域&#xff0c;期待与你一同探索、学习、进步&#xff0c;一起卷起来叭&#xff…

Java八股文——Spring篇

文章目录 Java八股文专栏其它文章Java八股文——Spring篇SpringSpring的IoC和AOPSpring IoC实现机制Spring AOP实现机制 动态代理JDK ProxyCGLIBByteBuddy Spring框架中的单例Bean是线程安全的吗&#xff1f;什么是AOP&#xff0c;你们项目中有没有使用到AOPSpring中的事务是如…

NineData数据库DevOps功能全面支持百度智能云向量数据库 VectorDB,助力企业 AI 应用高效落地

NineData 的数据库 DevOps 解决方案已完成对百度智能云向量数据库 VectorDB 的全链路适配&#xff0c;成为国内首批提供 VectorDB 原生操作能力的服务商。此次合作聚焦 AI 开发核心场景&#xff0c;通过标准化 SQL 工作台与细粒度权限管控两大能力&#xff0c;助力企业安全高效…

开源技术驱动下的上市公司财务主数据管理实践

开源技术驱动下的上市公司财务主数据管理实践 —— 以人造板制造业为例 引言&#xff1a;财务主数据的战略价值与行业挑战 在资本市场监管日益严格与企业数字化转型的双重驱动下&#xff0c;财务主数据已成为上市公司财务治理的核心基础设施。对于人造板制造业而言&#xff0…

借助它,普转也能获得空转信息?

在生命科学研究领域&#xff0c;转录组技术是探索基因表达奥秘的有力工具&#xff0c;在疾病机制探索、生物发育进程解析等诸多方面取得了显著进展。然而&#xff0c;随着研究的深入&#xff0c;研究人员发现普通转录组只能提供整体样本中的基因表达水平信息&#xff0c;却无法…

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…

Java事务回滚详解

一、什么是事务回滚&#xff1f; 事务回滚指的是&#xff1a;当执行过程中发生异常时&#xff0c;之前对数据库所做的更改全部撤销&#xff0c;数据库状态恢复到事务开始前的状态。这是数据库“原子性”原则的体现。 二、Spring 中的 Transactional 默认行为 在 Spring 中&am…

云灾备数据复制技术研究

云灾备数据复制技术&#xff1a;数字时代的“安全气囊” 在当今信息化时代&#xff0c;数据就像城市的“生命线”&#xff0c;一旦中断&#xff0c;后果不堪设想。想象一下&#xff0c;如果政务系统突然崩溃&#xff0c;成千上万的市民服务将陷入瘫痪。这就是云灾备技术的重要…

如何处理Shopify主题的显示问题:实用排查与修复指南

在Shopify店铺运营过程中&#xff0c;主题显示问题是影响用户体验与品牌形象的常见痛点。可能是字体错位、图片无法加载、移动端显示混乱、功能失效等&#xff0c;这些都可能造成客户流失和转化下降。 本文将从问题识别、原因分析、修复方法到开发者建议全方位解读如何高效解决…

前端监控方案详解

一、前端监控方案是什么&#xff1f; 前端监控方案是一套系统化的工具和流程&#xff0c;用于收集、分析和报告网站或Web应用在前端运行时的各种性能指标、错误日志、用户行为等数据。它通常包括以下几个核心模块&#xff1a; 性能监控&#xff1a;页面加载时间、资源加载时间…

Camera相机人脸识别系列专题分析之十二:人脸特征检测FFD算法之libvega_face.so数据结构详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; Camera相机人脸识别系列专题分析之十一&#xff1a;人脸特征检测FFD算法之低功耗libvega_face.so人脸属性(年龄&#xff0c;性别&#xff0c;肤…

如何配置HarmonyOS 5与React Native的开发环境?

配置 HarmonyOS 5 与 React Native 的开发环境需遵循以下步骤 一、基础工具安装 ‌DevEco Studio 5.0‌ 从 HarmonyOS 开发者官网 下载安装勾选组件&#xff1a; HarmonyOS SDK (API 12)ArkTS 编译器JS/ArkTS 调试工具HarmonyOS 本地模拟器 ‌Node.js 18.17 # 安装后验证版…

kotlin kmp 副作用函数 effect

在 Kotlin Multiplatform (KMP) Compose 中&#xff0c;“effect functions”&#xff08;或“effect handlers”&#xff09;是专门的可组合函数&#xff0c;用于在 UI 中管理副作用。 在 Compose 中&#xff0c;可组合函数应该是“纯”的和声明式的。这意味着它们应该理想地…

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…

【Pandas】pandas DataFrame isna

Pandas2.2 DataFrame Missing data handling 方法描述DataFrame.fillna([value, method, axis, …])用于填充 DataFrame 中的缺失值&#xff08;NaN&#xff09;DataFrame.backfill(*[, axis, inplace, …])用于**使用后向填充&#xff08;即“下一个有效观测值”&#xff09…

MQTT协议:物联网时代的通信基石

MQTT协议&#xff1a;物联网时代的通信基石 在当今快速发展的物联网&#xff08;IoT&#xff09;时代&#xff0c;设备之间的通信变得尤为重要。MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;协议作为一种轻量级的消息传输协议&#xff0c;正逐渐成为物联…

Excel 表格内批量添加前缀与后缀的实用方法

我们经常需要为 Excel 表格中的内容统一添加前缀或后缀&#xff0c;例如给编号加“NO.”、给姓名加“会员_”等。手动操作效率低&#xff0c;本文将介绍几种实用的方法&#xff0c;帮助你快速完成批量添加前缀和后缀的操作。 使用“&”运算符添加前缀或后缀&#xff08;推…

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…