Search code examples
cassemblycalling-conventionintel-syntax

Mov and add are doing nothing for some reason


I got this code from my university professor, so I'm fairly certain that the code works, but for me the output is always 0.

I tried it on Windows and on a virtual Ubuntu machine but still the same.

I'm compiling using mingw:

gcc test.c test.s

This is the C code:

#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;
}

And this is assembly:

.intel_syntax noprefix

.text

    .globl _func

_func:

    enter 0,0

    mov eax, edi
    add eax, esi
    leave
    ret

For inputs 2 and 3 it should output 5, but it's always 0.


Solution

  • This part of the assembly language ...

        mov eax, edi
        add eax, esi
    

    ... is one correct way to add the first two int arguments to a function and return the result, if the first two int arguments to the function are in registers edi and esi. On x86 Linux, that is true if and only if the program is compiled with the "64-bit ABI", which may or may not be what your Ubuntu virtual machine does by default. As far as I know, it is never true on Windows, regardless of ABI.

    Use of the Linux 64-bit ABI, however, is not consistent with the rest of the assembly language: in particular, on Linux (all varieties) a C function named func corresponds to an assembly language procedure named func, not _func. But this should have caused your program to fail to link (the gcc command would have produced an error message saying "undefined reference to `func'"), not to produce incorrect output.

    I advise you to go back to the professor who gave you the assembly code and ask them what operating system and ABI it's supposed to work with, and how to adapt it to the computer(s) you have convenient access to.

    (You may not have encountered the term "ABI" before. It stands for Application Binary Interface, and it's a bunch of rules for how the low-level details of things like procedure calls work. For instance, the "x86-64 ELF ABI", which is what Linux uses, says that the first two integer arguments to a function call are placed in the DI and SI registers (in that order) before the CALL instruction, and an integer return value will be found in AX after it returns. But the x86-64 Windows ABI says that the first two integer arguments to a function are placed in some other two registers -- I don't remember which two -- and the x86-32 ELF ABI says they go on the stack. Everyone agrees on integer return values appearing in AX though.)