After reading this stack overflow answer, and this document, I still don't understand the difference between movq and movabsq.
My current understanding is that in movabsq, the first operand is a 64-bit immediate operand whereas movq sign-extends a 32-bit immediate operand. From the 2nd document referenced above:
Moving immediate data to a 64-bit register can be done either with the
movqinstruction, which will sign extend a 32-bit immediate value, or with themovabsqinstruction, when a full 64-bit immediate is required.
In the first reference, Peter states:
Interesting experiment:
movq $0xFFFFFFFF, %raxis probably not encodeable, because it's not representable with a sign-extended 32-bit immediate, and needs either the imm64 encoding or the%eaxdestination encoding.(editor's note: this mistaken assumption is fixed in the current version of that answer).
However, when I assemble/run this it seems to work fine:
.section .rodata
str:
.string "0x%lx\n"
.text
.globl main
main:
pushq %rbp
movq %rsp, %rbp
movl $str, %edi
movq $0xFFFFFFFF, %rsi
xorl %eax, %eax
call printf
xorl %eax, %eax
popq %rbp
ret
$ clang file.s -o file && ./file
prints 0xffffffff. (This works similarly for larger values, for instance if you throw in a few additional "F"s). movabsq generates an identical output.
Is Clang inferring what I want? If it is, is there still a benefit to movabsq over movq?
Did I miss something?