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

【汇编逆向系列】三、函数调用包含单个参数之float类型-xmm0寄存器,sub,rep,stos,movss,mulss,addss指令

一、汇编代码

single_float_param:0000000000000060: F3 0F 11 44 24 08  movss       dword ptr [rsp+8],xmm00000000000000066: 57                 push        rdi0000000000000067: 48 83 EC 10        sub         rsp,10h000000000000006B: 48 8B FC           mov         rdi,rsp000000000000006E: B9 04 00 00 00     mov         ecx,40000000000000073: B8 CC CC CC CC     mov         eax,0CCCCCCCCh0000000000000078: F3 AB              rep stos    dword ptr [rdi]000000000000007A: F3 0F 10 44 24 20  movss       xmm0,dword ptr [rsp+20h]0000000000000080: F3 0F 59 05 00 00  mulss       xmm0,dword ptr [__real@3fc00000]00 000000000000000088: F3 0F 58 05 00 00  addss       xmm0,dword ptr [__real@3f000000]00 000000000000000090: 48 83 C4 10        add         rsp,10h0000000000000094: 5F                 pop         rdi0000000000000095: C3                 ret0000000000000096: CC                 int         3

二、汇编分析

1. xmm0寄存器

xmm0 是 Intel x86 架构中 ​​16 个 128 位 XMM 寄存器​​的首个寄存器,属于 SSE(Streaming SIMD Extensions)指令集的核心组件

在这里是在函数调用中传递浮点参数或返回值(如 Windows fastcall 约定),用于函数参数中的第一个浮点型参数

2. movss 指令

movss(Move Scalar Single-Precision Floating-Point)是 SSE 指令集中的关键指令,用于操作单精度浮点数(32 位)。其核心特性如下:

​数据传输​​:将单精度浮点数从源操作数(内存或 XMM 寄存器)复制到目标操作数(XMM 寄存器或内存)的低 32 位

​高位处理​​:目标操作数的高位(96 位)保持不变(若目标为 XMM 寄存器)或忽略(若目标为内存)

3. float类型的内存空间

了解浮点类型传参首先要知道一个浮点类型的数在内存空间内是如何表示的,Float 类型(单精度浮点数)在内存中的存储遵循 ​​IEEE 754 标准​​,占用 ​​4 字节(32 位)​​,其结构分为三个部分:​​符号位(Sign)、指数位(Exponent)和尾数位(Mantissa)​​。以下是详细解析:

部分​比特位​​作用​
​符号位(S)最高位(第 31 位)0 表示正数,1 表示负数。
​指数位(E)​第 30–23 位(8 位)存储​​科学计数法的指数值​​,采用​​偏移编码​​(实际指数 = 存储值 - 127)
​尾数位(M)第 22–0 位(23 位)存储​​规格化后的小数部分​​,隐含整数部分为 1(不直接存储)

数字转换成浮点类型存储

下面以13.625这个数为例说明如何拆解float类型

步骤 1:转换为二进制​
  • ​整数部分 13​:
    13 ÷ 2 = 6...1 → 6 ÷ 2 = 3...0 → 3 ÷ 2 = 1...1 → 1 ÷ 2 = 0...1
    结果为 1101(从最后一个余数向前读)。
  • ​小数部分 0.625​:
    0.625 × 2 = 1.25 → 取整 1,余 0.25
    0.25 × 2 = 0.5 → 取整 0,余 0.5
    0.5 × 2 = 1.0 → 取整 1,余 0
    结果为 .101
  • ​合并​​:13.625 = 1101.101₂。
​步骤 2:规格化(科学计数法)​
  • 移动小数点至首位为 11101.101 → 1.101101 × 2³(左移 3 位)。
  • ​隐含整数 1​:尾数仅存储小数点后的部分 101101(补足 23 位:10110100000000000000000)。
​步骤 3:计算指数位​
  • 实际指数 3 → ​​存储值 = 3 + 127 = 130​​(偏移值 127 是 IEEE 754 固定规则)。
  • 130 的二进制:10000010₂。
​步骤 4:组合三部分​
  • ​符号位​​:0(正数)。
  • ​指数位​​:10000010
  • ​尾数位​​:10110100000000000000000
  • ​完整二进制​​:
    0 10000010 10110100000000000000000 → 十六进制为 0x415A0000

浮点类型转化成数字

下面以0x3FC00000 为例,将二进制转换成浮点数字

步骤一:​​拆分十六进制值
  • 十六进制:3FC00000 → 二进制:0011 1111 1100 0000 0000 0000 0000 0000
  • 按 IEEE 754 标准划分:
  • ​符号位 S​​(1位):0(正数)
  • ​指数位 E​​(8位):01111111(十进制 127)
  • ​尾数位 M​​(23位):10000000000000000000000
步骤二:计算指数偏移值

     实际指数 = E - 127 = 127 - 127 = 0

步骤三:计算尾数值

    尾数隐含整数部分 1(IEEE 754 规范),因此实际尾数为:

 1 + M = 1 + 0.10000000000000000000000₂

 M的二进制小数部分10000000000000000000000转化为10进制,套入公式:

   

  示例:

示例​​(单精度尾数 100000000000011110000000):第 1 位:1×2−1=0.5
第 13–16 位:1×(2−13+2−14+2−15+2−16)≈0.0002289
总和:1+0.5+0.0002289=1.5002289

    二进制小数 0.1₂ = 十进制 0.5(因 1×2⁻¹ = 0.5

       最终尾数 = 1 + 0.5 = 1.5

    步骤四:组合结果

    • 浮点数值 = (-1)^S × 尾数 × 2^{实际指数}
      1 × 1.5 × 2^0
      = ​​1.5​​。

    4. sub指令

    减法指令, sub         rsp,10h 指在rsp栈顶指针上分配16字节的内存空间,栈布局将会进行如下变化

    执行 sub rsp,10h 后:
    +-----------------+ <-- RSP
    | 16字节栈空间    |  // 初始化为 0xCC
    +-----------------+
    | 保存的 RDI      |  // push rdi
    +-----------------+ <-- 原始 RSP
    | 浮点参数        |  // [rsp+8] → [新RSP+20h]
    +-----------------+

    这里有个小细节:

    为什么分配16字节?

    在Debug模式下,编译器可能会分配额外的栈空间,即使这些空间并不完全被使用。这通常是为了:

    1. ​调试方便​​:分配的空间可以用于存储临时变量或用于调试检查(例如用0xCC填充以检测未初始化内存的使用)。
    2. ​栈对齐​​:x86-64架构要求栈在函数调用时保持16字节对齐(特别是在调用某些需要对齐的指令如SSE指令之前)。虽然在这个函数中,分配16字节之前栈已经是16字节对齐的(因为进入函数时RSP是16字节对齐的,然后push rdi(8字节)使RSP变为8字节对齐,再减去16字节(16的倍数)后,RSP又变为16字节对齐),但分配16字节可以确保后续操作满足对齐要求。
    3. ​填充初始化​​:在Debug模式下,编译器可能会分配额外的空间并用特定值(如0xCC)填充,以便在调试时更容易识别未初始化的内存访问。

    为什么用0xCC填充?

    • 0xCC是调试模式下常用的填充值,它有两个作用:
      1. 在调试器中,当程序执行到0xCC时,会触发断点(因为0xCC是int 3指令的机器码)。
      2. 在内存中填充0xCC,如果程序错误地执行了这些区域,会立即触发断点,便于发现错误。
      3. 另外,0xCC在内存中显示为连续的“烫”字(在GBK编码中),便于肉眼识别未初始化内存。

     5. rep指令

    重复前缀,作用​​:根据 ECX(32位)或 RCX(64位)寄存器的值重复执行后续指令,每次执行后计数器减1,直到计数器为

    6. stos指令

    存储字符串指令,将 EAX(32位)或 RAX(64位)寄存器的值存储到 [EDI] 或 [RDI] 指向的内存地址,并根据方向标志(DF)更新指针

    7. 重复操作

      000000000000006B: 48 8B FC           mov         rdi,rsp000000000000006E: B9 04 00 00 00     mov         ecx,40000000000000073: B8 CC CC CC CC     mov         eax,0CCCCCCCCh0000000000000078: F3 AB              rep stos    dword ptr [rdi]

    这几行代码的核心就是rep stos指令, 首先将rsp栈顶指针的地址给到rdi寄存器,给ecx寄存器赋值为4, eax寄存器赋值为0xCCCCCCCC

    req指令为将 stos dword ptr [rdi] 指令重复操作 ecx次,即4次

    stos指令为将eax的数据存储到rdi的地址,即栈顶指针,就是前面sub指令分配的16字节内存内

    8. mulss,addss指令

    故名思意,mulss即将两个数相乘,放在第一个数的地址

    addss则为相加

    9. 内存释放

    在函数结尾处的 add rsp, 10h 指令与函数开头的 sub rsp, 10h 严格对应, 调整栈顶指针的位置。

    三、汇编转化

    single_float_param:0000000000000060: F3 0F 11 44 24 08  movss   dword ptr [rsp+8],xmm0  ; 保存浮点参数到栈0000000000000066: 57                 push    rdi                     ; 保存 RDI0000000000000067: 48 83 EC 10        sub     rsp,10h                 ; 分配 16 字节栈空间000000000000006B: 48 8B FC           mov     rdi,rsp                 ; RDI = 栈顶指针000000000000006E: B9 04 00 00 00     mov     ecx,4                   ; 循环计数 = 40000000000000073: B8 CC CC CC CC     mov     eax,0CCCCCCCCh           ; 填充值 = 0xCC0000000000000078: F3 AB              rep stos dword ptr [rdi]        ; 用 0xCC 填充栈空间000000000000007A: F3 0F 10 44 24 20  movss   xmm0,dword ptr [rsp+20h] ; 加载参数到 XMM00000000000000080: F3 0F 59 05 00 00  mulss   xmm0,dword ptr [__real@3fc00000] ; 乘以 1.5f0000000000000088: F3 0F 58 05 00 00  addss   xmm0,dword ptr [__real@3f000000] ; 加上 0.5f0000000000000090: 48 83 C4 10        add     rsp,10h                 ; 释放栈空间0000000000000094: 5F                 pop     rdi                     ; 恢复 RDI0000000000000095: C3                 ret                             ; 返回结果

    其中很大部分的操作都是debug调试添加的,release都会优化掉,优化后即:

    Release 模式优化版本
    mulss xmm0, [__real@3fc00000]
    addss xmm0, [__real@3f000000]
    ret

    转化为C语言:

    // 函数声明
    float single_float_param(float param);// 实际实现
    float single_float_param(float param) {// Debug 模式专用:分配并初始化栈空间volatile unsigned char stack_buf[16]; for (int i = 0; i < sizeof(stack_buf); i++) {stack_buf[i] = 0xCC; // 调试填充值}// 实际计算:1.5 * param + 0.5float result = param * 1.5f + 0.5f;return result;
    }

    相关文章:

    【汇编逆向系列】三、函数调用包含单个参数之float类型-xmm0寄存器,sub,rep,stos,movss,mulss,addss指令

    一、汇编代码 single_float_param:0000000000000060: F3 0F 11 44 24 08 movss dword ptr [rsp8],xmm00000000000000066: 57 push rdi0000000000000067: 48 83 EC 10 sub rsp,10h000000000000006B: 48 8B FC mov …...

    JAVA开发工具——IntelliJ IDEA

    JAVA开发工具——IntelliJ IDEA 软件下载地址https://www.jetbrains.com/idea/ IDEA项目结构介绍 项目&#xff08;project&#xff09;模块&#xff08;module&#xff09;包&#xff08;package&#xff09;类&#xff08;class) 包含关系&#xff1a;项目 > 模块 >…...

    基于fpga的疲劳驾驶检测

    基于fpga的疲劳驾驶检测 前言一、系统硬件设计二、系统软件设计系统上板实验测试 前言 代码基于网络大佬代码进行修改的。限制性比较大&#xff0c;不太灵活&#xff0c;当个本科毕业设计还是够的。 基于FPGA的疲劳检测模块硬件设计以FPGA核心控制模块为中心&#xff0c;通过…...

    感谢阿里云RDS产品及时的“光速服务”

    ❝ 开头还是介绍一下群&#xff0c;如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, OceanBase, Sql Server等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;&#xff08;共3000人左右…...

    从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(十一)

    下载buildroot https://buildroot.org/download.html下载交叉工具链 使用ST官方交叉工具链的话&#xff0c;在buildroot配置外部工具会有问题&#xff0c;所以直接使用正点原子的交叉编译工具 buildroot构建根文件系统 - 参考正点原子 配置 buildroot tar -vxf buildroot-20…...

    18-Oracle 23ai JSON二元性颠覆传统

    在当今百花齐放的多模型数据库时代&#xff0c;开发人员常在关系型与文档型数据库间艰难取舍。Oracle Database 23ai推出的JSON关系二元性&#xff08;JSON Relational Duality&#xff09;​​ 和二元性视图&#xff08;Duality Views&#xff09;​​ 创新性地统一了两者优势…...

    Linux68 FTP 测试 上传下载

    6.在vi编辑器里&#xff0c;哪个命令能将光标移到第200行&#xff1f;&#xff08; B &#xff09; 7.A、200g B、:200 C、g200 D、G200 假如您需要找出 /etc/my.conf 文件属于哪个包 (package) &#xff0c;您可以执行&#xff08; D &#xff09;C A、 rpm -q /etc/my.co…...

    山东大学《数据可视化》期末复习宝典

    &#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a;&#x1f3c0;山东大学期末速通专用_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1…...

    【Elasticsearch】映射:Join 类型、Flattened 类型、多表关联设计

    映射&#xff1a;Join 类型、Flattened 类型、多表关联设计 1.Join 类型1.1 主要应用场景1.1.1 一对多关系建模1.1.2 多层级关系建模1.1.3 需要独立更新子文档的场景1.1.4 文档分离但需要关联查询 1.2 使用注意事项1.3 与 Nested 类型的区别 2.Flattened 类型2.1 实际运用场景和…...

    SpringBoot十二、SpringBoot系列web篇之过滤器Filte详解

    一、前言 JavaWeb三大组件Servlet、Filter、Listener&#xff0c;其中之一便是过滤器Filter。 其实&#xff0c;Filter我们平常用的不多&#xff0c;一般多为项目初期搭建web架构的时候使用&#xff0c;后面用的就少了&#xff0c;在日常业务开发中不太可能碰到需要手写Filte…...

    【RTSP从零实践】1、根据RTSP协议实现一个RTSP服务

    &#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…...

    行为设计模式之Iterator(迭代器)

    行为设计模式之Iterator&#xff08;迭代器&#xff09; 摘要&#xff1a; 迭代器模式(Iterator)是一种行为设计模式&#xff0c;它提供顺序访问聚合对象元素的方法&#xff0c;同时不暴露内部结构。该模式由迭代器接口(Iterator)、具体迭代器(ConcreteIterator)、聚合接口(Ag…...

    FPGA点亮ILI9488驱动的SPI+RGB接口LCD显示屏(一)

    FPGA点亮ILI9488驱动的SPIRGB接口LCD显示屏 ILI9488 RGB接口初始化 目录 前言 一、ILI9488简介 二、3线SPI接口简介 三、配置寄存器介绍 四、手册和初始化verilog FPGA代码 总结 前言 ILI9488是一款广泛应用于嵌入式系统和电子设备的彩色TFT LCD显示控制器芯片。本文将介…...

    ​​​​​​​6板块公共数据典型应用场景【政务服务|公共安全|公共卫生|环境保护|金融风控|教育科研]

    1. 政务服务 1.1 城市规划与管理 公共数据在城市规划与管理中可发挥关键作用。通过汇聚自然资源、建筑物、人口分布等基础数据,构建数字孪生城市模型,辅助城市总体规划编制、决策仿真模拟。在城市基础设施建设、安全运营、应急管理等方面,公共数据也是不可或缺的基础支撑。例…...

    如何实现本地mqtt服务器和云端服务器同步?

    有时候&#xff0c;一个物联网项目&#xff0c;A客户想要本地使用&#xff0c;B客户想要线上使用&#xff0c;C客户想要本地部署&#xff0c;当有网环境时能线上使用。这个时候就需要本地MQTT服务和线上MQTT服务能相互自动转发。 后来经我一翻研究&#xff0c;其实Activemq支持…...

    windows10下搭建nfs服务器

    windows10下搭建nfs服务器 有参考这篇博客 Windows10搭建NFS服务 - fuzidage - 博客园 下载 NFS Server这个app 通过网盘分享的文件&#xff1a;nfs1268 (1).exe 链接: https://pan.baidu.com/s/1rE4h710Uh-13kWGXvjkZzw 提取码: mwa4 --来自百度网盘超级会员v5的分享 下载后…...

    CSS中justify-content: space-between首尾贴边中间等距(两端元素紧贴左右边缘,中间元素等距均匀分布)

    justify-content: space-between; 是 CSS Flexbox 布局中的一个属性值&#xff0c;主要作用是在弹性容器的主轴方向上均匀分布子元素&#xff0c;具有以下核心特性&#xff1a; 作用效果&#xff1a; 首尾贴边 第一个子元素紧贴容器起始端 最后一个子元素紧贴容器结束端 中…...

    【知识扫盲】分布式系统架构或分布式服务中的管理面,数据面和业务面

    &#x1f9e9; 一、三大“面”的定义与职责&#xff08;以大模型推理平台为例&#xff09; 层级英文名职责关键组件举例数据面Data Plane处理用户请求、模型推理、输入输出数据转换等核心任务模型服务引擎、Tokenizer/Detokenizer、推理加速器&#xff08;TensorRT、ONNX Runt…...

    华为云Flexus+DeepSeek征文|Dify - LLM 云服务单机部署大语言模型攻略指南

    前言&#xff1a;在当今人工智能快速发展的时代&#xff0c;华为云推出的 Dify - LLM 对话式 AI 开发平台为企业和开发者提供了便捷的大语言模型应用开发解决方案。 通过在华为云 Flexus 云服务器上单机部署 Dify&#xff0c;并成功集成 DeepSeek 模型&#xff0c;我们能够快速…...

    Python爬虫:trafilatura 的详细使用(快速提取正文和评论以及结构,转换为 TXT、CSV 和 XML)

    更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、trafilatura 概述1.1 trafilatura介绍1.2 亮点特色1.3 安装二、基本使用2.1 从URL直接提取内容2.2 输出格式控制2.3 从HTML字符串提取2.4 使用命令行工具三、高级功能3.1 全局设置3.2 提取参数定制3.3 多线程批量处…...

    Cursor 工具项目构建指南: Uniapp Miniprogram 环境下的 Prompt Rules 约束

    简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 Cursor 工具项目构建指南: Uniapp Miniprogram 环境下的 Prompt Rules 约束前言项目简…...

    JAVA反序列化应用 : URLDNS案例

    反序列化的基本原理 基础普及 &#xff1a; 对象初始化数据方法 &#xff1a;1、使用构造方法 2、使用封装中的 set,get方法 这边我们就使用 1 注意 我们之后还需要进行 接入 序列化的接口 &#xff1a; 先进行序列化 &#xff1a; 反序列化&#xff1a; 反序列化导致的安…...

    Vue-Leaflet地图组件开发(三)地图控件与高级样式设计

    第三篇&#xff1a;Vue-Leaflet地图控件与高级样式设计 1. 专业级比例尺组件实现 1.1 比例尺控件集成 import { LControl } from "vue-leaflet/vue-leaflet";// 在模板中添加比例尺控件 <l-control-scaleposition"bottomleft":imperial"false&qu…...

    174页PPT家居制造业集团战略规划和运营管控规划方案

    甲方集团需要制定一个清晰的集团价值定位&#xff0c;从“指引多元”、“塑造 能力”以及“强化协同”等方面引领甲方做大做强 集团需要通过管控模式、组织架构及职能、授权界面、关键流程、战略 实施和组织演进路径&#xff0c;平衡风险控制和迅速发展&#xff0c;保证战略落地…...

    wsl开启即闪退

    [ 问题 ]&#xff1a; 在一次电脑卡住&#xff0c;强制关机重启后&#xff0c;遇到打开WSL就闪退的问题在CMD中打开WSL&#xff0c;出现如上图的描述&#xff1a; C:\Users\admin>wsl wsl: 检测到 localhost 代理配置&#xff0c;但未镜像到 WSL。NAT 模式下的 WSL 不支持…...

    Spark 写文件

    Repartition Spark 输出文件数量 假设每个 Task 的输出数据都包含了全部 8 个分区值,那么最终的文件生成情况如下: 总文件数 = Task 数量 分区组合数 假设: ​Task 数量​:200 ​分区组合数​:8 个 (from_cluster 和 ds 的组合) 则: ​总文件数​:200 8 = ​1600 …...

    PostgreSQL 的扩展pg_prewarm

    PostgreSQL 的扩展pg_prewarm pg_prewarm 是 PostgreSQL 提供的一个实用扩展&#xff0c;用于将数据预先加载到共享缓冲区或操作系统缓存中&#xff0c;从而提升查询性能。 一、扩展概述 核心功能 手动预热&#xff1a;将指定的表或索引数据加载到内存自动预热&#xff1a;…...

    F5 – TCP 连接管理:会话、池级和节点级操作

    在 F5 BIG-IP 中,您可以在池成员级别或节点级别管理流向服务器的流量。节点级别状态会影响与该节点关联的所有池,而池成员状态则仅限于单个池。了解每种方法以及何时使用它们对于顺利进行维护窗口和流量管理至关重要。 池级状态:启用、禁用、强制离线、移除 在 BIG-IP 配置…...

    金融预测模型开发:数据预处理、机器学习预测与交易策略优化

    金融预测模型开发:数据预处理、机器学习预测与交易策略优化 概述 本文将详细介绍一个完整的金融预测模型开发流程,包含数据预处理、机器学习预测和交易策略优化三个核心模块。我们使用Python实现一个端到端的解决方案,适用于股票价格预测和量化交易策略开发。 # 导入必要…...

    【P2P】直播网络拓扑及编码模式

    以下从 P2P 直播的常见拓扑模式出发,分析各种方案的特点与适用场景,并给出推荐。 一、P2P 直播的核心挑战 实时性要求高 直播场景下,延迟必须控制在可接受范围(通常 <2 秒),同时要保证画面连贯、不卡顿。带宽分布不均 每个节点(观众)上传带宽与下载带宽差异较大,且…...