相关疑难解决方法(0)

使用GCC的内联汇编直接调用

如果要从内联汇编中调用C/C++函数,可以执行以下操作:

void callee() {}
void caller()
{
    asm("call *%0" : : "r"(callee));
}
Run Code Online (Sandbox Code Playgroud)

然后GCC将发出如下所示的代码:

movl $callee, %eax
call *%eax
Run Code Online (Sandbox Code Playgroud)

这可能会有问题,因为间接调用会破坏旧CPU上的管道.

由于地址callee最终是常量,可以想象可以使用i约束.引自GCC在线文档:

'我"

允许使用立即整数操作数(具有常量值的操作数).这包括符号常量,其值仅在汇编时或以后知道.

如果我尝试这样使用它:

asm("call %0" : : "i"(callee));
Run Code Online (Sandbox Code Playgroud)

我从汇编程序中收到以下错误:

错误:后缀或操作数对`call'无效

这是因为GCC会发出代码

call $callee
Run Code Online (Sandbox Code Playgroud)

代替

call callee
Run Code Online (Sandbox Code Playgroud)

所以我的问题是是否可以使GCC输出正确call.

c c++ gcc inline-assembly function-call

11
推荐指数
1
解决办法
9852
查看次数

我如何告诉 gcc 我的内联汇编破坏了堆栈的一部分?

考虑这样的内联汇编:

uint64_t flags;
asm ("pushf\n\tpop %0" : "=rm"(flags) : : /* ??? */);
Run Code Online (Sandbox Code Playgroud)

尽管可能存在某种内在函数来获取 RFLAGS 的内容,但我如何向编译器表明我的内联汇编破坏了堆栈顶部的一个四字内存?

c gcc x86-64 inline-assembly red-zone

7
推荐指数
1
解决办法
529
查看次数

在扩展内联ASM中调用printf

我试图在64位Linux上的GCC扩展内联ASM中输出相同的字符串两次.

int main()
{
    const char* test = "test\n";

    asm(
        "movq %[test], %%rdi\n"    // Debugger shows rdi = *address of string*  
        "movq $0, %%rax\n"

        "push %%rbp\n"
        "push %%rbx\n"
        "call printf\n"         
        "pop %%rbx\n"
        "pop %%rbp\n"

        "movq %[test], %%rdi\n" // Debugger shows rdi = 0
        "movq $0, %%rax\n"

        "push %%rbp\n"
        "push %%rbx\n"
        "call printf\n"     
        "pop %%rbx\n"
        "pop %%rbp\n"
        : 
        :  [test] "g" (test)
        : "rax", "rbx","rcx", "rdx", "rdi", "rsi", "rsp"
        );

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在,字符串只输出一次.我尝试了很多东西,但我想我错过了关于调用约定的一些注意事项.我甚至不确定clobber列表是否正确,或者我是否需要保存和恢复RBPRBX.

为什么字符串不输出两次? …

printf gcc x86-64 inline-assembly calling-convention

4
推荐指数
1
解决办法
1194
查看次数