由于某种原因,Mov 和 add 什么都不做

Mov and add are doing nothing for some reason

我从我的大学教授那里得到了这段代码,所以我相当确定代码有效,但对我来说输出总是 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。

这部分汇编语言...

    mov eax, edi
    add eax, esi

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

然而,Linux 64 位 ABI 的使用与汇编语言的其余部分不一致:特别是,在 Linux(所有变体)上,一个名为 func 对应于名为 func 的汇编语言过程,而不是 _func。但这应该会导致您的程序无法 link(gcc 命令会产生一条错误消息说 "undefined reference to `func'"),而不是产生不正确的输出。

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

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