4

I'm trying to compile the following assembly...

movq $0x3534373536383235, 0x000000000055638f8
movq $0x55638f8, %rdi
retq

The first line throws the error Error: operand size mismatch for 'movq'

Which doesn't make sense to me, because they are both 8 byte numbers.

I did a little research and movabsq was recommended, like so...

movabsq $0x3534373536383235, 0x000000000055638f8
movq $0x55638f8, %rdi
retq

But this throws the error: Error: operand size mismatch for 'movabs'

What am I missing?

Here's the entire error from my mac

level3.s:1:27: error: invalid operand for instruction
movq $0x3534373536383235, 0x000000000055638f8
                          ^~~~~~~~~~~~~~~~~~~
jww
  • 97,681
  • 90
  • 411
  • 885
Kendall Weihe
  • 2,021
  • 4
  • 27
  • 53
  • Possible duplicate of [movq and 64 bit numbers](http://stackoverflow.com/questions/19582654/movq-and-64-bit-numbers) – AnT stands with Russia Oct 13 '16 at 22:46
  • [AnT's link](https://stackoverflow.com/questions/19582654/movq-and-64-bit-numbers) is not a great dup target because the question is confused / broken: `movq $0xffffffffffffffff, -8(%rbp)` is encodeable with a sign-extended 32-bit immediate, and other problems, see my comments on that question. – Peter Cordes Mar 01 '18 at 18:32
  • Related: [why we can't move a 64-bit immediate value to memory?](https://stackoverflow.com/q/62771323) and [Difference between movq and movabsq in x86-64](https://stackoverflow.com/q/40315803) – Peter Cordes Sep 17 '20 at 16:28

2 Answers2

7

If you look in the manual under the lemma MOV (which is, admittedly, a bit intimidating), you will find that there is no mov r/m64, imm64.

There's a way to load a full 64bit constant into a register, and there's a way to load a sign-extended 32bit constant into a 64bit memory location, but there is no single instruction that takes a 64bit immediate and writes it to memory.

So you have to do it in two steps, such as by using a temporary register or by writing two dwords straight to memory separately.

harold
  • 61,398
  • 6
  • 86
  • 164
4

One way to do it is:

movabsq  $0x3534373536383235, %rax
movabsq  %rax, 0x000000000055638f8

As the other comment says, you can't move a 64 bit immediate to a 64 bit memory address because there is no instruction that allows you to do this. This opcode is missing because opcodes cannot currently exceed 15 bytes, and the two 64 bit values alone are 16 bytes, and would have to be part of the opcode. This limitation applies to smaller opcodes that would become too large with prefixes as well. Because you are moving to an absolute 64 bit memory address, you will want to use movabs or movabsq, whichever your assembler likes.

XorMalice
  • 154
  • 3
  • OP specified both a 64 bit address and a 64 bit constant, though. – XorMalice Oct 14 '16 at 19:19
  • Do you happen to know why opcodes can't exceed 15 bytes? – jeteon Jul 26 '17 at 23:36
  • 1
    @jeteon: It's the whole *instruction* that's limited to 15 bytes; the opcode is at most 2 bytes, or more if you include the mandatory prefixes. This limit makes designing a fast decoder easier. Original 8086 decoded one byte at a time or something, but later CPUs decode a whole instruction at once. Making sure a fixed-width buffer can always hold a whole instruction is helpful. IDK why they picked 15 instead of 16 or something, but a 4-bit counter can hold 15 but not 16. – Peter Cordes Feb 15 '18 at 05:50
  • @PeterCordes : 8086 could prefetch 6 bytes. – Michael Petch Feb 15 '18 at 06:02
  • @MichaelPetch: Right, but didn't it decode them one at a time? Or was that just prefixes? Of course, the only way 16-bit machine code can get that big is via prefixes, so once it's done chewing through prefixes and the opcode byte, the 6-byte buffer (or 4 in 8088?) was (almost) big enough to hold operands. Modern CPUs of course decode groups of multiple instructions in parallel, so upper length limits are obviously useful there; no fallback needed in case a 16-byte decode block (starting at the beginning of the next not-decoded instruction) can't contain a whole instruction. – Peter Cordes Feb 15 '18 at 06:07