1

我从我的大学教授那里得到了这段代码,所以我相当肯定代码有效,但对我来说,输出总是 0。

我在 Windows 和虚拟 Ubuntu 机器上尝试过,但还是一样。

我正在使用 mingw 进行编译:

gcc test.c test.s

这是C代码:

#include <stdio.h>

int func(int a, int b);

int main()
{   
    int a, b;
    scanf("%d %d", &a, &b);
    printf("%d\n", func(a, b));
    return 0;
}

这是组装:

.intel_syntax noprefix

.text

    .globl _func

_func:

    enter 0,0

    mov eax, edi
    add eax, esi
    leave
    ret

对于输入 2 和 3,它应该输出 5,但它始终为 0。

4

1 回答 1

3

这部分汇编语言...

    mov eax, edi
    add eax, esi

int... 是将前两个参数添加到函数并返回结果的一种正确方法,如果函数的前两个int参数在寄存器中edi并且esi. 在 x86 Linux 上,当且仅当程序使用“64 位 ABI”编译时才是正确的,这可能是也可能不是您的 Ubuntu 虚拟机默认执行的操作。据我所知,无论 ABI 如何,在 Windows 上都不是这样。

但是,Linux 64 位 ABI 的使用与汇编语言的其余部分不一致:特别是在 Linux(所有变体)上,名为 C 的函数func对应于名为 的汇编语言过程func,而不是_func。但这应该会导致您的程序无法链接(该gcc命令会产生一条错误消息,说“未定义对 `func' 的引用”),而不是产生不正确的输出。

我建议您回到给您汇编代码的教授那里,并询问他们应该使用什么操作系统和 ABI,以及如何使其适应您可以方便访问的计算机。

(您以前可能没有遇到过“ABI”这个术语。它代表应用程序二进制接口,它是一系列关于诸如过程调用之类的低级细节如何工作的规则。例如,“x86-64 ELF ABI” ",这是 Linux 使用的,它表示函数调用的前两个整数参数在 CALL 指令之前放置在 DI 和 SI 寄存器中(按此顺序),返回后将在 AX 中找到一个整数返回值. 但是 x86-64 Windows ABI 说函数的前两个整数参数被放置在其他两个寄存器中——我不记得是哪两个——而 x86-32 ELF ABI 说它们进入堆栈。尽管每个人都同意 AX 中出现的整数返回值。)

于 2019-01-26T03:18:39.210 回答