I understand in x86_64 assembly there is for example the (64 bit) rax register, but it can also be accessed as a 32 bit register, eax, 16 bit, ax, and 8 bit, al. In what situation would I not just use the full 64 bits, and why, what advantage would there be?
As an example, with this simple hello world program:
section .data
msg: db "Hello World!", 0x0a, 0x00
len: equ $-msg
section .text
global start
start:
mov rax, 0x2000004 ; System call write = 4
mov rdi, 1 ; Write to standard out = 1
mov rsi, msg ; The address of hello_world string
mov rdx, len ; The size to write
syscall ; Invoke the kernel
mov rax, 0x2000001 ; System call number for exit = 1
mov rdi, 0 ; Exit success = 0
syscall ; Invoke the kernel
rdi and rdx, at least, only need 8 bits and not 64, right? But if I change them to dil and dl, respectively (their lower 8-bit equivalents), the program assembles and links but doesn't output anything.
However, it still works if I use eax, edi and edx, so should I use those rather than the full 64-bits? Why or why not?
mov r64, sign-extended-imm32is 7 bytes, vs. 5 formov r32, imm32. In GAS, you can usemovabsto requestmov r64, imm64, but NASM/YASM only choose that encoding based on the size of the constant. (And in fact NASM optimizes small constants tomov r32, imm32when you write the destination asrdi. I'm not sure about symbol addresses; it might leave them asimm64in case you're not using the "small" code model and you have symbols with addresses about 32 bit. It won't optimizemov rdi,0toxor edi,edithough, because of the side-effect on flags.) - Peter Cordes