Неразрешенный внешний символ C++ с Ассемблером
Я пытаюсь сделать функцию в ассемблере, чтобы использовать ее в C. Моя проблема в том, что я не могу скомпилировать свой код. Я использую Visual Studio 2012. Я добавил MASM в Custiomization сборки, поэтому я понятия не имею, что не так. C:
#include <stdio.h>
int szukaj_max (int a, int b, int c);
int main()
{
int x, y, z, wynik;
printf("\nProszępodaćtrzy liczby całkowite: ");
scanf_s("%d %d %d", &x, &y, &z, 32);
wynik = szukaj_max(x, y, z);
printf("\nSpośród podanych liczb %d, %d, %d, \ liczba %d jest największa\n", x,y,z, wynik);
return 0;
Монтаж:
.686
.model flat
public _szukaj_max
.code
_szukaj_max PROC
push ebp ; zapisanie zawartości EBP na stosie
mov ebp, esp ; kopiowanie zawartości ESP do EBP
mov eax, [ebp+8] ; liczba x
cmp eax, [ebp+12] ; porownanie liczb x i y
jge x_wieksza ; skok, gdy x >= y
; przypadek x < y
mov eax, [ebp+12] ; liczba y
cmp eax, [ebp+16] ; porownanie liczb y i z
jge y_wieksza ; skok, gdy y >= z
; przypadek y < z
; zatem z jest liczbąnajwiekszą
wpisz_z:
mov eax, [ebp+16] ; liczba z
zakoncz:
pop ebp
ret
x_wieksza:
cmp eax, [ebp+16] ; porownanie x i z
jge zakoncz ; skok, gdy x >= z
jmp wpisz_z
y_wieksza:
mov eax, [ebp+12] ; liczba y
jmp zakoncz
_szukaj_max ENDP
END
Ошибка:
Error 2 error LNK2019: unresolved external symbol "int __cdecl szukaj_max(int,int,int)" (? szukaj_max@@YAHHHH@Z) referenced in function _main C:\Users\Kaczor\Desktop\Ako\4.1\4.1\Source.obj
Error 3 error LNK1120: 1 unresolved externals C:\Users\Kaczor\Desktop\Ako\4.1\4.1\Debug\4.1.exe 1
2 ответа
Компилятор основного файла, содержащего вызов функции, предполагает, что это файл C++, например, потому что имя файла заканчивается на ".cpp". Поэтому компилятор интерпретирует объявление int szukaj_max (int a, int b, int c);
как объявление функции C++. Тем не менее, ваш файл ассемблера определяет функцию C.
Основное различие заключается в искажении имен: имена символов, сгенерированные для функций C++, содержат информацию о параметрах, главным образом для облегчения разрешения перегрузки компоновщиком. Поэтому простой символ _szukaj_max
даже не искал. (Я был изначально смущен __cdecl
появляется в сообщении об ошибке, но это определяет проблемы ABI, такие как порядок передачи параметров, обязанности по очистке стека и т. д., а не искажение имени.)
Более подробную информацию о "украшенных именах", как называет их Microsoft, смотрите здесь.
Решение:
- Каноническим и переносимым способом является объявление функции "extern C" в вашем основном файле:
extern "C" int szukaj_max(int a, int b, int c);
- Назовите функцию так, как этого ожидают компилятор и компоновщик. Вероятно, вы можете объединить имя вручную или просто посмотрите на ошибку компоновщика: имя в вашем случае
?szukaj_max@@YAHHHH@Z
(без подчеркивания). Это не переносимо, потому что другие компиляторы имеют другие соглашения. (Но тогда ассемблер MASM может быть не полностью переносимым.) - Или, если вы на самом деле программируете на C, измените расширение основного имени файла на ".c", чтобы компилятор предполагал, что все объявленные функции являются функциями C (это правильное решение Ange). Это снова должно быть портативным.
Я считаю, что некоторые решения могут быть неполными, поэтому я просто добавляю свой процесс, надеясь, что он кому-то поможет.
Установка - это Visual Studio 2015 на x64 Windows 10 с расширением файла.cpp (компиляция для x64). Я пытался запустить этот int2d_x64.asm из al-khaser внутри моего приложения MFC Visual Studio.
Я нашел эту статью LALLOUS' LAB и этот ответ Майка Дейнса на msdn принципиально полезными, и вкратце:
- Добавьте файл.asm в свой проект (щелкните правой кнопкой мыши имя проекта> добавить элемент> существующий элемент> int2d_x64.asm)
- Добавьте поддержку компиляции файла.asm для вашего проекта (щелкните правой кнопкой мыши имя проекта> Зависимости сборки> Настройки сборки> установите флажок masm и нажмите ОК)
- Определите тип элемента файла.asm как Microsoft Macro Assembler для вашего файла (int2d_x64.asm в моем случае). (щелкните правой кнопкой мыши файл.asm в проводнике решений> Свойства> Общие> В раскрывающемся меню Тип элемента выберите Microsoft Macro Assembler)
- Определите саму функцию как
extern "C" void __int2d();
(В случае OP это будет так, как предложил @Peter - Reinstate Monica:extern "C" int szukaj_max(int a, int b, int c);
)
Вы должны назвать файл ".c", а не ".cpp". У меня была такая же проблема, и она была решена.