assembly - Sign or Zero Extension of address in 64bit mode for MOV moffs32? -


let's have instruction mov eax,[0xffffffff] encoded in 64bit mode 67a1ffffffff (effective address-size toggled 67 prefix default 64 32 bits).

intel's instruction reference manual (doc order number: 325383-057us december 2015) on page vol. 2a 2-11 says:

2.2.1.3 displacement
addressing in 64-bit mode uses existing 32-bit modr/m , sib encodings. modr/m , sib sizes not change. remain 8 bits or 32 bits , sign-extended 64 bits.

this suggests 32bit displacement should sign-extended not sure if concerns special moffs addressing mode well. on next page intel says:

2.2.1.6 rip-relative addressing

rip-relative addressing enabled 64-bit mode, not 64-bit address-size. use of address-size prefix not disable rip-relative addressing. effect of address-size prefix truncate , zero-extend computed effective address 32 bits.

this suggests in relative addressing mode disp32 sign-extended 64 bit, added rip , truncated , zero-extended. hovever not sure if same rule applies absolute addressing mode, case of mov moffs operations.

what address eax loaded from, a) ffffffffffffffff or b) 00000000ffffffff ?

67 a1 ffffffff isn't using disp32, mod/rm section of documentation doesn't apply. moffs32 own thing. (thanks @jester clarifying it's 0 extended.)

i didn't go digging in docs clarification on moffs32 in 64bit mode. however, it's normal zero-extension when use address-size prefix (like mov eax, [esp] instead of mov eax, [rsp]).


anyway, means disassembling mov eax, [0xffffffff] wrong (at least in nasm syntax), because assembles instruction different.

the correct nasm syntax assemble machine code is

mov eax, [a32 0xffffffff]

yasm doesn't support a32 keyword address-size overrides, nasm does.


gnu as provides way express (without using .byte): addr32 mov 0xffffffff,%eax

movl    0x7fffffff, %eax  # 8b mod/rm disp32 movl    0xffffffff, %eax  # a1 moffs64: movabs, no rex, because address can't encoded in disp32  movabs  0x7fffff, %eax    #     a1 moffs64: movabs, no rex or address-size prefix movabs  0xffffffff, %rax  # rex a1 moffs64 movabs  0xffff, %ax       #  66 a1 moffs64: operand-size prefix  .byte 0x67, 0xa1, 0xff, 0xff, 0xff, 0xff  # disassembles  addr32 mov 0xffffffff,%eax                                           # , syntax works assembler input: addr32 mov 0xffffffff,%eax    # 67 a1 ff ff ff ff:  moffs32 

as mentioned earlier, a32 keyword works nasm, not yasm, , assemble 67 a1 moffs32. same syntax different register assemble mov disp32 , address-size prefix. (e.g. mov ecx, [a32 0x7fffff] assembles 67 8b 0c 25 ff ff 7f 00 addr32 mov 0x7fffff,%ecx)

you can write mov eax, [qword 0xffff...] moffs64 encoding, there's no way require moffs32 encoding. (i.e. in way refuse assemble if used different register.)

agner fog's objconv disassembler gets wrong (disassembling machine code produced gnu as block above). objconv appears assume sign-extension. (it puts machine code in comments prefixes: opcode, operands)

; note: absolute memory address without relocation     mov     eax, dword [abs qword 7fffffh]          ; 0033 _ a1, 00000000007fffff  ... ; note: absolute memory address without relocation     mov     eax, dword [0ffffffffffffffffh]         ; 0056 _ 67: a1, ffffffff 

ndisasm -b64 disassembles incorrectly, code doesn't work same way:

00000073  a1ffff7f00000000  mov eax,[qword 0x7fffff]          -00 ... 00000090  67a1ffffffff      mov eax,[0xffffffff] 

i have expected disassembly mov eax, [qword 0xffffffff], if it's not going use a32 keyword. assemble moffs64 references same address original, longer. overlooked when adding amd64 support ndisasm, existed before amd64.