4
votes

I want to move a 64-bit unsigned integer to a register using inline asm. What happens is the constant gets sign-extended if it in fact fits in 32 bits.

Here is my code:

#include "stdint.h"
uint64_t foo() {
    uint64_t x;
    asm ("movq %1, %0"
         : "=q" (x)
         : "i" (0x00000000faceffff) );
    return x;
}

Now, clang -S code.c produces the following assembly:

#APP    
movq    $-87097345, %rax        # imm = 0xFFFFFFFFFACEFFFF
#NO_APP

Same thing for gcc. Same thing for movabsq in place of movq. Same for "p" constraint instead of "i".

I get the result I expect if the constant is larger than 32 bits.

1
deleted previous comment as it's now in the answer. Will delete this comment later. - rcgldr
If it fits in 32 bits you don't need a 64bit mov in the first place. - harold
@harold, I do need it, because in my real use case I'll want to patch the constant which is 64 bit in general (an address). - Vladislav Ivanishin

1 Answers

3
votes

Is there a suffix for constants to declare them as unsigned long long with gcc? With Microsoft compilers it's "...ull" in this case 0x00000000faceffffull.