2

I am in a Machine Architecture class in college right now and we are starting to learn assembly. We have a question that says:

The following x86-64 assembly instruction will copy 16 bits from the A register to the main memory location pointed to by the B register.

My lab partner thinks the answer is movw %ax, (%rbx).
Because the place we are copying it to is a pointer.

I think it is: movw %ax, (%bx).
Because that signifies that it's 16 bits.

Any explanation will help because we are lost and there's not a ton of explicit information on this!

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • 1
    Note that you could have just looked at C compiler output for `void foo(short *p) { *p = 1; }` to find out what a store to a 16-bit memory location looks like. – Peter Cordes Oct 15 '19 at 03:51
  • Related: [Moving two bytes into the lowest portion of a register](//stackoverflow.com/q/58382772) appears to be about a different part of the same lab. So does [What does this x86-64 assembly code mean/do?](//stackoverflow.com/q/58386753) – Peter Cordes Oct 15 '19 at 05:45

1 Answers1

2

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:

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847