我费了很大的劲才让它运转起来:
我尝试了以下方法:
uint32_t reverseBits(volatile uint32_t n) {
uint32_t i = n;
__asm__ (".intel_syntax\n"
"xor eax, eax \n"
"inc eax \n"
"myloop: \n"
"shr %0, 1 \n"
"adc eax, eax \n"
"jnc short myloop \n"
"mov %1, %0 \n"
: [i] "=r"(i), [n] "=r"(n));;
return n;
}
我会得到:
Line 11: Char 14: error: unknown token in expression
"shr %0, 1 \n"
^
<inline asm>:5:5: note: instantiated into assembly here
shr %edx, 1
^
显然,编译器将< code>%0替换为< code>%register,但仍然保留< code>'%'...
因此,我决定将 %0
替换为 edx
,将 %1
替换为 ecx
:
uint32_t reverseBits(volatile uint32_t n) {
uint32_t i = n;
__asm__ (".intel_syntax\n"
"xor eax, eax \n"
"inc eax \n"
"myloop: \n"
"shr edx, 1 \n"
"adc eax, eax \n"
"jnc short myloop \n"
"mov ecx, edx \n"
: [i] "=r"(i), [n] "=r"(n));;
return n;
}
并得到结果错误:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==31==ERROR: AddressSanitizer: SEGV on unknown address 0x0001405746c8 (pc 0x00000034214d bp 0x7fff1363ed90 sp 0x7fff1363ea20 T0)
==31==The signal is caused by a READ memory access.
#1 0x7f61ff3970b2 (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
AddressSanitizer can not provide additional info.
==31==ABORTING
我怀疑编译器优化了东西并内联了被调用的函数(所以没有雷特),但仍然不知道我该怎么做。
注意:我不能把编译器从clang改成gcc,因为用clang 11的不是我而是一个远程服务器。我也已经看过这个链接,但它已经很旧了(2013年),如果从那以后事情没有改变,我会感到惊讶。
编辑:在彼得·科德斯的出色回答之后,我能够让它工作得更好一点:
uint32_t reverseBits(volatile uint32_t n) {
uint32_t i = n;
__asm__ (".intel_syntax noprefix\n"
"xor rax,rax \n"
"inc rax \n"
"myloop: \n"
"shr %V0, 1 \n"
"adc eax, eax \n"
"jnc short myloop \n"
"mov %V0, rax \n"
".att_syntax"
: [i] "=r"(i));;
return i;
}
然而有两件事:
1/我不得不将eax
更改为rax
,因为
=64位(
),这很奇怪,因为
I
2/我没有得到所需的输出:
input is : 00000010100101000001111010011100
output is: 93330624 (00000101100100000001110011000000)
expected: 964176192 (00111001011110000010100101000000)
注意:我测试了< code >“mov % v 0,1 \ n”
并正确地得到了< code>1作为输出,这证明了替换以某种方式工作。
我不知道有什么好的方法来做到这一点,我建议在
(更新:clang 14更改了以下内容:如何将gcc或clang设置为在内联asm()语句中永久使用英特尔语法?)
如何在英特尔语法中生成带有clang的汇编代码?是关于<code>-S</code>输出所使用的语法,与GCC不同,它没有连接到编译器的内联asm输入语法。--x86 asm syntax=intel
的行为没有改变:它仍然以英特尔语法输出,对内联asm没有帮助。
您可以滥用%V0
或%V[i]
(而不是%0
或%[i]
)来打印模板https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#x86Operandmodifiers中的“裸”完整寄存器名称,但这很糟糕,因为它只打印完整寄存器名称。即使对于选择EAX的32位int,它也会打印RAX而不是EAX。
(对于< code >“m”内存操作数来说,获取< code>dword ptr [rsp 16]或任何编译器选择的寻址模式也不起作用,但总比没有好。虽然在我看来,这并不比仅仅使用AT更好
或者您可以选择像"=a"(var)
这样的硬寄存器,然后显式使用EAX而不是%0
。但这更糟糕,并且破坏了约束系统的一些优化优势。
模板中仍然需要“.intel_syntax noprefix\n”
,并且应该以“.att_syntax”
结束模板,以将汇编程序切换回 AT
显然,告诉编译器它可以使用< code>"=r"选择任何寄存器,然后实际使用您自己的硬编码选择,当编译器选择不同的寄存器时,将会产生未定义的行为。您将踩在编译器的脚趾上,破坏它以后想要使用的值,并让它从错误的寄存器中获取垃圾作为输出。IDK,你为什么费事在你的问题中包括这一点;这对at来说是完全一样的
我正在使用Intel Ivy Bridge CPU,希望使用RDRAND操作码(https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide)在C#中。 如何通过C#调用此CPU指令?我在这里看到了一个从c#执行汇编代码的示例:C#
如这个问题所示,使用g,我可以< code > g-S-masm = Intel test . CPP 。另外,使用clang,我可以执行< code>clang -S test.cpp,但是clang不支持< code>-masm=intel(编译期间未使用的< code >警告参数:-masm=intel)。我如何用clang得到intel语法?
问题内容: 每次与Hotspot一起使用时,都不得不烦恼我,不得不阅读可怕的AT&T语法。 有没有办法告诉它使用英特尔语法? 问题答案: 您所需要做的就是将一些选项解析到dis-asm.h和binutils代码上 对于Intel Asm(我也更喜欢),只需添加以下内容 如果您需要组合选项,请像这样用逗号分隔 任何未被识别为hsdis选项的内容都将被提供给反汇编程序,这些选项与您从中看到的选项相同
问题内容: 按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实,参考或专业知识的支持,但是这个问题可能会引起辩论,争论,民意调查或扩展讨论。如果您认为此问题可以解决并且可以重新提出,请访问帮助中心以获取指导。 8年前关闭。 对我来说,英特尔语法更容易阅读。如果我只关注Intel语法来遍历汇编林,我会错过任何事情吗?我有什么理由要切换到AT&T(除了能够读取其他人的AT&T程序集之外
如何使用Java中的Intel AVX矢量指令集?这是一个简单的问题,但答案似乎很难找到。
我需要从英特尔处理器中的随机生成器(英特尔酷睿i3)获取随机数。我不想使用任何图书馆。我想在C中使用汇编程序粘贴,但我不知道应该使用哪些寄存器和指令。