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

(学习笔记)3.11 浮点代码(3.11.1 浮点传送和转换操作)

文章目录

  • 线索栏
  • 笔记栏
  • 总结栏

线索栏

  1. x86-64浮点体系结构经历了哪几个关键发展阶段?当前的AVX2架构提供了哪些寄存器(YMM/XMM)?它们的位宽和用途是什么?(图1,2)
  2. 用于在内存和XMM寄存器之间、以及XMM寄存器之间传送标量浮点数据的核心指令有哪些?(vmovss, vmovsd,vmovaps, vmovapd)(图3)
  3. 使用哪些指令?执行何种舍入?(vcvttsd2si等,向零舍入/截断)(图4)
  4. 使用哪些指令?为何是三操作数格式?(vcvtsi2sd等)(图4)
  5. GCC将float转double、double转float时,生成了什么看似复杂的指令序列?其实际效果是什么?(vunpcklps+vcvtps2pd等)(图5)
  6. 浮点参数和返回值通过哪个寄存器传递?(%xmm0)(图5)
  7. 如何分析类似fcvt、fcvt2这样的混合类型转换函数的汇编代码?(图5, 6)
  8. 给定源类型(src_t)和目的类型(dest_t),如何选择正确的转换指令?(练习题3.51)(图6)

笔记栏

第一部分:体系结构概述与寄存器 (对应图1, 2)

历史演进:从MMX(64位) -> SSE(128位 XMM) -> AVX(256位 YMM)。当前叙述基于2013年Haswell处理器引入的AVX2。

AVX浮点寄存器:

16个YMM寄存器:%ymm0~ %ymm15,每个256位(32字节)。

XMM寄存器:每个YMM寄存器的低128位,名为%xmm0~%xmm15,用于标量浮点操作。

标量数据存储:float只使用XMM寄存器的低32位;double使用低64位。

寄存器用途约定 (图2):

%xmm0:第一个浮点参数/浮点返回值。

%xmm1~%xmm7:后续浮点参数。

部分为“调用者保存”,部分为“被调用者保存”。

第二部分:浮点传送指令 (对应图3)

指令与功能 (图3-46):

vmovss:在内存(M32)和XMM寄存器间传送单精度(float)标量值。

vmovsd:在内存(M64)和XMM寄存器间传送双精度(double)标量值。

vmovaps/ vmovapd:在两个XMM寄存器间传送对齐的单/双精度数(也可用于标量)。

代码示例 (float_mov函数):

floatfloat_mov(floatv1,float*src,float*dst){floatv2=*src;*dst=v1;returnv2;}
#v1in%xmm0,src in%rdi,dst in%rsifloat_mov:vmovaps%xmm0,%xmm1 # 复制 v1vmovss(%rdi),%xmm0 # 从 src 读取 v2 vmovss%xmm1,(%rsi)# 将 v1 写入 dst ret # 返回值 v2 在%xmm0

第三部分:浮点转换指令 (对应图4, 5)

浮点数 -> 整数 (双操作数,图3-47):

vcvttsd2siq:将双精度数(M64/X)转换为四字整数(R64),向零舍入。

类似指令处理float转int/long。

整数 -> 浮点数 (三操作数,图3-48):

vcvtsi2sdq:将四字整数(M64/R64)转换为双精度数,存入目的XMM寄存器。第二个源操作数(另一个XMM)的值不影响低位结果,通常与目的相同。

例:vcvtsi2sdq %rax, %xmm1, %xmm1

浮点精度转换 (GCC的特殊代码,图5):

float-> double:

vunpcklps%xmm0,%xmm0,%xmm0 # 将[x3,x2,x1,x0]变为[x1,x1,x0,x0]vcvtps2pd%xmm0,%xmm0 # 将两个低位单精度转双精度,得[dx0,dx0]

double-> float:

vmovddup%xmm0,%xmm0 # 将[x1,x0]变为[x0,x0]vcvtpd2ps%xmm0,%xmm0 # 将两个双精度转单精度,存入低64位,高位置零

注意:GCC生成此多指令序列而非单条vcvtss2sd/vcvtsd2ss的原因不明,但效果相同。

第四部分:综合示例与练习 (对应图5, 6)

函数 fcvt分析 (图5):

参数:整数和指针通过通用寄存器(%edi, %rsi等)传递。

操作:演示了加载、存储、整数与浮点、浮点精度间的多种转换。

返回值:double类型,通过 %xmm0返回。

练习题3.51 解答思路 (图6):
src_t

dest_t

指令

注释

long

double

vcvtsi2sdq %rdi, %xmm0, %xmm0

整数在%rdi,结果到%xmm0

double

int

vcvttsd2si %xmm0, %eax

浮点在%xmm0,结果到%eax

double

float

vcvtsd2ss %xmm0, %xmm0, %xmm0(或GCC的多指令序列)

结果在%xmm0的低32位

long

float

先用vcvtsi2sdq转double,再用vcvtsd2ss转float

需两步转换

float

long

vcvttss2siq %xmm0, %rax

浮点在%xmm0,结果到%rax


总结栏

本节系统阐述了x86-64架构上浮点运算的机器级表示,揭示了与整数体系既相似又不同的设计。

  1. 独立的寄存器文件:浮点操作使用专属的XMM/YMM寄存器组(16个),而非整数寄存器。这允许并行处理标量或向量数据,并定义了专门的调用约定(参数/返回值通过%xmm0等传递)。
  2. 指令集的分化:浮点指令通常以v前缀开头,并通过后缀(ss-单精度标量, sd-双精度标量, ps-打包单精度,pd-打包双精度)精确指明数据类型和操作模式。这与整数指令的b/w/l/q后缀体系类似但独立。
  3. 转换规则明确:
    (1)浮点转整数:有专用的vcvttsd2si等指令,且遵循C语言规范向零舍入。
    (2)整数/浮点互转:使用不同的指令集,整数到浮点为三操作数格式。
    (3)精度转换:虽然GCC有时生成复杂的指令序列,但其最终效果与单条转换指令等价,了解其模式有助于阅读编译器输出。
  4. 从高级到低级的映射:通过fcvt等示例,可以看到复杂的C语言类型转换被系统地分解为加载、转换、存储等原子机器指令。分析此类代码的关键是追踪每个数据的来源(寄存器/内存)、类型转换过程以及最终目的地。

核心启示:浮点代码的编译是类型系统到指令集的精确映射。理解浮点寄存器、指令后缀和转换规则,是分析科学计算、图形处理等涉及浮点运算程序性能与行为的必备技能。尽管GCC的某些代码生成策略(如精度转换)看似冗余,但了解其模式对调试和逆向工程至关重要。

http://www.jsqmd.com/news/599664/

相关文章:

  • 【开源项目】想搞个“预测万物”的数字沙盘?MiroFish 一篇部署教程搞定
  • 双向排序(参照acwing的yxc)
  • OpenClaw开源贡献:为Phi-3-mini-128k-instruct提交技能PR
  • ESP32驱动ST7796S LCD的PlatformIO标准组件
  • GeekDoc
  • OpenClaw+Qwen3-14b_int4_awq:自动化数据收集与分析方案
  • 关于一个二本计算机专业学生的未来愿景
  • 开源神器来袭!深度解析铭飞MCMS:从入门到实战的全场景Java开源CMS系统
  • CSS如何实现自定义复选框样式_利用CSS变量切换选中状态背景
  • PostgreSQL 选择数据库
  • 你真的理解AI么?不不不,你真的理解产业么?
  • 生成式推荐GR4AD
  • eBPF Skeleton:简化内核编程新利器,近红外相机在机器视觉检测中的应用。
  • golang如何实现工作流引擎_golang工作流引擎实现要点
  • ATtiny85轻量级图形库应用与优化
  • Linux系统管理员必备命令大全
  • 如何在多个异步请求中统一判断:任一成功则执行A,全部失败则执行B.txt
  • OpenClaw技能市场挖掘:千问3.5-9B增强插件TOP5
  • python ctypes
  • AI专家进阶:掌握核心指南模板,从零开始的C++学习生活 2:类和对象(上)。
  • OpenClaw环境迁移指南:将Phi-3-mini-128k-instruct配置复制到新电脑
  • 如何用 CustomEvent 构造函数创建携带自定义数据的事件
  • Eclipse 添加书签的详细指南
  • Pixie Chroma嵌入式RGB点阵驱动库技术解析
  • 医疗AI大模型入门基础教程(非常详细):OpenHospital开源全解析,看这篇就够了!
  • 嵌入式开发必备硬件知识解析与应用
  • 【MicroPython编程-ESP32篇:设备驱动】-TEA5767收音机模块驱动
  • 绝地求生自动压枪解决方案:告别后坐力困扰,提升射击精准度
  • C语言注释陷阱与跨平台文件操作Bug解析
  • 【数据结构】「树」专题:树、森林与二叉树遍历之间的关系+408真题