四、函数调用包含单个参数之Double类型-mmword,movsd,mulsd,addsd指令,总结汇编的数据类型

一、汇编代码

上一节开始,讲到了很多debug编译独有的汇编方式,为了更好的区分release的编译器优化和debug的区别,从本章节开始将会提供debug和release的汇编用作对比

Debugb编译

复制代码
single_double_param:
  00000000000000A0: F2 0F 11 44 24 08  movsd       mmword ptr [rsp+8],xmm0
  00000000000000A6: 57                 push        rdi
  00000000000000A7: 48 83 EC 10        sub         rsp,10h
  00000000000000AB: 48 8B FC           mov         rdi,rsp
  00000000000000AE: B9 04 00 00 00     mov         ecx,4
  00000000000000B3: B8 CC CC CC CC     mov         eax,0CCCCCCCCh
  00000000000000B8: F3 AB              rep stos    dword ptr [rdi]
  00000000000000BA: F2 0F 10 44 24 20  movsd       xmm0,mmword ptr [rsp+20h]
  00000000000000C0: F2 0F 59 05 00 00  mulsd       xmm0,mmword ptr [__real@4004000000000000]
                    00 00
  00000000000000C8: F2 0F 58 05 00 00  addsd       xmm0,mmword ptr [__real@3ff4000000000000]
                    00 00
  00000000000000D0: 48 83 C4 10        add         rsp,10h
  00000000000000D4: 5F                 pop         rdi
  00000000000000D5: C3                 ret

Release编译

复制代码
single_double_param:
  0000000000000000: F2 0F 59 05 00 00  mulsd       xmm0,mmword ptr [__real@4004000000000000]
                    00 00
  0000000000000008: F2 0F 58 05 00 00  addsd       xmm0,mmword ptr [__real@3ff4000000000000]
                    00 00
  0000000000000010: C3                 ret

二、汇编分析

1. 栈区空间

和浮点类型类似的同样需要申请16个字节的安全空间,使用的方法也是一样的,同时在release编译中也优化掉了这一部分。详细介绍请看上一章节

复制代码
sub rsp, 10h                    ; 分配16字节栈空间
mov rdi, rsp                    ; rdi指向栈顶
mov ecx, 4                      ; 循环4次
mov eax, 0CCCCCCCCh             ; 初始化值0xCC(调试模式填充)
rep stos dword ptr [rdi]        ; 用0xCC填充栈空间(调试用)

2. Double类型在内存空间的表示

在计算机编程中,double类型(双精度浮点数)的内存空间占用和结构遵循IEEE 754标准,无论系统架构(32位或64位)或编译器类型,double类型始终占用 ​​8字节(64位)内存空间​ ​,这是IEEE 754标准对双精度浮点数的统一规定,与单精度浮点数(float,4字节)和长双精度(long double,通常16字节)形成对比。

double类型的64位内存空间划分为三个部分:

a.符号位(Sign)​​:1位

0表示正数,1表示负数

b. 指数位(Exponent)​​:11位

采用偏移表示法(偏移量1023),实际指数范围为 ​​-1022 到 1023​​,支持表示极大或极小的数值(如±10⁻³⁰⁸ 到 ±10³⁰⁸)

c. 尾数位(Mantissa)​​:52位

存储小数部分,隐含整数位1(规格化数),实际精度为 ​​53位二进制有效数字​ ​,等效约 ​​15--17位十进制有效数字

这部分的计算方式完全和float类型一致,只是不同类型的位数不同

3. mmword

MMWORD 是 ​​x86/x64 汇编语言​ ​中的一种数据类型标识符,主要用于处理 ​​64 位多媒体操作数​​,尤其在 MMX(MultiMedia eXtensions)和 SSE(Streaming SIMD Extensions)指令集中。以下是其核心要点:

a. 数据类型标识

  • MMWORD 在汇编中表示一个 ​64 位(8 字节)的多媒体数据单元​ ,与 __m64(C/C++ 中的 MMX 数据类型)等价
  • 用于明确操作数的位宽和语义,避免与普通整型混淆(如 QWORD 虽同为 64 位,但表示无符号整数)

b. 指令操作对象

常见于 MMX/SSE 指令的操作数中,例如:

复制代码
movq mm0, mmword ptr [ebx]   ; 将内存中 64 位数据加载到 MMX 寄存器 mm0

mmword ptr 修饰内存地址,指明操作数大小为 64 位

拓展:

windows x64汇编中常见的数据单位总结

一、 基础存储单位

|--------------|-----------|------------|---------------------------------|----------------------|
| 单位 | ​​位宽​ | ​​字节数​ | ​​定义​ | 典型应用​ |
| ​​bit | 1位 | 1/8字节 | 最小二进制单元(0或1) | 布尔运算、硬件标志位 |
| Byte | 6位 | 1字节 | 由8个bit组成,存储基本单元 | 字符编码(ASCII)、内存寻址最小单位 |
| Word​ | 16位 | 2字节 | 早期CPU一次处理的数据长度 | 16位系统整数运算(如8086) |
| ​​DWord​ | 32位 | 4字节 | 双字(Double Word),由2个Word组成 | 32位系统整数/指针操作 |
| QWord​ | 64位 | 8字节 | 四字(Quad Word),由4个Word或2个DWord组成 | 64位系统长整型、双精度浮点数 |

💡 ​​关键说明​​:

  • ​Word长度可变性​:在32位系统中,Word可能被定义为32位(如x86架构)
  • ​字节固定性​:1 Byte恒等于8 bit,不受架构影响

二、 多媒体拓展单位(SIMD指令集专用)

|--------------|-----------|----------|--------------|---------------------|
| 单位 | ​​位宽​ | 字节数​ | ​​对应指令集​ | ​​典型应用​ |
| MMWord​ | 64位 | 8字节 | MMX | 早期图像/音频处理(如像素块操作) |
| XMMWord​ | 128位 | 16字节 | SSE/AVX | 向量化浮点运算(如4×32位浮点并行) |

🔬 ​​技术演进​​:

  • ​MMWord​:复用FPU寄存器,操作64位整数
  • ​XMMWord​:SSE引入独立128位寄存器,支持浮点与整型并行计算

4. 逻辑运算指令

该示例中用到了movsd,mulsd,addsd三种64位的浮点数运算

|-----------|---------------|-----------|------------------------------------------------------------|-----------|
| ​​指令​ | ​​操作数格式​ | ​​功能​ | 详细介绍 | 适用场景​ |
| MOVSD | xmm_dest, src | 复制浮点数 | 将 ​​64 位双精度浮点数​​ 从源操作数(内存或 XMM 寄存器)复制到目标操作数(XMM 寄存器) | 加载/存储浮点数据 |
| MULSD | xmm_dest, src | 浮点数乘法 | 将目标 XMM 寄存器中的双精度浮点数 ​​乘以​​ 源操作数(内存或 XMM 寄存器),结果存回目标寄存器 | 标量乘法运算 |
| ADDSD | xmm_dest, src | 浮点数加法 | 将目标 XMM 寄存器中的双精度浮点数 ​​加上​​ 源操作数(内存或 XMM 寄存器),结果存回目标寄存器 | 标量加法运算 |

三、 汇编转化

复制代码
movsd mmword ptr [rsp+8], xmm0  ; 将浮点参数保存到栈[rsp+8]
push rdi                        ; 保存rdi寄存器(被调用者保存)
sub rsp, 10h                    ; 分配16字节栈空间
mov rdi, rsp                    ; rdi指向栈顶
mov ecx, 4                      ; 循环4次
mov eax, 0CCCCCCCCh             ; 初始化值0xCC(调试模式填充)
rep stos dword ptr [rdi]        ; 用0xCC填充栈空间(调试用)
movsd xmm0, mmword ptr [rsp+20h]  ; 从栈[rsp+0x20]加载参数到xmm0
mulsd xmm0, mmword ptr [__real@4004000000000000]  ; 乘以常量2.5(0x400400...)
addsd xmm0, mmword ptr [__real@3ff4000000000000]  ; 加上常量1.25(0x3ff400...)

转化成C语言

复制代码
double single_double_param(double param) {
    // 调试模式下的栈初始化(对应 rep stos 指令),release则会优化掉这部分
    volatile char debug_fill[16]; // 0xCC填充的栈空间

    // 核心计算逻辑(对应 mulsd/addsd)
    return param * 2.5 + 1.25;
}
相关推荐
我在人间贩卖青春4 天前
汇编之伪指令
汇编·伪指令
我在人间贩卖青春5 天前
汇编之伪操作
汇编·伪操作
济6175 天前
FreeRTOS基础--堆栈概念与汇编指令实战解析
汇编·嵌入式·freertos
myloveasuka5 天前
汇编TEST指令
汇编
我在人间贩卖青春5 天前
汇编编程驱动LED
汇编·点亮led
我在人间贩卖青春5 天前
汇编和C编程相互调用
汇编·混合编程
myloveasuka6 天前
寻址方式笔记
汇编·笔记·计算机组成原理
请输入蚊子6 天前
《操作系统真象还原》 第六章 完善内核
linux·汇编·操作系统·bochs·操作系统真像还原
myloveasuka6 天前
指令格式举例
汇编·笔记·计算机组成原理
我在人间贩卖青春7 天前
汇编之分支跳转指令
汇编·arm·分支跳转