我正在使用内嵌组装x86_64与clang。我希望将确切的程序集编译到我在源代码中指定的二进制文件中,但出于某种原因,clang一直在更改它。只有在我使用AT&T GCC样式程序集时才会发生这种情况,而在MSVC __asm中则不会发生这种情况。我想使用AT&T样式程序集,因为我的其他代码经常使用AT&T样式,而且我希望保持一致。以下是我的程序集代码的声明方式:
__attribute__((naked)) void XxInternalOperation()
{
asm volatile("mov %%rcx, %%rax\n\t"
"mov %0, %%r11\n\t"
"jmpq *%%r11"
:
: "r" (jumpAddrAbsolute)
: "r11");
}我希望我的程序集代码表示这个英特尔代码:
mov rax, rcx
mov r11, jmpAddrAbsolute ; <-- this is an unsigned long long variable
jmp r11但是,在IDA中,一个快速的分解显示了一些其他的东西:
mov rax, cs:jumpAddrAbsolute
mov rax, rcx
mov r11, rax
jmp r11有什么方法可以得到我想要的确切的装配代码吗?
发布于 2020-07-14 09:30:07
Clang不会“改变”您的程序集。它完全按照您的要求执行,即:它选择一个寄存器(这就是r约束的意思),并以%0代替它。注意,这个寄存器也可以是rax,在这种情况下,您的代码将无法工作。如果希望clang选择内存操作数,则使用m约束。有关gcc式内联装配的详细信息,请参阅gcc手册。下面是一个例子:
extern unsigned long long jumpAddrAbsolute;
__attribute__((naked)) void XxInternalOperation()
{
asm volatile("mov %%rcx, %%rax\n\t"
"mov %0, %%r11\n\t"
"jmpq *%%r11"
:
: "m" (jumpAddrAbsolute)
: "r11", "rax");
}该文件汇编为:
movq %rcx, %rax
movq jumpAddrAbsolute(%rip), %r11
jmpq *%r11这似乎是你想要的。
请注意,自从您在第一条指令中使用rax后,我已经将它标记为clobbered。请进一步注意,在执行此内联程序集语句时,不能保证rcx保存任何特定的值。编译器可以自由地将其设置为它喜欢的任何值。
还请注意,编译器可能决定内联XxInternalOperation,在这种情况下,间接跳转将产生在调用方中执行尾调用的意外副作用。考虑将函数标记为noinline以避免这种情况。
不过,一般来说,在内联程序集中执行跳转或调用通常是错误方法的标志,通常会导致各种问题。如果您已经决定使用这个内联程序集解决问题的一些细节,我可能会向您建议一个更好的解决方案。
https://stackoverflow.com/questions/62888372
复制相似问题