gcc mingw 与汇编结合时给出垃圾输出

kin*_*gW3 1 c assembly gcc mingw calling-convention

我的 gcc:线程模型: posix

gcc 版本 8.1.0(x86_64-posix-seh-rev0,由 MinGW-W64 项目构建)

我正在尝试创建一个简单的应用程序,它使用 gcc 和 intel 语法对两个文件 saberi.c 和 saberi.s 的两个数字求和,其中 saberi 表示求和。

萨伯里.c

#include <stdio.h>
int saberi(int a, int b);
int main()
{   
    int a, b;
    scanf("%d %d", &a, &b);
    printf("Sum is: %d\n", saberi(a, b));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

军刀

.intel_syntax noprefix
.text
    .globl saberi
saberi:
    enter 0,0
    mov eax, edi
    add eax, esi
    leave
    ret
Run Code Online (Sandbox Code Playgroud)

然后我执行 gcc saberi.c saberi.s ,当我打开可执行文件并输入任意两个数字(例如 1 和 2)时,我会得到一个随机值作为总和。

Aja*_*iya 5

MinGW 编译器默认针对 Windows 目标进行编译。这意味着编译器遵循Windows ABI和 Windows 调用约定。前两个整数参数传入 和rcxrdx而不是像System V ABI 中那样传入rdi和。rsi

您可以通过生成 saberi.c 的程序集来进行验证:

gcc -S saberi.c -o saberi_compiled.s
Run Code Online (Sandbox Code Playgroud)

您将看到,在调用之前saberi,编译器将参数移动到ecx和中edx

所以你的 saberi.s 应该改为 -

intel_syntax noprefix
.text
    .globl saberi
saberi:
    enter 0,0
    mov eax, ecx
    add eax, edx
    leave
    ret
Run Code Online (Sandbox Code Playgroud)

你应该得到正确的结果。

另一种选择是告诉编译器在调用时使用 System V ABI saberisysv_abi这可以在 gcc (MinGW) 中使用函数属性来完成saberi

int saberi(int a, int b) __attribute__((sysv_abi));
Run Code Online (Sandbox Code Playgroud)

然后你可以保持你的装配相同。当您想要编写可跨平台移植的程序集时,此方法非常有用。但当然仅限于gcc