16-bit address-size is not usable in 64-bit code. Pointers are 64-bit. You could have tried assembling movw %ax, (%bx)
, although the resulting error message, foo.s:1: Error: `(%bx)' is not a valid base/index expression
is not super-helpful. (I used gcc -c foo.s
to run GAS on it, on my x86-64 Linux desktop.)
Address-size and operand-size are separate things.
mov %ax, (%rbx)
is a 16-bit store to the memory pointed-to by RBX. %ax
is a 16-bit register so it implies 16-bit operand size. (And yes, movw
with the operand-size override suffix on the mnemonic is also a valid way of writing it.)
Fun fact:
mov %ax, (%ebx)
is encodable in 64-bit mode, but it will only use the low 32 bits of RBX as the address for the memory operand. You basically never want to use 32-bit address-size in 64-bit mode, not even in an LEA instruction.
Your lab partner is correct, it's exactly analogous to C:
uint16_t *p;
sizeof(p) == 8 // With a normal x86-64 C compiler
sizeof(*p) == 2
You always have to use the full size of the register in addressing modes. Using the low 16 bits of a pointer as the addressing mode wouldn't be useful.
there's not a ton of explicit information on this!
Intel's manuals are very explicit, but also quite long. https://software.intel.com/en-us/articles/intel-sdm#three-volume
HTML extract of the main part of the vol.2 manual (without the how-to-read-it part): https://www.felixcloutier.com/x86/index.html, with the entry for mov
being https://www.felixcloutier.com/x86/mov
See also other links at https://stackoverflow.com/tags/x86/info.
Related: