gpt4 book ai didi

linux - clang 错过汇编程序错误?

转载 作者:太空宇宙 更新时间:2023-11-04 09:25:36 29 4
gpt4 key购买 nike

在我看来,clang++ 错过了 g++ 拾取的汇编代码中的错误。还是我缺少一些 clang 的编译器标志?我是汇编代码的新手。

我使用 clang++ 编译并链接了我的应用程序,没有错误和警告,但我遇到了严重的段错误。切换到 g++,另一方面,我遇到了这些错误:

GO_F_ImageColourConversion.cpp: Assembler messages:
GO_F_ImageColourConversion.cpp:4679: Error: `(%rsi,%edx,2)' is not a valid base/index expression
GO_F_ImageColourConversion.cpp:4682: Error: `(%rcx,%edx,1)' is not a valid base/index expression

我正在使用这些编译器标志:-DLINUX -g -Wno-deprecated -D_GNU_SOURCE -D_REENTRANT -D__STDC_CONSTANT_MACROS -fPIC -fPIE

我有以下代码(省略不相关的部分):

Ipp8u * pSrc;
Ipp8u * pDst;
int x, y;

asm volatile
(
"movl (%1, %0, 2), %%eax;\n"
"shlw $8, %%ax;\n"
"shrl $8, %%eax;\n"
"movw %%ax, (%2, %0, 1);\n"

: /* no output */
: "r" (x), "r" (pSrc), "r" (pDst)
: "eax", "memory");
}

从看这个answer on SO ,我意识到我有一个 32/64 位问题(我正在移植到 64 位)。Ipp8u* 是 8 位,但在我的机器上只有 4 位。

将 int 更改为 uintptr_t x, y; 似乎可以解决问题。为什么 clang 在编译时不报错?

最佳答案

gcc 和 clang 都对我的代码感到窒息:

6 : error: base register is 64-bit, but index register is not
"movl (%1, %0, 2), %%eax\n"
^
<inline asm>:1:13: note: instantiated into assembly here
movl (%rdi, %edx, 2), %eax

来自 clang 3.8 on the godbolt compiler explorer ,它周围有一个函数,所以它是可测试的,你在问题中没有提供。您确定您的 clang 正在构建 64 位代码吗? (-m64,不是 -m32-mx32)。

在 Godbolt 上提供指向您的代码的链接,某些版本的 clang 会默默地错误编译它,否则对于您的实际问题我只能说“无法重现”。

是的,您的问题是 x 是一个 int,您的问题是寻址模式下的混合寄存器大小。 (%rsi,%edx,2) 不可编码。


使用 %q0 获取 %rdx 并不能保证寄存器的高 32 位中没有垃圾(尽管这种可能性很小)。相反,您可以使用 "r"((int64_t)x)sign-extend x to 64bits .

为什么您需要内联汇编?您的 C 版本的编译器输出有多糟糕?

如果您确实想使用内联 asm,这好得多:

uint32_t asm_tmp = *(uint32_t *)(x*2 + (char*)pSrc);  // I think I've reproduced the same pointer math as the addressing mode you used.
asm ( "shlw $8, %w[v]\n\t" // e.g. ax
"shrl $8, %k[v]\n\t" // e.g. eax. potential partial-register slowdown from reading eax after writing ax on older CPUs
: [v] "+&r" (asm_tmp)
);
*(uint16_t *)(x + (char*)pDst) = asm_tmp; // store the low 16

这可以用 clang 很好地编译,但是 gcc is kinda braindead about generating the address .也许地址有不同的表达方式?

您的代码以加载开始并以存储结束,从而违背了约束的目的。总是让编译器尽可能多地处理。如果没有内联 asm,您可能会从中获得更好的代码,并且编译器会理解它的作用,并且可能会自动矢量化或进行其他转换。使用 "memory" clobber 消除 asm 语句成为 volatile 的需要对优化器来说已经是一个很大的改进:现在它是一个编译器只知道转换的纯函数一个寄存器。

另见 the end of this answer有关编写不差劲的内联 asm 的更多指南。

关于linux - clang 错过汇编程序错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36885777/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com