我最近一直在尝试学习汇编,并且偶然发现了这篇文章。作者使用NASM和Microsoft链接器来设置组装环境。我遵循相同的步骤并安装了NASM。然后,我开始编译hello world应用程序。编译成功,但是在链接阶段出现错误。错误如下:
hello_world.obj : error LNK2001: unresolved external symbol printf
hello_world_basic.exe : fatal error LNK1120: 1 unresolved external
这是Microsoft链接器(link.exe)的输出。我按照文章中的描述运行来自Developer Command Prompt的链接命令,并且因为hello world是64位应用程序,所以我正确设置了LIB环境变量(即使文章中未提及)。
hello_world.asm
bits 64
default rel
segment .data
msg db "Hello world!", 0xd, 0xa, 0
segment .text
global main
extern ExitProcess
extern printf
main:
push rbp
mov rbp, rsp
sub rsp, 32
lea rcx, [msg]
call printf
xor rax, rax
call ExitProcess
在Windows命令提示符下编译程序。
nasm -f win64 -o hello_world.obj hello_world.asm
设置LIB环境变量。
set LIB=LIB=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\ATLMFC\lib\x86;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\lib\x64;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\um\x64
并链接成可执行文件。
link hello_world.obj /subsystem:console /entry:main /out:hello_world_basic.exe "KERNEL32.LIB"
问题是什么?我有什么想念的吗?
根据链接,Microsoft已将一些标准C内容移至@Jester共享的另一个库中。
所有printf和scanf函数的定义都已内联移动到<stdio.h>,<conio.h>和其他CRT标头中。此重大更改会导致在本地声明这些功能但不包括适当的CRT头文件的任何程序的链接器错误(LNK2019,未解析的外部符号)。如果可能,应更新代码以包括CRT头文件(即添加#include <stdio.h>)和内联函数,但是如果您不想修改代码以包括这些头文件,则另一种解决方案是在链接器输入中添加一个额外的库legacy_stdio_definitions.lib。
因此,您需要链接legacy_stdio_definitions.lib
以实现,printf
还需要初始化CRT,因此请将源代码更改为
bits 64
default rel
segment .data
msg db "Hello world!", 0xd, 0xa, 0
segment .text
global main
extern ExitProcess
extern _CRT_INIT
extern printf
main:
push rbp
mov rbp, rsp
sub rsp, 32
call _CRT_INIT
lea rcx, [msg]
call printf
xor rax, rax
call ExitProcess
最后,按如下所示运行链接器。
link hello_world.obj /subsystem:console /entry:main /out:hello_world_basic.exe kernel32.lib legacy_stdio_definitions.lib msvcrt.lib
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句