我有一些C代码:

#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);
}

我正在编译并在我的(英特尔)Mac笔记本电脑上运行.

代码的输出似乎有所不同,这取决于我是用(GNU)GCC还是Clang编译的. 我为GCC编译了gnucc -o gnu-test test.c(我从https://gcc.gnu.org/install/download.html下载源代码后,在我的Mac上从源代码构建了gnucc),为Clang(内置MacOS Clang)编译了clang -o clang-test test.c.

在我的Mac上,使用GNU,结果是2(这是我预期的).有了Cang,结果是140701838959608.

在我看来,Clang的结果似乎是错误的,但我也在想,也许是我的内联汇编不太正确,而GCC只是碰巧没有expose 我的错误.

我在Compiler Explorer上try 了相同的代码,GCC(x86-64 GCC 13.2给2)和Clang(x86-64 Clang 16.0.0给140726522786920)的输出也不同.

我try 反汇编带有objdump -d的Clang二进制代码:

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>

100003f80: 48 89 00 movq %rax, (%rax)似乎是问题所在?Clang在ecx中具有正确的值,在rax中具有正确的写入地址,但它使用movq %rax, (%rax)而不是movq %rcx, (%rax)

推荐答案

Clang正在生成正确的代码,但您在输入操作数上指定的约束不正确.

约束("rax")不被解释为寄存器名称.相反,约束中的每个字母指定一种允许的操作数类型.这里的第一个字母r允许使用任何通用寄存器,这使得rcx的 Select 有效.

要约束到rax寄存器,您需要使用"a"约束.请参阅machine constraints page中的x86部分.

__asm__("movq %%rax, %0\n" : "=m" (anum.x) : "a"(2));

C++相关问答推荐

从STdin读写超过4096个字节

在C语言中使用scanf()时我无法理解的警告

如何正确地索引C中的 struct 指针数组?

GCC预处理宏和#杂注GCC展开

在没有动态内存分配的情况下,用C语言最快地将各种数组复制到单个较大的数组中

在CLANG中调试预处理器宏

是什么让numpy.sum比优化的(自动矢量化的)C循环更快?

平均程序编译,但结果不好

如何使解释器存储变量

不同出处的指针可以相等吗?

如何使用FSeek和文件流指针在C中查找文件的前一个元素和前一个减go 一个元素

当内存来自Malloc时,将char*转换为另一个指针类型是否违反了严格的别名规则?

从另一个宏函数调用C宏

某些EAX值的不同调用方的CPUID结果不一致

发送和接收的消息中的Unix域套接字不匹配

为什么GCC不能在 struct 初始值设定项中以sizeof作为条件的三进制中处理复合文字的编译时求值?

';malloc():损坏的顶部大小';分配超过20万整数后

C 和 C++ 标准如何告诉您如何处理它们未涵盖的情况?

与 C 相比,C++ 中无副作用的无限循环的好处是 UB?

计算 e^x 很好.但不是 x 的罪