Неразрешенный внешний символ 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 принципиально полезными, и вкратце:

  1. Добавьте файл.asm в свой проект (щелкните правой кнопкой мыши имя проекта> добавить элемент> существующий элемент> int2d_x64.asm)
  2. Добавьте поддержку компиляции файла.asm для вашего проекта (щелкните правой кнопкой мыши имя проекта> Зависимости сборки> Настройки сборки> установите флажок masm и нажмите ОК)
  3. Определите тип элемента файла.asm как Microsoft Macro Assembler для вашего файла (int2d_x64.asm в моем случае). (щелкните правой кнопкой мыши файл.asm в проводнике решений> Свойства> Общие> В раскрывающемся меню Тип элемента выберите Microsoft Macro Assembler)
  4. Определите саму функцию как extern "C" void __int2d(); (В случае OP это будет так, как предложил @Peter - Reinstate Monica: extern "C" int szukaj_max(int a, int b, int c);)

Вы должны назвать файл ".c", а не ".cpp". У меня была такая же проблема, и она была решена.

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