I was originally trying to generate the bytes for an immediate move into a 64 bit register.The specific operation I wanted was
mov rdi, 0x1337
Using https://www.felixcloutier.com/x86/mov, the only non-sign extended instructions I saw was
REX.W + B8+ rd io
This confused me so I created a small assembly program to see what the assembler would generate
global _start
section .text
_start:
mov rdi, 0x1337
syscall
mov rax, 60
xor rdi, rdi
syscall
I had to turn off optimizations so that there would be a move into a 64-bit register. So I compiled with nasm -felf64 -O0 main.asm && ld main.o
and generated a a.out
. I look at the objdump -M intel -d ./a.out
and this line
48 bf 37 13 00 00 00 movabs rdi,0x1337
That line looks nothing like
REX.W + B8+ rd io
to me? Additionally, after some research, I saw that the command is suppose to be 10 bytes. How do you get that from REX.W + B8+ rd io
?
B8+ rd
means the operand (a register) is encoded in the low 3 bits of the opcode, not in a ModR/M byte.From the Intel Software Developer's Manual,
It looks like Intel wanted to use
+ro
for 64-bit operands encoded in that way, but then didn't actually do that. Not just in themov
lemma, but anywhere, as far as I could find. For example 64-bitpush
andpop
could have had+ ro
, but they also have+ rd
. And "Indicated" is likely a typo, the rest of the text uses the present tense.The
(e/r)di
register is number 7, andB8 + 7 = BF
, explaining the opcode.io
stands for a qword immediate (o for octo, as in 8 bytes, perhaps?).The REX prefix (40 for the base prefix, +8 to set the W bit, optionally +1 to set the B bit to access R8..R15), the opcode, no ModR/M byte, and the 8-byte immediate, add up to 10 bytes.