x86/x64汇编基础18.汇编基础14:浮点运算指令-汇编语言社区论坛-技术社区-学技术网

x86/x64汇编基础18.汇编基础14:浮点运算指令

笔记

学习最新前沿软件逆向安全技术、游戏安全辅助脚本技术,B 站 小迪 xiaodi 老师

微信 i-xiaodi ,备用微信Binary_uncle_

作业:看完视频独立把实验程序练习完,分析流程

处理浮点数的运算

简单了解,不强制记忆,忘了就查笔记

1. FPU(Floating Point Unit,浮点运算单元)

  • 定义: FPU 是处理器中的一个硬件模块,专门负责浮点运算
  • 功能: 处理浮点数的加减乘除、平方根、三角函数等复杂操作。
  • 实现:
    • 在早期 x86 处理器中,FPU 是一个独立的协处理器(如 Intel 8087)。
    • 从 80486 开始,FPU 集成进了 CPU 内核中。

FPU 的组成

  • 寄存器堆栈:
    • 8 个 80 位宽的浮点寄存器(ST0-ST7),以堆栈形式组织
    • 通过 pushpop 模式操作寄存器。
  • 状态寄存器: 用于保存堆栈状态(如堆栈深度)和计算标志(如 C0-C3)。
  • 控制寄存器: 配置 FPU 的工作模式(如精度、舍入模式等)。

2.x87 指令集

  • 定义: x87 是专门为 FPU 设计的一套指令集,早期专用于处理浮点运算。
  • 特点:
    • 操作对象是 FPU 的堆栈寄存器(ST0-ST7)。
    • 指令风格通常是 Fxxx 开头,比如 FLD(加载浮点数)、FADD(浮点加法)
    • 支持扩展精度(80 位),比 SSE 的单精度和双精度浮点数更高。
  • 代表指令:
    • FLD(load) / FST: 加载/存储浮点数。
    • FADD / FSUB: 浮点加法/减法。
    • FMUL / FDIV: 浮点乘法/除法。
    • FCOM / FUCOM: 比较浮点数。

x87 的适用场景

  • 高精度计算(如科学计算)。
  • 需要 80 位扩展精度支持的场景。

3. SSE(Streaming SIMD Extensions)

  • 定义: SSE 是 Intel 在 x86 处理器上引入的一套 SIMD(单指令多数据)扩展指令集
  • 特点:
    • 采用 xmm 寄存器(每个 128 位宽)。
    • 支持并行处理多个单精度(32 位)或双精度(64 位)浮点数。
    • 指令风格是 xxxPS(处理单精度矢量)或 xxxSD(处理双精度标量)
  • 优势:
    • 更快的浮点计算(无需堆栈操作)
    • 并行处理多个浮点数,提高性能。

SSE 的适用场景

  • 并行计算(如多媒体、游戏、音视频处理)。
  • 性能要求较高但不需要扩展精度的场景。

总结关系

  1. FPU 是硬件模块,x87 是它的指令集:
    • FPU 是处理器的物理单元。
    • x87 是针对 FPU 提供的指令集。
  1. SSE 是独立于 FPU 的 SIMD 指令集:
    • SSE 使用的是独立的 xmm 寄存器
    • 它不依赖 FPU,也不与 x87 堆栈共享资源。

1. 浮点堆栈概念

x86 浮点指令通常操作的是浮点单元(FPU)的寄存器堆栈。

FPU(Floating Point Unit,浮点运算单元):

是计算机处理器中的一种专门用于处理浮点数运算的硬件模块。它主要负责执行涉及小数或非整数值的数学计算,例如加减乘除、平方根、三角函数等复杂操作。

  • FPU 使用一个 8 级的堆栈架构(ST(0)ST(7)
  • 堆栈顶通常表示为 ST(0),是 FPU 操作的默认目标

x32dbg 中,FPU 浮点运算的反汇编指令 如下所示:

实验程序说明:3.1 + 4.3 单浮点小数


1. 浮点加载指令 (FLD)

FLD 指令的全称是 “Floating-Point Load”

常见情形:

  1. 从内存加载到堆栈顶:
FLD DWORD PTR ss:[ebp-4]       ; 加载单精度浮点数
FLD QWORD PTR ss:[ebp-8]       ; 加载双精度浮点数
FLD TBYTE PTR ss:[ebp-0C]      ; 加载 10 字节扩展精度浮点数
  1. 从寄存器加载(堆栈的相对位置):
FLD ST(1)                      ; 将 ST(1) 的值复制到 ST(0)
  1. 反汇编形式补充 ST(0)
    • x32dbg 可能显示为:
FLD ST(0), DWORD PTR ss:[ebp-4]

实际行为是 FLD DWORD PTR ss:[ebp-4],只是一种伪表示。


为什么存进去数据不一样了?

图片[1]-x86/x64汇编基础18.汇编基础14:浮点运算指令-汇编语言社区论坛-技术社区-学技术网

这是因为 FPU 的内部扩展机制

  1. 0x40466666 的含义:
    • 这个值是按照 IEEE 754 单精度格式编码的。
    • 它的二进制表示为:
符号位:0
指数部分:10000000 (偏移量 127,对应指数为 2)
尾数部分:0.10011001100110011001100

解码为:

图片[2]-x86/x64汇编基础18.汇编基础14:浮点运算指令-汇编语言社区论坛-技术社区-学技术网

FPU 的内部存储格式:

  • FLD 指令会将单精度浮点数转换为 80 位扩展精度格式(内部格式)。
  • 在扩展精度格式中,3.1 的值表示为:
符号位:0
指数部分:16384 (偏移量 16383,对应指数为 2)
尾数部分:1.C6666666...

转换结果是:

图片[3]-x86/x64汇编基础18.汇编基础14:浮点运算指令-汇编语言社区论坛-技术社区-学技术网

这是扩展精度的表示方式。

  • mov dword ptr ss:[ebp-0x4], 0x40466666 将 IEEE 754 单精度浮点值 3.1 的二进制表示存入内存。
  • 使用 FLD 加载这个值后,FPU 会将其扩展为 80 位浮点格式。
  • 因此,ST(0) 的值看似与 0x40466666 不一致,但它实际上表示的是相同的浮点数 3.1

图片[4]-x86/x64汇编基础18.汇编基础14:浮点运算指令-汇编语言社区论坛-技术社区-学技术网

2. 浮点存储指令 (FST/FSTP)

FST“Floating-Point Store”

  • 功能:将浮点堆栈顶部(ST(0))的值存储到指定的内存位置或寄存器中。
  • 操作:只存储堆栈顶部的浮点数,并保持该值在堆栈顶部。

FSTP“Floating-Point Store and Pop”

  • 功能:将浮点堆栈顶部(ST(0))的值存储到指定的内存位置或寄存器中,并且弹出堆栈顶部的值,即将堆栈指针移动到下一个值
  • 操作:存储堆栈顶部的浮点数,并将堆栈指针向下移动,弹出该值。

常见情形:

  1. 将堆栈顶的值存储到内存:
FST DWORD PTR ss:[ebp-4]       ; 将 ST(0) 的值存储为单精度浮点数
FSTP QWORD PTR ss:[ebp-8]      ; 将 ST(0) 的值存储为双精度浮点数,并弹出堆栈
FSTP TBYTE PTR ss:[ebp-0C]     ; 将 ST(0) 的值存储为扩展精度浮点数,并弹出堆栈
  1. 将堆栈顶的值存储到其他堆栈寄存器:
FST ST(1)                      ; 将 ST(0) 的值复制到 ST(1)
FSTP ST(2)                     ; 将 ST(0) 的值复制到 ST(2),并弹出堆栈

3. 浮点算术运算

常见情形:

  1. 基本运算:加减乘除
FADD DWORD PTR ss:[ebp-4]      ; 将 [ebp-4] 加到 ST(0)
FSUB QWORD PTR ss:[ebp-8]      ; 将 [ebp-8] 减去 ST(0)
FMUL ST(0), ST(1)              ; 将 ST(0) 与 ST(1) 相乘
FDIV ST(1), ST(0)              ; 将 ST(1) 除以 ST(0)
  1. 反汇编伪表示:
    • x32dbg 有时将隐式堆栈寄存器显式显示:
FADD ST(0), QWORD PTR ss:[ebp-8]

4. 浮点比较

常见情形:

  1. 直接比较:
FCOM DWORD PTR ss:[ebp-4]      ; 比较 ST(0) 与 [ebp-4]
FCOM ST(1)                     ; 比较 ST(0) 与 ST(1)
  1. 带弹出的比较:
FCOMP DWORD PTR ss:[ebp-4]     ; 比较后弹出 ST(0)
FCOMP ST(1)                    ; 比较 ST(0) 和 ST(1),然后弹出 ST(0)

 

FSTSW 指令

功能

FSTSW 用于将 FPU 的状态字(FPU Status Word)复制到通用寄存器(AX)或内存中。

语法

AX: 将状态字存储到通用寄存器 AX 中。
[mem]: 将状态字存储到内存地址 [mem]。

图片[5]-x86/x64汇编基础18.汇编基础14:浮点运算指令-汇编语言社区论坛-技术社区-学技术网
常见用法:

获取状态字到 AX:

FSTSW AX

将 FPU 状态字复制到通用寄存器 AX。

获取状态字到内存:

FSTSW [mem]

将状态字存储到内存地址 [mem]。

结合 FCOMP 使用: 一般与 FCOMP 一起使用,完成浮点数比较并获取比较结果:

FCOMP QWORD PTR [mem]   ; 比较 ST(0) 和内存中的双精度数
FSTSW AX                ; 将状态字加载到 AX
SAHF                    ; 将状态字的高 8 位加载到 FLAGS 寄存器
JZ equal_label          ; 根据 ZF 判断是否相等

 

 


5. 浮点堆栈控制

常见情形:

  1. 交换堆栈寄存器:
FXCH ST(1)                     ; 交换 ST(0) 和 ST(1)
  1. 清除堆栈:
FINIT                           ; 初始化 FPU 状态,清空堆栈

6. 特殊指令

常见情形:

  1. 正弦/余弦/平方根:
FSQRT                          ; 计算 ST(0) 的平方根
FSIN                           ; 计算 ST(0) 的正弦值
FCOS                           ; 计算 ST(0) 的余弦值
  1. 加载常量:
FLD1                           ; 加载 1.0 到 ST(0)
FLDZ                           ; 加载 0.0 到 ST(0)
fldpi  												 ; 加载圆周率 π
  1. 取反:
FCHS                           ; 将 ST(0) 取反

 

扩展 SSE 指令集<———————–

在 x86 汇编中,xmm 寄存器属于 SSE(Streaming SIMD Extensions)指令集的一部分,它们用于处理矢量和标量浮点运算,支持更高效的并行计算。与 x87 的堆栈式 FPU 不同,SSE 使用寄存器直接寻址,寄存器名字如 xmm0xmm1等。以下是对常见 xmm 寄存器操作指令及用法的详细讲解。


xmm 寄存器简介

  • 每个 xmm 寄存器大小为 128 位,可以存储以下内容:
    • 4 个单精度浮点数(32 位)
    • 2 个双精度浮点数(64 位)
    • 16 个字节(8 位)数据
    • 其他整数或逻辑数据格式
  • 常见指令可以操作标量(单个浮点数)或矢量(多个浮点数)。

常见指令及用法

1. MOVAPS / MOVUPS

功能: 将数据在内存和 xmm 寄存器之间传输。

指令

描述

MOVAPS xmm0, xmm1

复制对齐的单精度浮点数向量数据到寄存器 xmm0 中。

MOVUPS xmm0, xmm1

复制未对齐的单精度浮点数向量数据到寄存器 xmm0 中。

MOVAPS xmm0, [mem]

从对齐的内存地址加载单精度浮点数数据到 xmm0 中。

MOVUPS xmm0, [mem]

从未对齐的内存地址加载单精度浮点数数据到 xmm0 中。

  • 对齐与未对齐:
    • 对齐(MOVAPS: 数据必须位于内存地址的 16 字节边界上,否则会导致崩溃。
    • 未对齐(MOVUPS: 无需满足 16 字节对齐,但性能稍差。

什么是内存对齐?

  • 对齐(Aligned): 数据的地址是其大小的倍数。例如:
    • 4 字节的数据存储在地址是 4 的倍数的地方(如 0x1004)。
    • 16 字节(128 位)的 SSE 寄存器数据存储在地址是 16 的倍数的地方(如 0x1010)。
  • 未对齐(Unaligned): 数据的地址不是其大小的倍数。例如:
    • 4 字节的数据存储在地址 0x1005。
    • 16 字节的数据存储在地址 0x1013。

例子

MOVAPS xmm0, [ebp-0x10]  ; 加载 4 个对齐的浮点数到 xmm0。
MOVUPS xmm1, [ebp-0x20]  ; 加载未对齐的浮点数到 xmm1。
MOVAPS [ebp-0x30], xmm0  ; 存储 xmm0 的数据到对齐的内存地址。

2. ADDPS / ADDSD

功能: 执行浮点加法。

  • ADDPS: 对矢量(多个单精度浮点数)执行并行加法。
  • ADDSD: 对标量(单个双精度浮点数)执行加法。

指令

描述

ADDPS xmm0, xmm1

xmm0xmm1 中的 4 个单精度浮点数逐元素相加。

ADDSD xmm0, xmm1

xmm1 的标量(双精度浮点数)加到 xmm0 上。

例子

结果:
xmm0[0] = xmm0[0] + xmm1[0]  // 第1个元素相加
xmm0[1] = xmm0[1] + xmm1[1]  // 第2个元素相加
xmm0[2] = xmm0[2] + xmm1[2]  // 第3个元素相加
xmm0[3] = xmm0[3] + xmm1[3]  // 第4个元素相加

计算后结果存储在 xmm0 中。

ADDPS xmm0, xmm1        ; xmm0[i] += xmm1[i], i = 0..3
ADDSD xmm0, xmm1        ; xmm0[0] += xmm1[0], 仅操作第一个双精度数

3. MULPS / MULSD

功能: 执行浮点乘法。

  • MULPS: 对矢量进行并行乘法。
  • MULSD: 对标量进行单一乘法。

指令

描述

MULPS xmm0, xmm1

xmm0xmm1 的矢量浮点数逐元素相乘。

MULSD xmm0, xmm1

xmm1 的标量乘到 xmm0 上。

例子

MULPS xmm0, xmm1        ; xmm0[i] *= xmm1[i], i = 0..3
MULSD xmm0, xmm1        ; xmm0[0] *= xmm1[0], 仅操作第一个双精度数

4. DIVPS / DIVSD

功能: 执行浮点除法。

  • DIVPS: 对矢量进行并行除法。
  • DIVSD: 对标量进行单一除法。

指令

描述

DIVPS xmm0, xmm1

xmm0xmm1 的矢量浮点数逐元素相除。

DIVSD xmm0, xmm1

xmm1 的标量除到 xmm0 上。


5. CMPPS / CMPSD

功能: 比较浮点数。

  • CMPPS: 对矢量进行并行比较。
  • CMPSD: 对标量进行单一比较。

指令

描述

CMPPS xmm0, xmm1, imm8

imm8 指定的条件比较两个矢量的浮点数。

CMPSD xmm0, xmm1, imm8

imm8 指定的条件比较两个标量的浮点数。

  • imm8 是比较条件,例如:
    • 0: 等于(EQ)。
    • 1: 小于(LT)。
    • 2: 小于等于(LE)。

6. SQRTPS / SQRTSD

功能: 计算平方根。

  • SQRTPS: 对矢量计算平方根。
  • SQRTSD: 对标量计算平方根。

指令

描述

SQRTPS xmm0

计算 xmm0 中每个元素的平方根。

SQRTSD xmm0

计算 xmm0 中标量元素的平方根。


7. MINPS / MAXPS

功能: 计算最小值或最大值。

  • MINPS: 对矢量计算逐元素最小值。
  • MAXPS: 对矢量计算逐元素最大值。

x32dbg 中查看 xmm 寄存器

x32dbg 中,你可以通过以下步骤查看 xmm 寄存器的值:

  1. 在调试过程中,单步执行到包含 xmm 操作的指令。
  2. 打开寄存器窗口(通常默认显示在调试界面的右侧)。
  3. 找到 xmm0 ~ xmm15 的寄存器值。
  • 32 位模式(x86):
  • SSE 寄存器:XMM0-XMM7
  • 64 位模式(x64):
  • 扩展 SSE 寄存器:XMM0-XMM15
  1. 观察每个寄存器的 128 位数据,通常以 16 字节的十六进制显示。

简单课外了解:AVX(Advanced Vector Extensions)指令集

以下是 YMM 寄存器常用的 AVX 指令,分为不同的类别列出,方便理解和参考:


1. 数据加载和存储

这些指令用于将数据加载到 YMM 寄存器或从 YMM 寄存器存储到内存。

指令

描述

VMOVAPS

加载/存储对齐的 256 位单精度浮点数到 YMM。

VMOVUPS

加载/存储未对齐的 256 位单精度浮点数到 YMM。

VMOVAPD

加载/存储对齐的 256 位双精度浮点数到 YMM。

VMOVUPD

加载/存储未对齐的 256 位双精度浮点数到 YMM。

VMOVDQA

加载/存储对齐的 256 位整数数据到 YMM。

VMOVDQU

加载/存储未对齐的 256 位整数数据到 YMM。

VBROADCASTSS

将内存中的单个单精度浮点数广播到 YMM 的所有元素。

VBROADCASTSD

将内存中的单个双精度浮点数广播到 YMM 的所有元素。


2. 算术运算

AVX 支持对 YMM 寄存器中的向量进行算术运算。

单精度浮点运算(32 位 × 8)

指令

描述

VADDPS

对两个 YMM 寄存器中的 8 个单精度浮点数逐元素相加。

VSUBPS

对两个 YMM 寄存器中的 8 个单精度浮点数逐元素相减。

VMULPS

对两个 YMM 寄存器中的 8 个单精度浮点数逐元素相乘。

VDIVPS

对两个 YMM 寄存器中的 8 个单精度浮点数逐元素相除。

VSQRTPS

计算 YMM 寄存器中的 8 个单精度浮点数的平方根。

双精度浮点运算(64 位 × 4)

指令

描述

VADDPD

对两个 YMM 寄存器中的 4 个双精度浮点数逐元素相加。

VSUBPD

对两个 YMM 寄存器中的 4 个双精度浮点数逐元素相减。

VMULPD

对两个 YMM 寄存器中的 4 个双精度浮点数逐元素相乘。

VDIVPD

对两个 YMM 寄存器中的 4 个双精度浮点数逐元素相除。

VSQRTPD

计算 YMM 寄存器中的 4 个双精度浮点数的平方根。

整数运算

指令

描述

VPADDD

对两个 YMM 寄存器中的 8 个 32 位整数逐元素相加。

VPSUBD

对两个 YMM 寄存器中的 8 个 32 位整数逐元素相减。

VPADDQ

对两个 YMM 寄存器中的 4 个 64 位整数逐元素相加。

VPSUBQ

对两个 YMM 寄存器中的 4 个 64 位整数逐元素相减。


3. 逻辑运算

这些指令执行按位逻辑操作。

指令

描述

VANDPS

对两个 YMM 寄存器中的 8 个单精度浮点数按位与。

VORPS

对两个 YMM 寄存器中的 8 个单精度浮点数按位或。

VXORPS

对两个 YMM 寄存器中的 8 个单精度浮点数按位异或。

VANDPD

对两个 YMM 寄存器中的 4 个双精度浮点数按位与。

VORPD

对两个 YMM 寄存器中的 4 个双精度浮点数按位或。

VXORPD

对两个 YMM 寄存器中的 4 个双精度浮点数按位异或。


4. 比较操作

比较指令可以用来逐元素比较向量中的值。

指令

描述

VCMPPS

对两个 YMM 寄存器中的 8 个单精度浮点数逐元素比较。

VCMPPD

对两个 YMM 寄存器中的 4 个双精度浮点数逐元素比较。

VPCMPGTD

对两个 YMM 寄存器中的 8 个有符号整数逐元素比较。

VPCMPGTQ

对两个 YMM 寄存器中的 4 个有符号整数逐元素比较。


5. 数据混合与选择

用于对数据向量进行混合或选择操作。

指令

描述

VBLENDPS

按掩码从两个 YMM 寄存器中混合单精度浮点数。

VBLENDPD

按掩码从两个 YMM 寄存器中混合双精度浮点数。

VSHUFPS

按模式选择并混合单精度浮点数。

VSHUFPD

按模式选择并混合双精度浮点数。


6. 数据转换

用于类型转换或压缩、扩展数据。

指令

描述

VCVTDQ2PS

将 YMM 中的 8 个 32 位整数转换为单精度浮点数。

VCVTPS2DQ

将 YMM 中的 8 个单精度浮点数转换为 32 位整数。

VCVTPS2PD

将 8 个单精度浮点数转换为 4 个双精度浮点数。

VCVTPD2PS

将 4 个双精度浮点数转换为 8 个单精度浮点数。


常见的 YMM 寄存器 AVX 指令用法

 


1. 数据加载与存储

用于从内存加载数据到 YMM 寄存器,或将寄存器中的数据存储回内存。

; 加载对齐数据
VMOVAPS YMM0, [dataAligned]
; 存储对齐数据
VMOVAPS [resultAligned], YMM0

; 加载未对齐数据
VMOVUPS YMM1, [dataUnaligned]
; 存储未对齐数据
VMOVUPS [resultUnaligned], YMM1

; 广播单精度值到所有元素
VBROADCASTSS YMM2, [singleValue]

; 广播双精度值到所有元素
VBROADCASTSD YMM3, [doubleValue]

2. 算术运算

YMM 寄存器中每 32 位(单精度浮点数)或 64 位(双精度浮点数)逐元素运算。

单精度浮点运算(8 个元素)

; 加法:YMM0 = YMM1 + YMM2
VADDPS YMM0, YMM1, YMM2
; 减法:YMM0 = YMM1 - YMM2
VSUBPS YMM0, YMM1, YMM2
; 乘法:YMM0 = YMM1 * YMM2
VMULPS YMM0, YMM1, YMM2
; 除法:YMM0 = YMM1 / YMM2
VDIVPS YMM0, YMM1, YMM2

双精度浮点运算(4 个元素)

; 加法:YMM0 = YMM1 + YMM2
VADDPD YMM0, YMM1, YMM2
; 减法:YMM0 = YMM1 - YMM2
VSUBPD YMM0, YMM1, YMM2
; 乘法:YMM0 = YMM1 * YMM2
VMULPD YMM0, YMM1, YMM2
; 平方根:YMM0 = sqrt(YMM1)
VSQRTPD YMM0, YMM1

3. 逻辑运算

对 YMM 寄存器中的每一位进行逻辑操作。

; 按位与:YMM0 = YMM1 & YMM2
VANDPS YMM0, YMM1, YMM2
; 按位或:YMM0 = YMM1 | YMM2
VORPS YMM0, YMM1, YMM2
; 按位异或:YMM0 = YMM1 ^ YMM2
VXORPS YMM0, YMM1, YMM2
; 按位与非:YMM0 = YMM1 & ~YMM2
VANDNPS YMM0, YMM1, YMM2

4. 比较运算

比较两个寄存器的数据,结果存储在目标寄存器中。

; 比较是否大于:YMM0 = (YMM1 > YMM2) ? 0xFFFFFFFF : 0x0
VCMPGTPS YMM0, YMM1, YMM2
; 比较是否小于:YMM0 = (YMM1 < YMM2) ? 0xFFFFFFFF : 0x0
VCMPLTPS YMM0, YMM1, YMM2
; 比较是否相等:YMM0 = (YMM1 == YMM2) ? 0xFFFFFFFF : 0x0
VCMPEQPS YMM0, YMM1, YMM2

5. 数据混合与重组

用于从多个寄存器中混合、选择或重新排列数据。

; 按掩码混合单精度浮点数:YMM0 = blend(YMM1, YMM2, mask)
VBLENDPS YMM0, YMM1, YMM2, 0b11001100

; 按模式混合单精度浮点数
VSHUFPS YMM0, YMM1, YMM2, 0b10110001
; 从两个寄存器中打包数据
VUNPCKLPS YMM0, YMM1, YMM2
VUNPCKHPS YMM0, YMM1, YMM2

6. 数据转换

将数据从一种类型转换为另一种类型。

; 整数转换为单精度浮点数
VCVTDQ2PS YMM0, YMM1
; 单精度浮点数转换为整数
VCVTPS2DQ YMM0, YMM1
; 单精度浮点数转双精度浮点数
VCVTPS2PD YMM0, XMM1
; 双精度浮点数转单精度浮点数
VCVTPD2PS YMM0, YMM1

7. 数据广播

广播内存中的单一值到整个寄存器。

; 单精度浮点数广播
VBROADCASTSS YMM0, [mem]
; 双精度浮点数广播
VBROADCASTSD YMM0, [mem]

8. 示例程序

将两个 8 元单精度浮点数组相加并存储结果:

section .data
    array1: dd 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0
    array2: dd 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0
    result: times 8 dd 0.0

section .text
global _start
_start:
    ; 加载数据到寄存器
    VMOVUPS YMM0, [array1]
    VMOVUPS YMM1, [array2]

    ; 执行逐元素相加
    VADDPS YMM0, YMM0, YMM1

    ; 存储结果到内存
    VMOVUPS [result], YMM0

    ; 结束
    ret

9. 小结

以上是 YMM 寄存器操作中最常见的指令,涵盖数据加载与存储、算术运算、逻辑运算、比较、混合、重组和数据类型转换等场景。通过这些指令,可以充分利用 AVX 指令集来优化 SIMD 运算。

请登录后发表评论