gdb:SSE 寄存器输出格式

Dav*_*iD. 5 debugging assembly gdb sse cpu-registers

当我使用输出 SSE 寄存器时,print我得到了预期的结果:

(gdb) p $xmm0
$1 = {
    v4_float = {0, 0, 0, 0}, 
    v2_double = {0, 0}, 
    v16_int8 = {0 <repeats 16 times>}, 
    v8_int16 = {0, 0, 0, 0, 0, 0, 0, 0}, 
    v4_int32 = {0, 0, 0, 0}, 
    v2_int64 = {0, 0}, 
    uint128 = 0
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用info registers $xmm0所有内容都是十六进制的:

(gdb) i r $xmm0
xmm0           {
    v4_float = {0x0, 0x0, 0x0, 0x0}, 
    v2_double = {0x0, 0x0}, 
    v16_int8 = {0x0 <repeats 16 times>}, 
    v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 
    v4_int32 = {0x0, 0x0, 0x0, 0x0}, 
    v2_int64 = {0x0, 0x0}, 
    uint128 = 0x00000000000000000000000000000000
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以获得与我相同的输出print吗?

编辑: 也许是一个不相关的问题,但我如何解释 的值v4_float?一个例子:

(gdb) i r $xmm0
xmm0           {
    v4_float = {0x1, 0x0, 0x0, 0x0}, 
    v2_double = {0x0, 0x0}, 
    v16_int8 = {0x0, 0x0, 0xa0, 0x3f, 0x0 <repeats 12 times>}, 
    v8_int16 = {0x0, 0x3fa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 
    v4_int32 = {0x3fa00000, 0x0, 0x0, 0x0}, 
    v2_int64 = {0x3fa00000, 0x0}, 
    uint128 = 0x0000000000000000000000003fa00000
}
Run Code Online (Sandbox Code Playgroud)

不应该v4_float[0]v4_int32[0]两者都是0x3fa00000( 1.25f) 吗?如果我使用print我正确地得到v4_float = {1.25, 0, 0, 0}. 那么为什么v4_float[0] = 0x1在使用时info registers呢?

Man*_*mar 2

有没有办法获得与打印相同的输出?,没有

不过我对此做了一些研究,所以想将其发布在这里以供将来参考。以下是有关命令“ info all-registers”和有关特殊寄存器的信息。

有些机器有特殊的寄存器,其内容可以用几种不同的方式解释。例如,现代基于 x86 的机器具有 SSE 和 MMX 寄存器,它们可以保存以多种不同格式打包在一起的多个值。

info registers 命令显示规范名称。例如,在 SPARC 上,info 寄存器将处理器状态寄存器显示为 $psr,但您也可以将其称为 $ps;在基于 x86 的机器上 $ps 是 eflags 寄存器的别名。当以这种方式检查寄存器时,gdb 总是将普通寄存器 的内容视为整数。

看来 gdb 在显示寄存器时存在限制(由于各种原因,如不同类型的机器和其他原因)。我们还应该记住,寄存器不是程序的简单变量,而是对于一个程序来说是特殊且唯一的。程序,看起来十六进制是显示这些寄存器的自然格式。然而,只要有可能,gdb 就会以两种格式显示通用寄存器值的内容。为了说明这一点,请考虑以下输出:

//We can see that gdb is displaying the registers in both format(hex and decimal)
//and in some cases hex and hex format.
(gdb) info r
rax            0x7ffff7dd6568   140737351869800
rbx            0x0  0
rcx            0x400620 4195872
rdx            0x7fffffffe218   140737488347672
rsi            0x7fffffffe208   140737488347656
rdi            0x1  1
rbp            0x7fffffffe120   0x7fffffffe120
rsp            0x7fffffffe070   0x7fffffffe070
r8             0x4006b0 4196016
.............................
ds             0x0  0
es             0x0  0
fs             0x0  0
gs             0x0  0
//gdb would interpret the registers in the normal variable types. However if 
// we want to display it in decimal rather in hex format. 
(gdb) p $rsp
$24 = (void *) 0x7fffffffe070
(gdb) p/d $rsp
$25 = 140737488347248
Run Code Online (Sandbox Code Playgroud)

还有另一个重要的设置可以更改数字显示的默认基数。

设置输出基数

设置数字显示的默认基数。支持的基数选择为十进制 8、10 或 16。基数本身必须明确指定或使用当前输入基数。

这可用于更改 GDB 内普通变量/数字的默认显示。然而这些设置也不会改变寄存器的默认视图(当使用信息寄存器时)。然而,当我们使用 print 命令显示它时,它会将普通变量和寄存器的默认值从十进制更改为十六进制。为了说明这一点,请考虑我们有一个局部变量(结果)。

(gdb) show output-radix 10
Default output radix for printing of values is 10.
(gdb) p ii
$26 = (int *) 0x400369
(gdb) p result
$27 = 0
(gdb) info r $xmm0
xmm0           {
  v4_float = {0x0, 0x0, 0x0, 0x0}, 
  v2_double = {0x0, 0x0}, 
  v16_int8 = {0xff, 0x0 <repeats 15 times>}, 
  v8_int16 = {0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 
  v4_int32 = {0xff, 0x0, 0x0, 0x0}, 
  v2_int64 = {0xff, 0x0}, 
  uint128 = 0x000000000000000000000000000000ff
}
(gdb) p $xmm0
$28 = {
  v4_float = {3.57331108e-43, 0, 0, 0}, 
  v2_double = {1.2598673968951787e-321, 0}, 
  v16_int8 = {-1, 0 <repeats 15 times>}, 
  v8_int16 = {255, 0, 0, 0, 0, 0, 0, 0}, 
  v4_int32 = {255, 0, 0, 0}, 
  v2_int64 = {255, 0}, 
  uint128 = 255
}
(gdb) set output-radix 16
Output radix now set to decimal 16, hex 10, octal 20.
(gdb) p result
$29 = 0x0
(gdb) info r $xmm0
xmm0           {
  v4_float = {0x0, 0x0, 0x0, 0x0}, 
  v2_double = {0x0, 0x0}, 
  v16_int8 = {0xff, 0x0 <repeats 15 times>}, 
  v8_int16 = {0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 
  v4_int32 = {0xff, 0x0, 0x0, 0x0}, 
  v2_int64 = {0xff, 0x0}, 
  uint128 = 0x000000000000000000000000000000ff
}
(gdb) p $xmm0
$30 = {
  v4_float = {3.57331108e-43, 0, 0, 0}, 
  v2_double = {1.2598673968951787e-321, 0}, 
  v16_int8 = {0xff, 0x0 <repeats 15 times>}, 
  v8_int16 = {0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 
  v4_int32 = {0xff, 0x0, 0x0, 0x0}, 
  v2_int64 = {0xff, 0x0}, 
  uint128 = 0x000000000000000000000000000000ff
}
Run Code Online (Sandbox Code Playgroud)

所以看起来,使用 info register 命令时无法更改格式。但是,如果我们想使用 print 命令显示寄存器,则可以更改其默认格式,因为 GDB 确实将寄存器视为普通寄存器,因此以不同的格式显示它。因此,我们应该在调试会话中使用这两种类型的命令来显示不同情况下的寄存器。