为什么在GDB中将eax设置为1后,rax是0xffffffff00000001而不是0x0000000000000001?

问题描述 投票:0回答:1

我正在 x86-64 系统上使用 GDB 调试 GAS 汇编程序。当我将rax寄存器设置为-1然后将eax设置为1时,rax的值变为0xffffffff00000001,但我期望它是0x0000000000000001,因为我认为设置eax会清除rax的高32位(基于我的内容)已阅读有关 x86-64 如何处理 eax 的信息)。

这就是我所做的:

(gdb) set $rax=-1
(gdb) info register rax
rax            0xffffffffffffffff  -1
(gdb) set $eax=1
(gdb) info register rax
rax            0xffffffff00000001  -4294967295        #  (???)
debugging assembly gdb x86-64 cpu-registers
1个回答
0
投票

GDB 通过更改内存中的字节来更改寄存器(例如,在 Linux 上通过

struct pt_regs
系统调用在目标进程的
ptrace
中)。不是通过在目标进程的上下文中在 CPU 上运行类似
mov eax, ...
的指令。

如果我没有看到你的实验,我可能会猜测

set $eax=1
可能会零扩展到完整的 RAX 以匹配 asm 语义,但在考虑之后,它似乎很合理,它没有。 这简化了 GDB 的内部结构,不必以与 32 位部分寄存器不同的方式处理 8 位和 16 位部分寄存器,只需修改为所有 4 个宽度实际指定的操作数的宽度即可。

如果您想设置完整的寄存器,通过命名它仍然很容易做到(

$rax
)。 要截断和零扩展任意表达式,我想
set $rax=(uint32_t)(a*b + c | d)
或其他。

对于 128 位

$xmm0
,保留
$ymm0 / $zmm0
的高位不修改会匹配旧版 SSE 语义,而不是 VEX/EVEX 语义。 因此,即使模拟写入寄存器的 asm 指令,您也可能想要它,并且如果零扩展是唯一的选择,则很难实现。

© www.soinside.com 2019 - 2024. All rights reserved.