7

At my 64bit Intel machine following code works:

mov rdi, 1 << 40
add r10, rdi

and this quite equivalent looking one produces a warning and doesn't work:

add r10, 1 << 40

Should I just stick with number 1 or am I missing something? This behaviour seems akward.

The warning produced by code nr 2:

warning: signed dword immediate exceeds bounds
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
user1864035
  • 113
  • 1
  • 4
  • Related: [How to push a 64bit int in NASM?](https://stackoverflow.com/questions/16917643/how-to-push-a-64bit-int-in-nasm): if a sign-extended imm32 won't work, usually best to `mov` the constant to a register, just like for ALU instructions like `add`. – Peter Cordes Mar 01 '18 at 18:14
  • 1
    Also related [`mov r64, imm64` vs. loading it from memory](https://stackoverflow.com/questions/46433208/which-is-faster-imm64-or-m64-for-x86-64). – Peter Cordes Mar 02 '18 at 01:17
  • [x86\_64 Cannot add 64 bit value to rax, "operand mismatch on 'add'"](https://stackoverflow.com/q/58258882) is the GAS version of this; much less helpful error message, but does error instead of warning and encoding a wrong value. – Peter Cordes Oct 10 '20 at 03:34
  • 1
    If the value is in memory you can just do a 32-bit add to the high part: `add dword ptr [var + 4], (1 << 40) >> 32` – phuclv Oct 10 '20 at 06:27
  • @PeterCordes As a side note compilers in 64 bit make use of `mov r64, disp[rip]` instead of using the `mov r64, imm64` because it is faster by about 23% (on my Xeon). – Alexis Wilke Mar 04 '23 at 05:19
  • 1
    @AlexisWilke: That's not what latest trunk GCC/clang do, at least not in a trivial `return 0x123456789ab;` function when tuning for recent Intel or AMD CPUs or with the default -mtune=generic (https://godbolt.org/z/eT4jMqMEG). I think I have seen them use memory for 64-bit constants in weird cases, but the risk is that on an L3 cache miss it's *much* slower. But yes, if all goes well, then throughput can be higher for a mov-load from memory and for a 10-byte mov imm64, depending on how well code packed into the uop cache. (Or if not running from the uop cache at all e.g. from JCC erratum) – Peter Cordes Mar 04 '23 at 09:53

1 Answers1

12

There is an opcode for mov r/m64, imm64, but there is no opcode for add r/m64, imm64 in the x86-64 instruction set. In other words: you cannot use 64-bit immediate operand for add, but you can for mov (there are many instructions that don't have the imm64 variant; you can check the Instruction Set Reference in the Intel Software Developer Manual to check which instructions have such variant and which don't).

Griwes
  • 8,805
  • 2
  • 43
  • 70
  • 4
    In fact `mov` is the *only* instruction that takes an `imm64`. See [Intel's insn set ref manual entry for `mov`](https://github.com/HJLebbink/asm-dude/wiki/MOV). (There's also a special AL/AX/EAX/RAX-only `moffs` form that doesn't use a regular addressing mode, and allows a 64-bit absolute address). But `mov r64, imm64` works with any reg. – Peter Cordes Mar 01 '18 at 18:13