0

When I write to a register, everything is fine,

movq  $0xffffffffffffffff, %rax

But I get Error: operand size mismatch when I write to a memory location,

movq  $0xffffffffffffffff, -8(%rbp)

Why is that? I see in compiled C code that in asm these numbers are split in two and two movl instructions show up.

Maybe you can tell me where the mowq and other instructions are documented.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
ericj
  • 2,138
  • 27
  • 44
  • 1
    @jww: You missed removing the "thanks" fluff along with other filler. If you're going to bother editing an old post at all, definitely remove that too (https://meta.stackoverflow.com/questions/288160/no-thanks-damn-it). – Peter Cordes Feb 15 '18 at 05:27
  • `0xffffffffffffffff` is representable as a sign-extended imm32 (`-1`). I think you made up this example without actually testing this specific constant, because gas version 2.29.1 assembles it just fine; `48 c7 45 f8 ff ff ff ff movq $0xffffffffffffffff,-0x8(%rbp)` (disassembly from objdump). **If the high 32 bits weren't all copies of bit 31, it wouldn't be encodeable with a memory destination, though.** – Peter Cordes Feb 15 '18 at 05:33
  • And BTW, the AT&T mnemonic for `mov r64, imm64` is `movabs`. Intel-syntax assemblers pick an encoding based on the constant when you use a 64-bit register destination. – Peter Cordes Feb 15 '18 at 05:35

1 Answers1

3

Why is that?

Because MOV r64, imm64 is a valid x86 instruction, but MOV r/m64, imm64 is not (there's no encoding for it).


I see in compiled C code that in asm these numbers are split in two and two movl instructions show up.

MOV r/m64, imm32 is a valid x86 instruction, which is why you see two of them being used to store a 64-bit immediate to memory.


Maybe you can tell me where the mowq and other instructions are documented

In Intel's Software Developer Manuals.

Community
  • 1
  • 1
Michael
  • 57,169
  • 9
  • 80
  • 125
  • Thanks, but what is the logic that this instruction isn't there? – ericj Oct 25 '13 at 15:01
  • Intel did not think that such an instruction would be very useful, so they chose not to waste a scarce instruction encoding on it. – markgz Oct 26 '13 at 00:26
  • 1
    @markgz: AMD designed the x86-64 ISA extensions, not Intel. But yes, they decided that most 64-bit instructions would still use 32-bit immediates (sign-extended), because large constants are rare (and 64-bit addresses are normally handled by RIP-relative LEA). But yes, the REX.W=1 version of the 5-byte `mov r32,imm32` special encoding (with the register number in the opcode byte) becomes `mov r64, imm64`, while REX.W=1 `mov r/m32, imm32` becomes `mov r/m64, sign_extended_imm32`. There were already two different opcodes that could move an immediate to a register, so AMD took advantage. – Peter Cordes Feb 15 '18 at 05:25
  • The question is claiming use of `movl`, 32-bit bit operand-size. Most compilers would use `mov r64, imm64` / `mov r/m64, r64`, but it's also possible to do 2x `mov r/m32, imm32`. But you wouldn't use 2x `mov r/m64, sign_extended_imm32` like your answer suggests to store a single 64-bit value; you'd have to partially overlap them and write 4 bytes above where you want. – Peter Cordes Apr 04 '22 at 07:03
  • The whole questions is semi-bogus anyway, `movq $0xffffffffffffffff, -8(%rbp)` is encodeable because `-1` fits in an imm32. – Peter Cordes Apr 04 '22 at 07:04