Search code examples
assemblyx86-64gnu-assemblerinstruction-set

Error: operand type mismatch for `add' immediate value GNU Assembler intel syntax


I tried this simple assembly:

add r9, 0x4014000000000000

It gave me error:

Error: operand type mismatch for `add'

I also try:

addq r9, 0x4014000000000000 #(second operand is 64-bit)

which q stand for quad 64-bit, CMIIW.

I'm sure r9 is 64-bit wide.

I also try:

add r9, 0xffffffffffffffff #(second operand is 64-bit too)

But this time where second operand is 0xffffffffffffffff which it's 64-bit operand is working fine, so what was happened?


Solution

  • There is no encoding that supports a 64-bit immediate on the add instruction, just like it is the case for the majority of instructions.

    To add r9, 0x4014000000000000, move the immediate to a scratch register and add that to R9.

    mov rax, 0x4014000000000000
    add r9, rax
    

    Your add r9, 0xffffffffffffffff instruction does work because in this case 'the very big' immediate value is in fact just -1, and that's a value that nicely fits the encoding that sign-extends a 32-bit immediate into a 64-bit value. The assembler will even do better and use a single byte immediate to encode this instruction.
    Your add r9, 0xffffffffffffffff is actually add r9, -1.

    For 64-bit values in [0xFFFFFFFFFFFFFF80, 0x000000000000007F], (-128, +127) the assembler encodes a sign-extendable 8-bit immediate.
    For 64-bit values in [0xFFFFFFFF80000000, 0x000000007FFFFFFF], (-2147483648, +2147483647) the assembler encodes a sign-extendable 32-bit immediate.
    Other 64-bit values cannot be encoded.