为什么 GDB 不是制表符完整的 mmx 寄存器名称(mm0-mm7)

why does GDB not tab-complete mmx register name(mm0-mm7)

我使用 gdb info registers <tab> 查看所有寄存器,但我没有看到 MMX 寄存器。

我的 CPU 是 Xeon Platinum 8163,一款支持 SSE 和 MMX 的现代 Xeon cpu。所以我认为这是一个 gdb 问题(如果我是对的)。

为什么 gdb 不支持显示 mmx 寄存器,而 mmx 寄存器与基本寄存器和 sse 寄存器相比应该具有相同的重要性。

MMX 寄存器没有自己独立的体系结构状态;它们为 x87 寄存器 st0..st7 起别名。 (英特尔这样做是为了让操作系统不会通过 FXSAVE/FXRSTOR 在上下文切换时特别支持 save/restore MMX 状态)。这与所有其他寄存器不同。

但我认为这是一个 GDB 错误,而不是有意决定不通过 x87 状态公开 MMX 状态。 info reg mmx 制表完成但不打印任何内容。 (x86-64 Arch 上的 GDB 10.1 GNU/Linux)

即使运行在MMX 状态下使用FPU 运行程序(例如在执行movd mm0, eax 之后),它仍然不会完成tab。事实上,甚至 p $mm0 也只是打印 void(因为 GDB 变量名称未被识别为绑定到 MMX 寄存器)。


可以通过i r float

查看MMX状态

例如在 mov eax, 231 / movd mm0, eax

之后
 starti
 stepi
 si

(gdb) p $mm0
 = void
(gdb) i r mm0
Invalid register `mm0'
(gdb) i r mmx
(gdb) i r float
st0            <invalid float value> (raw 0xffff00000000000000e7)
st1            0                   (raw 0x00000000000000000000)
...

又一步之后,pshufw mm1, mm0, 0

(gdb) si
0x000000000040100c in ?? ()
(gdb) i r float
st0            <invalid float value> (raw 0xffff00000000000000e7)
st1            <invalid float value> (raw 0xffff00e700e700e700e7)
st2            0                   (raw 0x00000000000000000000)

因此如果忽略80位扩展精度位模式的高16位,则可以将64位尾数部分视为MMX寄存器值。

我认为这已经很长时间没有解决了,因为 SSE2 使 MMX 大部分 过时,提供了更宽的寄存器并且不需要缓慢的 emms 之前离开 MMX 状态潜在的 x87 FPU 指令,如 fld。 (在像 Skylake 这样的现代 CPU 上,MMX 指令没有移动消除,并且一些 运行 在比它们的 SSE2 等价物更少的执行端口上,比如 paddd

当然,一些现有的代码,特别是 x264 和 FFmpeg 的 h.264 软件解码器,仍然使用手写的 MMX asm 而不是 XMM 寄存器的低 qword。这有时是有利的,例如允许 punpcklbw mm0, [rdi].

顺便说一句,我单步执行的测试程序是从这个 NASM 源代码组装+链接到一个静态可执行文件中的:

mov    eax, 231         ; __NR_exit_group = 0xe7
movd   mm0, eax
pshufw mm1, mm0, 0      ; broadcast the low word
emms
nop

syscall