c - 根据 linux 上的 x86-64 调用约定设置本地堆栈

标签 c assembly gnu red-zone

我正在对在 64 位 Linux 上运行的 gnu C 代码进行一些扩展的汇编优化。我想从汇编代码中打印调试消息,这就是我遇到以下内容的方式。我希望有人能解释我在这种情况下应该做什么。

看看这个示例函数:

    void test(int a, int b, int c, int d){


        __asm__ volatile (

        "movq $0, %%rax\n\t"
        "pushq %%rax\n\t"
        "popq %%rax\n\t"


        :
        :"m" (a)
        :"cc", "%rax"
        );

}

由于函数的四个参数属于 INTEGER 类,它们将通过寄存器传递,然后压入堆栈。对我来说奇怪的是 gcc 实际上是如何做到的:

test:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    %edi, -4(%rbp)
        movl    %esi, -8(%rbp)
        movl    %edx, -12(%rbp)
        movl    %ecx, -16(%rbp)

        movq $0, %rax
        pushq %rax
        popq %rax

        popq    %rbp
        ret

传递的参数被压入堆栈,但堆栈指针没有减少。因此,当我执行 pushq %rax 时,ab 的值将被覆盖。 我想知道的是:有没有办法让 gcc 正确设置本地堆栈?难道我不应该在函数调用中使用 pushpop 吗?

最佳答案

x86-64 abi 在堆栈指针下提供了一个 128 字节的红色区域,编译器决定使用它。您可以使用 -mno-red-zone 选项将其关闭。

关于c - 根据 linux 上的 x86-64 调用约定设置本地堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27361534/

相关文章:

将C代码转换为8086汇编

c - 嵌入式Linux。以原子方式执行代码块

c - 读取全局环境变量

c - 下标具有寄存器存储类的数组

android - 如何处理构建过程中自动生成的源代码文件

java - 最长递增子序列 - 无法理解实际的 LIS 创建

c - 从文件接收到数据并需要打印它,但程序没有正确读取数据?

windows - .data 部分是否加载到内存中?

c - 如何将 Intel Assembly C 转换为 AT&T C++

c - 为什么 ARM gcc 在函数开始时将寄存器 r3 和 lr 压入堆栈?