You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Intel XMM寄存器加载与乘法操作异常问题求助

问题:XMM寄存器浮点乘法测试异常分析

我编写了以下汇编程序测试XMM寄存器的数据乘法功能:

# file: xmm.a
.global _start:
_start:
movsd (%rip), %xmm4
movsd -8(%rip), %xmm7
mulsd %xmm4, %xmm7
jmp _start

使用as xmm.a -o xmm.o汇编、ld xmm.o -o xmm链接后,通过gdb --args ./xmm调试_start函数,得到如下输出:
该程序应直接将16字节代码数据加载至xmm4和xmm7寄存器并执行乘法,但实际未按预期工作。
我的系统是基于Intel i7处理器的Windows Subsystem for Linux(Ubuntu 20.04.6 LTS)。

(gdb) disassemble /r  _start

  Dump of assembler code for function _start:

       0x00401000 <+0>:     f2 0f 10 25 00 00 00 00 movsd  0x0(%rip),%xmm4
       0x00401008 <+8>:     f2 0f 10 3d f8 ff ff ff movsd  -0x8(%rip),%xmm7   <_start+8>

       0x00401010 <+16>:    f2 0f 59 fc     mulsd  %xmm4,%xmm7

    => 0x401014 <+20>:    eb ea   jmp    0x401000 <_start>

    End of assembler dump.

(gdb) x/8i _start-8

      0x400ff8:    add      %al,(%rax)
      0x400ffa:    add      %al,(%rax)
      0x400ffc:    add      %al,(%rax)
      0x400ffe:    add      %al,(%rax)
      0x401000 <_start>:    movsd  0x0(%rip),%xmm4
      0x401008 <_start+8>:  movsd  -0x8(%rip),%xmm7
      0x401010 <_start+16>: mulsd  %xmm4,%xmm7
   => 0x401014 <_start+20>: jmp    0x401000 <_start>

(gdb) print $xmm4

    $3 = {v4_float = {2.38630424e-29, -nan(0x783d10), 0, 0}, v2_double = {-nan(0x83d100ff20000), 0}, v16_int8 = {
    0, 0, -14, 15, 16, 61, -8, -1, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {0, 4082, 15632, -8, 0, 0, 0, 0},
      v4_int32 = {267517952, -508656, 0, 0}, v2_int64 = {-2184660617396224, 0}, uint128 = 18444559413092155392}

(gdb) print $xmm7

    $4 = {v4_float = {0.0351714566, -nan(0x7ffff8), 0, 0}, v2_double = {-nan(0xffff83d100ff2), 0}, v16_int8 = {
    -14, 15, 16, 61, -8, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {4082, 15632, -8, -1, 0, 0, 0, 0},
      v4_int32 = {1024462834, -8, 0, 0}, v2_int64 = {-33335275534, 0}, uint128 = 18446744040374276082}

(gdb)

按照IEEE754浮点标准,加载的数据和乘法结果均不符合规范,我不清楚问题出在哪里。


问题原因与解决方案

核心问题

你的代码没有在指令后定义要加载的浮点常量。movsd (%rip), %xmm4 使用RIP相对寻址,会读取当前指令结束后内存地址的8字节数据,但你的_start函数结束后没有放置任何合法的IEEE754双精度浮点数,导致实际加载的是后续的机器码(比如jmp指令的eb ea等字节),这些字节组合成的数值不是合法的双精度浮点数,因此寄存器中出现NaN。

修正后的代码

# file: xmm.a
.global _start
_start:
movsd (%rip), %xmm4        # 加载后续第一个双精度常量
movsd -16(%rip), %xmm7     # 加载后续第二个双精度常量(偏移量需根据指令长度计算)
mulsd %xmm4, %xmm7
jmp _start

# 定义测试用的双精度浮点数据,放在代码段之后
.double 2.5, 4.0           # 两个8字节的双精度数,对应2.5和4.0,乘积应为10.0

关键修正点

  1. 移除.global _start后的冒号,符合GAS汇编语法规范;
  2. 在代码末尾添加.double伪指令,定义合法的IEEE754双精度浮点常量,让RIP相对寻址能读取到正确数据;
  3. 调整movsd的RIP偏移量:执行movsd -16(%rip), %xmm7时,RIP指向这条指令的下一条指令(mulsd的地址),-16字节刚好指向第一个.double数据,(%rip)则指向第二个.double数据。

验证方法

重新编译链接后用GDB调试,查看寄存器值:

(gdb) print $xmm4.v2_double[0]
$1 = 2.5
(gdb) print $xmm7.v2_double[0]
$2 = 4.0
# 执行一次乘法后
(gdb) stepi
(gdb) print $xmm7.v2_double[0]
$3 = 10.0

内容的提问来源于stack exchange,提问作者dash-

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 23:23:16