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.)