Mov和Add由于某种原因无所事事

时间:2019-01-26 02:06:16

标签: c assembly calling-convention intel-syntax

我从大学教授那里获得了这段代码,因此我相当确定代码可以工作,但是对我来说输出始终为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。

1 个答案:

答案 0 :(得分:3)

这部分汇编语言...

    mov eax, edi
    add eax, esi

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

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

我建议您回到教授汇编代码的教授那里,询问他们应该使用哪种操作系统和ABI,以及如何使其适应您方便使用的计算机。< / p>

(您以前可能没有遇到过“ ABI”一词。它代表应用程序二进制接口,它是一堆规则,用于诸如过程调用之类的底层细节的工作方式。例如,“ x86- Linux使用的“ 64 ELF ABI”表示,函数调用的前两个整数参数(按此顺序)放在CALL指令之前的DI和SI寄存器中,并将在AX中找到一个整数返回值但是x86-64 Windows ABI表示,函数的前两个整数参数放在另外两个寄存器中(我不记得是哪两个),而x86- 32 ELF ABI表示它们进入堆栈。每个人都同意AX中出现的整数返回值。)