C++中的未解决外部符号与汇编器

4

我正在尝试编写汇编语言函数以便在C语言中使用。我的问题是我无法编译我的代码。我正在使用Visual Studio 2012。我已经将masm添加到构建自定义项中,所以我不知道出了什么问题。 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

4
尝试使用extern "C" int szukaj_max (int a, int b, int c);。 (说明:这是一段C++代码,其中的extern "C"表示将函数按照C语言的方式进行编译链接,而不是C++的方式。该函数的作用是在a、b、c三个整数中寻找最大值并返回。) - Jester
3个回答

6
主文件的编译器假设它是一个C++文件,例如因为文件名以“.cpp”结尾。因此,编译器将声明 int szukaj_max (int a, int b, int c); 解释为声明一个C++函数。然而,汇编文件定义了一个C函数。
主要区别在于名称修饰: 为C++函数生成的符号名称包含有关参数的信息,主要是为了方便链接器进行重载解析。因此,简单的符号 _szukaj_max 甚至不会被查找。(我最初对错误消息中出现的 __cdecl 感到困惑,但它定义了ABI问题,如参数传递顺序、堆栈清理责任等,而不是名称修饰。)
有关“装饰名称”的更多信息,请参见微软的这里
解决方法:
  • 规范且可移植的方法是在主文件中声明函数为“extern C”:
    extern "C" int szukaj_max(int a, int b, int c);
  • 按照编译器和链接器所期望的方式命名函数。您可能可以手动拼凑名称,或者只需查看链接器错误:在您的情况下,名称为 ?szukaj_max@@YAHHHH@Z(没有前导下划线)。这不是便携式的,因为其他编译器有不同的约定。(但是MASM汇编器可能也不是完全可移植的。)
  • 或者,如果您实际上是在使用C语言进行编程,请将主文件名的扩展名更改为“.c”,以便编译器假设所有已声明的函数均为C函数(这是Ange的正确解决方案)。那应该是可移植的。

5

我认为一些解决方案可能不完整,所以我在这里添加我的过程,希望能对任何人有所帮助。

环境为Visual Studio 2015,操作系统为x64的Windows 10,文件扩展名为.cpp (编译为x64)。我试图在Visual Studio MFC应用程序中运行来自al-khaser的int2d_x64.asm

我发现LALLOUS' LAB的 这篇文章msdn上Mike Danes的这篇答案基本上是有帮助的,简而言之:

  1. 将 .asm 文件添加到项目中(右键单击项目名称 > 添加项 > 现有项目 > int2d_x64.asm)
  2. 为您的项目添加 .asm 文件编译支持(右键单击项目名称 > 生成依赖项 > 生成定制项 > 选中 masm 并单击确定)
  3. 将文件(例如我的 int2d_x64.asm 文件)的项目类型定义为 Microsoft Macro Assembler。(在解决方案资源管理器中右键单击 .asm 文件 > 属性 > 常规 > 在“项类型”下拉菜单中选择“Microsoft Macro Assembler”)
  4. 将函数本身定义为 extern "C" void __int2d(); (对于本题,可以像 @Peter - Reinstate Monica 建议的那样写成:extern "C" int szukaj_max(int a, int b, int c);

2

您需要将文件命名为“.c”,而不是“.cpp”,我曾经遇到过同样的问题,通过这样做解决了问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接