如何在x87与SSE寄存器间直接传输数据?附加载异常排查
x87 FPU与SSE寄存器直接数据传输及相关问题解决
一、跳过内存中转的寄存器直接传输方法
要在x87 FPU寄存器(如st(0))和SSE寄存器(如xmm1)之间直接传输双精度浮点数,无需借助临时内存变量,直接使用以下指令即可:
- x87 → SSE:用
fstpd %xmm1,这条指令会把st(0)中的双精度值直接写入xmm1寄存器的低64位,完成从x87到SSE的直接传输。 - SSE → x87:若需要反向传输,使用
ldsd %xmm1, %st(0),将xmm1低64位的双精度值加载到st(0)中。
结合你的三角函数计算场景,修改后可直接把fsin的结果从st(0)写入xmm1,省去临时内存中转步骤。
二、解决fld加载失败和fsin结果异常的问题
问题根源
- val的定义错误:GAS汇编里,
.double后面必须写浮点格式的数值(比如90.0),如果只写90,汇编器会把它当作整数处理,转成双精度后的值并非预期的90.0,导致fld加载到st(0)的是错误值(甚至是0)。 - fsin的弧度制要求:x87的
fsin指令计算的是弧度值的正弦,不是角度值。90度对应的弧度是π/2(约1.5708),直接传入90(弧度)的话,结果并不是1。
修正后的完整代码
.section .data outfloatfmt: .asciz "%lf\n" val: .double 1.5707963267948966 # π/2的近似值,对应90度 sinres: .double 0 .section .text .extern printf .global main main: pushq %rbp movq %rsp, %rbp fld val(%rip) # 加载正确的弧度值到st(0) fsin # 计算正弦,结果存在st(0) fstpd %xmm1 # 直接把st(0)的值写入xmm1,跳过内存中转 movsd %xmm1, sinres(%rip) # 将xmm1的值存入目标内存 # 打印结果 movsd sinres(%rip), %xmm0 leaq outfloatfmt(%rip), %rdi movq $1, %rax callq printf movq %rbp, %rsp popq %rbp ret
内容的提问来源于stack exchange,提问作者TheSinisterStone
相关产品推荐
相关产品推荐

