3

我正在尝试在汇编程序中创建函数以在 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

3 回答 3

6

包含函数调用的主文件的编译器假定它是 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 的正确解决方案)。那应该又是便携的。
于 2016-02-12T09:34:05.940 回答
3

我相信一些解决方案可能不完整,所以我只是添加我的过程,希望它可以帮助任何人。

安装程序是 x64 Windows 10 上的 Visual Studio 2015,带有 .cpp 文件扩展名(为 x64 编译)。我试图在我的 Visual Studio MFC 应用程序中从 al-khaser 运行这个 int2d_x64.asm 。

我发现LALLOUS' LAB 的这篇文章,以及Mike Danes 在 msdn 上的这个回答 从根本上是有帮助的,简而言之:

  1. 将 .asm 文件添加到您的项目中(右键单击项目名称 > 添加项目 > 现有项目 > int2d_x64.asm)
  2. 为您的项目添加 .asm 文件编译支持(右键单击项目名称 > 构建依赖项 > 构建自定义 > 复选标记 masm 并按确定)
  3. 将 .asm 文件项类型定义为您的文件的 Microsoft Macro Assembler(在我的例子中为 int2d_x64.asm)。(右键单击解决方案资源管理器中的 .asm 文件 > 属性 > 常规 > 从项目类型下拉菜单中,选择 Microsoft 宏汇编程序)
  4. 将函数本身定义为extern "C" void __int2d();(对于 OP 的情况,这将是 @Peter - Reinstate Monica 建议的extern "C" int szukaj_max(int a, int b, int c);:)
于 2020-11-11T09:38:11.127 回答
2

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

于 2016-02-12T08:17:15.180 回答