问题描述
我最近一直在尝试学习汇编语言,并遇到了这个post。作者使用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 has moved some standard C stuff into another library @Jester已共享。
所有printf和scanf函数的定义都已内联移动到
, 和其他CRT标头中。此重大更改将导致在本地声明这些功能但不包括适当的CRT标头的任何程序的链接器错误(LNK2019,未解析的外部符号)。如果可能,应更新代码以包括CRT标头(即添加#include )和内联函数,但是如果您不想修改代码以包含这些头文件,则另一种解决方案是在链接器输入中添加一个额外的库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
,
在阅读 this discussion 中 Darran Rowe 的回答后设法解决了这个问题。他还进一步解释了为什么需要做这些事情。
解决办法如下:
在 x64 Native Tools Command Prompt for VS 20XX
中运行链接命令,您可以在 Visual Studio 20XX 下从“开始”菜单启动该命令(教程中建议的 Developer Command Prompt for VS 20XX
不起作用)。
将其用作链接命令:
link hello_world.obj /subsystem:console /out:hello_world_basic.exe kernel32.lib legacy_stdio_definitions.lib msvcrt.lib
这里的变化是:
-
/entry:main
已被删除 -
kernel32.lib legacy_stdio_definitions.lib msvcrt.lib
已添加