Gdb 无法设置寄存器x86-64中的最低字节?

Gdb 无法设置寄存器x86-64中的最低字节?,gdb,x86-64,cpu-registers,Gdb,X86 64,Cpu Registers,我正在x86-64中编写一个函数,将一个1字节的值转换为表示该字节ASCII码的十六进制字符串。在函数开始时,我尝试使用 movb %dil, %r11b 将1字节值存储在寄存器%r11的最低字节中。然而,当我在gdb中检查时,从来没有设置%r11b。相反,将设置%r11的较高字节。这是我在使用gdb时得到的结果: Breakpoint 1, 0x00000000004011f0 in byte_as_hex () (gdb) print /x $r11b $1 = 0x0 (gdb) pri

我正在x86-64中编写一个函数,将一个1字节的值转换为表示该字节ASCII码的十六进制字符串。在函数开始时,我尝试使用

movb %dil, %r11b
将1字节值存储在寄存器%r11的最低字节中。然而,当我在gdb中检查时,从来没有设置%r11b。相反,将设置%r11的较高字节。这是我在使用gdb时得到的结果:

Breakpoint 1, 0x00000000004011f0 in byte_as_hex ()
(gdb) print /x $r11b
$1 = 0x0
(gdb) print /x $r11
$2 = 0x246
(gdb) print /x $rdi
$3 = 0x48
(gdb) print /x $dil
$4 = 0x48
(gdb) stepi  /* subq $8, %rsp */
0x00000000004011f4 in byte_as_hex ()
(gdb) print /x $r11b
$5 = 0x0
(gdb) print /x $r11
$6 = 0x246
(gdb) print /x $rdi
$7 = 0x48
(gdb) print /x $dil
$8 = 0x48
(gdb) stepi /* movb %dil, %r11b */
0x00000000004011f7 in byte_as_hex ()
(gdb) print /x $r11b
$9 = 0x0
(gdb) print /x $r11
$10 = 0x248
(gdb) print /x $rdi
$11 = 0x48
(gdb) print /x $dil
$12 = 0x48
(gdb) print /x $r11d
$13 = 0x248
(gdb) print /x $r11w
$14 = 0x248
(gdb) print /x $r11b
$15 = 0x0

我非常困惑,因为我特别尝试将B从%dil移动到%r11b,但仍然无法设置字节。谁能向我解释一下为什么会这样?谢谢

这里有多个问题:

  • (报告为。)当使用显式格式说明符打印时,未定义的(以
    $
    开头的GDB局部变量)显示为0,而不是默认的
    void
    ,在未指定格式时显示:

  • 它们没有别名,例如
    r11b
    r11l
    ,因此必须使用正确的名称。

    您能否显示这些步骤的说明,以便更容易地了解应该发生的情况?这看起来像是坏的/有缺陷的GDB行为。我想知道GDB是否会与注册名不同,如
    %r11l
    ?字节寄存器名有两种不同的约定:
    r11b
    r11l
    。我忘了是谁发明的。GDB似乎正在将
    r11b
    识别为寄存器名,所以不应该是这样,但您永远不会知道可能存在的错误。我的函数的开始行是
    byte\u as\u hex:subq$8,%rsp movb%dil,%r11b shr$4,%r11b
    我在尝试movb之前做的唯一一件事就是调整堆栈指针,因此,我不确定会出什么问题。当然,这很好,但您的问题是,对于每个
    stepi
    ,您需要输入刚刚执行的指令,例如作为“注释”或GDB输出中的额外行。几乎可以肯定,您的指令执行得很好,而GDB不能正常工作。(这不是GDB第一次出现bug。你有什么版本的GDB?)我只是检查了
    r11l
    ,而不是
    r11b
    ,结果发现存储值的地方就是这里。我仍然不太确定发生了什么,但至少我知道这个值存储在某个地方。我的gdb版本是Fedora 8.3.50.20190824-30.fc31。我现在就编辑我的问题-这是我的第一个问题,所以我还在学习如何回答。谢谢你的帮助这些名字不是GDB独有的;我认为它们起源于AMD64中的AMD,它早于英特尔IA-32e。但是,是的,英特尔的手册只提到了r8..r15的
    r11b
    名称。另见@PeterCordes哦,这现在有道理了。我“幸运地”选择了
    RSP
    而不是
    R8
    -
    R15
    来测试:)上的低字节命名(注意,情况正好相反:根据您的第一个链接,是AMD使用了
    *B
    作为编号寄存器)哦,谢谢,是的,我自己总是使用
    r8b
    样式,忘记了哪个供应商在手册中使用了哪个。是针对第1点中GDB bug的规范问答。显然,未来的GDB版本应该打印void,而不是0,即使格式为。我认为这个问答实际上是重复的,尽管你的答案有一些更多的信息,如大写字母和其他注册名称,如
    ftag
    $ gdb /bin/true
    Reading symbols from /bin/true...
    (gdb) p $asdf
    $1 = void          <------ undefined, OK
    (gdb) p/x $asdf
    $2 = 0x0           <------ the problem
    (gdb) set $asdf=4345
    (gdb) p $asdf
    $3 = 4345
    (gdb) p/x $asdf
    $4 = 0x10f9
    (gdb) 
    
    al
    cl
    dl
    bl
    spl
    bpl
    sil
    dil
    r8l
    ...
    r15l