【问题标题】:gdb: SSE register output formatgdb:SSE 寄存器输出格式
【发布时间】:2014-04-02 22:51:14
【问题描述】:

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

(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
}

但是,如果我使用 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
}

有什么方法可以得到与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
}

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

【问题讨论】:

  • 尝试将/d 附加为小数
  • @FredrikPihl 我在使用info registers 时似乎无法指定格式,还是我遗漏了什么?
  • 好的,我刚刚发现gdb将浮点值转换为整数,然后以十六进制显示v4_float

标签: debugging assembly gdb sse cpu-registers


【解决方案1】:

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

但是我对此进行了一些研究,因此想将其发布在此处以供将来参考。以下是有关命令“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

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

设置输出基数基数

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

这可用于更改 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
}

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

【讨论】:

  • 然后我必须单独打印每个寄存器。感谢您的研究!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
相关资源
最近更新 更多