1

In gdb, I can't seem to access any of the pseudo-registers: r8b, r9b, r10b, r11b, r12b, r13b, r14b, nor r15b (however, r15d and r15w seem to work, and same for sil).

See an example:

section .text
global main

main:
  xor esi, esi
  mov sil, 0x1f
  xor r13d, r13d
  mov r13b, sil
  ret

Running with gdb:

(gdb) p $sil
$1 = -15
(gdb) p $r13 
$2 = 241
(gdb) p $r13b
$3 = void
(gdb) p /x $r13b
$4 = 0x0

I couldn't find anything in the gdb manual, and they aren't printed with the info all-registers command. I'm using GDB 10.

Marco
  • 2,796
  • 19
  • 24
  • 1
    This has come up on SO a couple times before, as [Unable to set the lowest byte in a register x86-64?](https://stackoverflow.com/q/64115162) (Ruslan's answer links the same GDB bug you did) and [Moving indirect-addressed value into AL works, but moving it into an 8-bit rXb register doesn't in yasm](https://stackoverflow.com/q/10379428). This one has a better title, so I closed the others as duplicates of this good canonical Q&A. – Peter Cordes Apr 10 '21 at 01:21
  • 1
    Wait a minute, in your NASM source I think you mean `mov r13b, sil`, because `mov r13, sil` is an operand-size mismatch. (Also, normally you'd do `movzx r13d, sil` instead of xor-zero and a byte mov, but the point of the example is to show that NASM understands a register name that GDB doesn't.) – Peter Cordes Apr 10 '21 at 01:22
  • @PeterCordes, thanks for fixing the code! Yeah, I was writing the code after the fact and might have got an instruction wrong :P. Thanks for the pointers, I missed the other stackoverflow question... I searched for this but couldn't find much information, so ended up looking at the gdb code. – Marco Apr 10 '21 at 01:49

1 Answers1

2

You can reference to the low byte of those registers using the l suffix:

r8l, r9l, r10l, r11l, r12l, r13l, r14l, r15l.

(gdb) p $r13l
$1 = -15
(gdb) p /x $r13l
$2 = 0xf1

I couldn't find these aliases documented anywhere, except in their definition in the gdb codebase:

/* Register names for byte pseudo-registers.  */

static const char * const amd64_byte_names[] =
{
  "al", "bl", "cl", "dl", "sil", "dil", "bpl", "spl",
  "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l",
  "ah", "bh", "ch", "dh"
};

Furthermore, there was a bug in the gdb codebase that would print 0 instead of void if a format is specified to the print command, as it happens in the last example. Future versions of gdb should display void if the value that you are printing is not defined.

Marco
  • 2,796
  • 19
  • 24
  • 1
    The `l`-suffix names are actually not unique to GDB: Intel's manuals use `r8l` for the low byte of `r8`, unlike AMD's choice of `r8b`: [Why does Apple use R8l for the byte registers instead of R8b?](https://stackoverflow.com/q/43991779) and [What are the names of the new X86\_64 processors registers?](https://stackoverflow.com/q/1753602). AMD were the original architects of AMD64, and their names are more widespread in most uses. (But I wouldn't be surprised if there isn't any GDB documentation other than this about only allowing those versions of the names.) – Peter Cordes Apr 10 '21 at 01:17
  • I read that what's how they are called by Intel, but in Intel SDM volume 1, they are referred as `r8b-r15b`, so I don't know where the `l`-suffix comes from. – Marco Apr 10 '21 at 01:42
  • 1
    Oh, I haven't checked recently; maybe Intel changed their manuals to follow the more widely-used conventions, or maybe a different part of Intel's manuals use r8l-r15l. The current vol.2 manual (April 2021) with instruction-encoding details also only uses r8b-r15b. – Peter Cordes Apr 10 '21 at 03:37
  • To put the mayhem to an end I chose to accept both variants `R8L` and `R8B` in my assembler :-) – vitsoft Apr 10 '21 at 06:59