当我使用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}
。那么为什么v4_float[0] = 0x1
使用info registers
?
答案 0 :(得分:1)
有没有办法获得与打印相同的输出?否
但是我做了一些关于此的研究,所以想在这里发布以供将来参考。以下是有关命令“ 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确实将寄存器视为普通寄存器,因此以不同的格式显示它。因此,我们应该在调试会话中使用这两种类型的命令在不同情况下显示寄存器。