I have some C code:
#include "stdio.h"
typedef struct num {
unsigned long long x;
} num;
int main(int argc, char **argv) {
struct num anum;
anum.x = 0;
__asm__("movq %%rax, %0\n" : "=m" (anum.x) : "rax"(2));
printf("%llu\n",anum.x);
}
which I'm compiling and running on my (Intel) Mac laptop.
The output from the code seems to be different depending on whether I compile with (GNU) GCC or Clang.
I compile with gnucc -o gnu-test test.c
for GCC (I built gnucc
from source on my Mac after downloading the source from https://gcc.gnu.org/install/download.html) and clang -o clang-test test.c
for Clang (built-in macOS Clang).
On my Mac, with GNU, the result is 2
(which is what I expect). With Clang, the result is 140701838959608
.
The Clang result seems wrong to me, but I'm also wondering if, perhaps, my inline assembly isn't quite correct and GCC just happens to not expose my error.
I tried out the same code on Compiler Explorer and the output there is also different for GCC (x86-64 GCC 13.2 gives 2
) and Clang (x86-64 Clang 16.0.0 gives 140726522786920
).
I tried disassembling the Clang binary with objdump -d
:
clang-test: file format mach-o 64-bit x86-64
Disassembly of section __TEXT,__text:
0000000100003f60 <_main>:
100003f60: 55 pushq %rbp
100003f61: 48 89 e5 movq %rsp, %rbp
100003f64: 48 83 ec 20 subq $32, %rsp
100003f68: 89 7d fc movl %edi, -4(%rbp)
100003f6b: 48 89 75 f0 movq %rsi, -16(%rbp)
100003f6f: 48 c7 45 e8 00 00 00 00 movq $0, -24(%rbp)
100003f77: 48 8d 45 e8 leaq -24(%rbp), %rax
100003f7b: b9 02 00 00 00 movl $2, %ecx
100003f80: 48 89 00 movq %rax, (%rax)
100003f83: 48 8b 75 e8 movq -24(%rbp), %rsi
100003f87: 48 8d 3d 16 00 00 00 leaq 22(%rip), %rdi ## 0x100003fa4 <_printf+0x100003fa4>
100003f8e: b0 00 movb $0, %al
100003f90: e8 09 00 00 00 callq 0x100003f9e <_printf+0x100003f9e>
100003f95: 31 c0 xorl %eax, %eax
100003f97: 48 83 c4 20 addq $32, %rsp
100003f9b: 5d popq %rbp
100003f9c: c3 retq
Disassembly of section __TEXT,__stubs:
0000000100003f9e <__stubs>:
100003f9e: ff 25 5c 00 00 00 jmpq *92(%rip) ## 0x100004000 <_printf+0x100004000>
and 100003f80: 48 89 00 movq %rax, (%rax)
seems to be the issue? Clang has the correct value in ecx
and the correct address to write to in rax
, but it does movq %rax, (%rax)
instead of movq %rcx, (%rax)
?