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

【汇编逆向系列】七、函数调用包含多个参数之浮点型- 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;
}

相关文章:

【汇编逆向系列】七、函数调用包含多个参数之浮点型- 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. 汇编代码 上一节介绍了整型的函数传参&#x…...

【MySQL系列】MySQL 执行 SQL 文件

博客目录 一、MySQL 执行 SQL 文件的常见场景二、MySQL 执行 SQL 文件的主要方法1. 使用 MySQL 命令行客户端2. 在 MySQL 交互界面中使用 source 命令3. 使用 MySQL Workbench 等图形化工具4. 使用编程语言接口 三、执行 SQL 文件时的注意事项1. 字符集问题2. 事务处理3. 错误处…...

论文MR-SVD

每个像素 7 个 FLOPs意思&#xff1a; FLOPs&#xff08;浮点运算次数&#xff09;&#xff1a;衡量算法计算复杂度的指标&#xff0c;数值越小表示运算越高效。含义&#xff1a;对图像中每个像素进行处理时&#xff0c;仅需执行7 次浮点运算&#xff08;如加减乘除等&#xf…...

Java 日期时间类全面解析

Java 日期时间类全面解析&#xff1a;从传统到现代的演进 一、发展历程概览 二、传统日期类&#xff08;Java 8前&#xff09; 1. java.util.Date - 日期表示类 Date now new Date(); // 当前日期时间 System.out.println(now); // Wed May 15 09:30:45 CST 2023// 特定时间…...

【工具-Wireshark 抓包工具】

工具-Wireshark 抓包工具 ■ Wireshark 抓包工具■ 通过IP指定查看■■ ■ Wireshark 抓包工具 抓包工具】win 10 / win 11&#xff1a;WireShark 下载、安装、使用 Wireshark下载 阿里云镜像 ■ 通过IP指定查看 ■ ■...

Linux安全机制:从SELinux到Intel SGX的堡垒

Linux安全机制&#xff1a;从SELinux到Intel SGX的堡垒 数字世界的钢铁长城 引言&#xff1a;操作系统的"防御工事" 当服务器每天承受数百万次攻击尝试时&#xff0c;Linux内核的安全机制如同精密的防御系统&#xff0c;在纳秒级时间内做出响应。现代Linux安全架构已…...

设备驱动与文件系统:06 目录与文件

磁盘使用的最后一层抽象&#xff1a;文件系统 今天我们讲第31讲&#xff0c;这一讲将完成磁盘对磁盘使用的最后一层抽象。对此板使用最后一层抽象&#xff0c;抽象出来的是什么呢&#xff1f; 实际上我们使用过磁盘&#xff0c;大家应该有这样的认识&#xff0c;最后不管这个磁…...

C++11 Token Bucket (令牌桶)算法的锁无实现及应用

Token Bucket&#xff08;令牌桶&#xff09;算法是一种在流量控制和资源分配领域被广泛应用的技术。它通过约束数据传输速率或任务执行频率&#xff0c;确保系统在资源有限的情况下&#xff0c;能够稳定、高效地运行&#xff0c;避免因突发流量或任务积压而导致的性能下降甚至…...

详细介绍uni-app中Composition API和Options API的使用方法

uni-app 中 Composition API 和 Options API 的使用方法详解 一、Options API&#xff08;Vue 2.x 传统方式&#xff09; 1. 基本结构 Options API 通过配置对象的不同选项&#xff08;如 data、methods、computed 等&#xff09;组织代码&#xff1a; <template><…...

delphi7 链表 使用方法

在 Delphi 中&#xff0c;链表是一种常见的数据结构&#xff0c;用于存储一系列的元素&#xff0c;其中每个元素都包含一个指向列表中下一个元素的引用。在 Delphi 7 中&#xff0c;你可以手动实现链表&#xff0c;或者使用一些现有的集合类&#xff0c;例如 TList 或者 TLinke…...

Linux 系统中的算法技巧与性能优化

引言​ Linux 系统以其开源、稳定和高度可定制的特性&#xff0c;在服务器端、嵌入式设备以及开发环境中得到了极为广泛的应用。对于开发者而言&#xff0c;不仅要掌握在 Linux 环境下实现各类算法的方法&#xff0c;更要知晓如何利用系统特性对算法进行优化&#xff0c;以提升…...

【C++系列】模板类型特例化

1. C模板类型特例化介绍 ​​定义​​&#xff1a;模板类型特例化&#xff08;Template Specialization&#xff09;是C中为模板的特定类型提供定制实现的机制&#xff0c;允许开发者对通用模板无法处理的特殊类型进行优化或特殊处理。 ​​产生标准​​&#xff1a; C98/03…...

K8S认证|CKS题库+答案| 7. Dockerfile 检测

目录 7. Dockerfile 检测 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、修改 Dockerfile 3&#xff09;、 修改 deployment.yaml 7. Dockerfile 检测 免费获取并激活 CKA_v1.31_模拟系统 题目 您必须在以…...

JAVA 对象 详解

对象 对象结构&#xff1a; 对象头&#xff08;元数据和指向class的指针&#xff09;、实例数据、对齐填充 数组对象&#xff1a; 对象头&#xff08;元数据和指向class的指针&#xff09;、数组长度、数组数据、对齐填充 对象创建&#xff1a; 一、当Java虚拟机遇到一条…...

MATLAB实战:四旋翼姿态控制仿真方案

以下是一个基于MATLAB/Simulink的四旋翼姿态控制仿真方案。本方案使用简化姿态动力学模型&#xff0c;并设计PID控制器进行稳定控制。 1. 四旋翼姿态动力学模型 核心方程&#xff1a;I * ω̇ ω (I * ω) τ 其中&#xff1a; I diag([Ixx, Iyy, Izz]) 为转动惯量矩阵 …...

基于Scala实现Flink的三种基本时间窗口操作

目录 代码结构 代码解析 (1) 主程序入口 (2) 窗口联结&#xff08;Window Join&#xff09; (3) 间隔联结&#xff08;Interval Join&#xff09; (4) 窗口同组联结&#xff08;CoGroup&#xff09; (5) 执行任务 代码优化 (1) 时间戳分配 (2) 窗口大小 (3) 输出格式…...

c++对halcon的动态链接库dll封装及调用(细细讲)

七个部分(是个大工程) 一,halcon封装函数导出cpp的内容介绍 二,c++中对halcon环境的配置 三,在配置环境下验证halcon代码 四,dll项目创建+环境配置 五,编辑dll及导出 六,调用打包好的动态链接库的配置 七,进行测试 一,halcon的封装及导出cpp的介绍 1,我这里…...

【优选算法】分治

一&#xff1a;颜色分类 class Solution { public:void sortColors(vector<int>& nums) {// 三指针法int n nums.size();int left -1, right n, i 0;while(i < right){if(nums[i] 0) swap(nums[left], nums[i]);else if(nums[i] 2) swap(nums[--right], num…...

QGraphicsView中鼠标点击与移动事件传递给MainWindow

在Qt图形应用程序开发中,QGraphicsView和QGraphicsScene框架提供了强大的2D图形显示功能。然而,当我们需要在主窗口(MainWindow)中处理这些视图中的鼠标事件。 问题背景 在典型的Qt图形应用程序架构中: MainWindow └── QGraphicsView└── QGraphicsScene└── QGra…...

【图片识别改名】如何批量将图片按图片上文字重命名?自动批量识别图片文字并命名,基于图片文字内容改名,WPF和京东ocr识别的解决方案

应用场景 在日常工作和生活中&#xff0c;我们经常会遇到需要对大量图片进行重命名的情况。例如&#xff0c;设计师可能需要根据图片内容为设计素材命名&#xff0c;文档管理人员可能需要根据扫描文档中的文字对图片进行分类命名。传统的手动重命名方式效率低下且容易出错&…...

RabbitMQ 的高可用性

RabbitMQ 是比较有代表性的&#xff0c;因为是基于主从&#xff08;非分布式&#xff09;做高可用的RabbitMQ 有三种模式&#xff1a;单机模式、普通集群模式、镜像集群模式。 单机模式 单机模式,生产几乎不用。 普通集群模式&#xff08;无高可用性&#xff09; 普通集群模…...

DAY 48 随机函数与广播机制

知识点回顾&#xff1a; 随机张量的生成&#xff1a;torch.randn函数卷积和池化的计算公式&#xff08;可以不掌握&#xff0c;会自动计算的&#xff09;pytorch的广播机制&#xff1a;加法和乘法的广播机制 ps&#xff1a;numpy运算也有类似的广播机制&#xff0c;基本一致 作…...

计算机基础知识(第五篇)

计算机基础知识&#xff08;第五篇&#xff09; 架构演化与维护 软件架构的演化和定义 软件架构的演化和维护就是对架构进行修改和完善的过程&#xff0c;目的就是为了使软件能够适应环境的变化而进行的纠错性修改和完善性修改等&#xff0c;是一个不断迭代的过程&#xff0…...

从零开始制作小程序简单概述

以下是结合案例的“从零制作小红书风格小程序”的全流程指南&#xff0c;采用小红书爆款笔记的结构呈现&#xff0c;并附CSDN参考资源&#x1f447;&#xff1a; 一、核心开发步骤&#xff08;附工具推荐&#xff09; 账号与定位 ✅ 注册类型选择&#xff1a;个人店&#xff08…...

AI架构师修炼之道

1 AI时代的架构革命 与传统软件开发和软件架构师相比&#xff0c;AI架构师面临着三重范式转换&#xff1a; 1.1 技术维度&#xff0c;需处理异构算力调度与模型生命周期管理的复杂性&#xff1b; 1.2 系统维度&#xff0c;需平衡实时性与资源约束的矛盾&#xff1b; 1.3 价…...

三十五、面向对象底层逻辑-Spring MVC中AbstractXlsxStreamingView的设计

在Web应用开发中&#xff0c;大数据量的Excel导出功能是常见需求。传统Apache POI的XSSF实现方式在处理超大数据集时&#xff0c;会因全量加载到内存导致OOM&#xff08;内存溢出&#xff09;问题。Spring MVC提供的AbstractXlsxStreamingView通过流式处理机制&#xff0c;有效…...

Unity的日志管理类

脚本功能&#xff1a; 1&#xff0c;打印日志到控制台 2&#xff0c;显示日志到UI Text 3&#xff0c;将日志写入本地文件 这对unity开发安卓平台来说很有用 using System; using System.IO; using System.Text; using UnityEngine; using UnityEngine.UI;public class FileLo…...

【PhysUnits】17.2 配套变量结构体 Var(variable.rs)

一、源码 这段代码定义了一个泛型结构体 Var&#xff0c;用于封装数值类型并提供各种运算操作。 /** 变量结构体 Var* 该结构体泛型参数 T 需满足 Numeric 约束*/use core::ops::{Neg, Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign}; use crate::constant::Integer;…...

iview组件库:当后台返回到的数据与使用官网组件指定的字段不匹配时,进行修改某个属性名再将response数据渲染到页面上的处理

1、需求导入 当存在前端需要的数据的字段渲染到表格或者是一些公共的表格组件展示数据时的某个字段名与后台返回的字段不一致时&#xff0c;那么需要前端进行稍加处理&#xff0c;而不能直接this.list res.data;这样数据是渲染不出来的。 2、后台返回的数据类型 Datalist(pn) …...

服务器 | Centos 9 系统中,如何部署SpringBoot后端项目?

系列文章目录 虚拟机 | Ubuntu 安装流程以及界面太小问题解决 虚拟机 | Ubuntu图形化系统&#xff1a; open-vm-tools安装失败以及实现文件拖放 虚拟机 | Ubuntu操作系统&#xff1a;su和sudo理解及如何处理忘记root密码 文章目录 系列文章目录前言一、环境介绍二、 使用syst…...