Mov и add ничего не делают по какой-то причине

Я получил этот код от своего университетского профессора, так что я уверен, что этот код работает, но для меня результат всегда равен 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 ответ

Решение

Эта часть языка ассемблера...

    mov eax, edi
    add eax, esi

... один правильный способ добавить первые два int аргументы функции и возвращают результат, если первые два int аргументы функции находятся в регистрах edi а также esi, В x86 Linux это верно, если и только если программа скомпилирована с "64-битным ABI", который может или не может быть тем, что ваша виртуальная машина Ubuntu делает по умолчанию. Насколько я знаю, это никогда не верно для Windows, независимо от ABI.

Однако использование 64-битного ABI в Linux несовместимо с остальной частью языка ассемблера: в частности, в Linux (все разновидности) функция C называется func соответствует процедуре на языке ассемблера с именем funcне _func, Но это должно было привести к тому, что ваша программа перестала связываться (gcc Команда выдала бы сообщение об ошибке "неопределенная ссылка на`func'"), чтобы не выдавать неправильный вывод.

Я советую вам вернуться к профессору, который дал вам код сборки и спросить их, с какой операционной системой и ABI она должна работать, и как адаптировать ее к компьютерам, к которым у вас есть удобный доступ.

(Возможно, вы раньше не сталкивались с термином "ABI". Он обозначает двоичный интерфейс приложения и представляет собой набор правил для того, как работают низкоуровневые детали таких вещей, как вызовы процедур. Например, "x86-64 ELF ABI"). "Это то, что использует Linux, говорит, что первые два целочисленных аргумента вызова функции помещаются в регистры DI и SI (в указанном порядке) перед инструкцией CALL, а целочисленное возвращаемое значение будет найдено в AX после его возврата Но ABI Windows x86-64 говорит, что первые два целочисленных аргумента функции помещаются в некоторые два других регистра - я не помню, какие два - и ELIF ABI x86-32 говорит, что они идут в стек. Все согласны с тем, что целые возвращаемые значения появляются в AX.)

Другие вопросы по тегам