0

x86 assembly program. I write 0xffffffffffffffff into the RSI register then I use MOV to load a constant (6). When I use ESI as the target, the higher bits become zeros, but not if I use SI or SIL as the target.

mov   rdi, format ; "0x%016lx\n"
mov   rsi, 0xffffffffffffffff
mov   esi, 6
call  _printf ; => 0x0000000000000006

… but …

mov   rdi, format
mov   rsi, 0xffffffffffffffff
mov   si, 6
call  _printf ; => 0xffffffffffff0006

… and …

mov   rdi, format
mov   rsi, 0xffffffffffffffff
mov   sil, 6
call  _printf ; => 0xffffffffffffff06
  • Why this difference?
  • Is this always true or only under some conditions?
  • Where is this documented?

I already checked the section about the MOV instruction (Vol 1, 7.3.1.1) in the Intel® 64 and IA-32 Architectures Software Developer’s Manual, and I didn't find the information there. I also checked the section in Volume 2A 4.2 (M-Z) about the MOV instruction, but I find it a little difficult to understand.

mistercake
  • 692
  • 5
  • 14
  • 1
    32 bit operations zero the top bits, yes. 16 or 8 bit don't. It's not about the `mov`. – Jester Oct 07 '19 at 18:28
  • 2
    The documentation of this is quite hidden in the _Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 1: Basic Architecture_, chapter _3.4.1.1 General-Purpose Registers in 64-Bit Mode_: "32-bit operands generate a 32-bit result, zero-extended to a 64-bit result in the destination general-purpose register." – Jester Oct 07 '19 at 18:34
  • The close-as-duplicate box didn't even need me to type anything, the target duplicate was already the 2nd hit just based on your question title. – Peter Cordes Oct 07 '19 at 19:00
  • 1
    Yes, this is *always* true. Writing a 32-bit register *always* zero-extends, writing narrower regs never does. – Peter Cordes Oct 07 '19 at 19:03

0 Answers0