Windows x64 汇编编程 NASM 中未解析的外部符号 printf
Unresolved external symbol printf in Windows x64 Assembly Programming with NASM
我最近一直在尝试学习汇编,遇到了这个post。笔者使用NASM和微软linker搭建了汇编环境。我按照相同的步骤安装了 NASM。然后我开始编译 hello world 应用程序。编译成功,但是在link阶段报错。错误如下:
hello_world.obj : error LNK2001: unresolved external symbol printf
hello_world_basic.exe : fatal error LNK1120: 1 unresolved external
这是微软 linker(link.exe) 的输出。我 运行 link 来自 Developer Command Prompt 的命令,如 post 中所述,并且因为 hello world 是一个 64 位应用程序,我正确设置了 LIB 环境变量(即使在post ).
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 Studio19\Community\VC\Tools\MSVC.27.29110\ATLMFC\lib\x86;C:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.27.29110\lib\x64;C:\Program Files (x86)\Windows Kits\NETFXSDK.8\lib\um\x86;C:\Program Files (x86)\Windows Kits\lib.0.19041.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\lib.0.19041.0\um\x64
然后 link 变成可执行文件。
link hello_world.obj /subsystem:console /entry:main /out:hello_world_basic.exe "KERNEL32.LIB"
问题是什么?有什么我遗漏的吗?
根据 link Microsoft has moved some standard C stuff into another library @Jester 分享。
The definitions of all of the printf and scanf functions have been moved inline into <stdio.h>, <conio.h>, and other CRT headers. This breaking change leads to a linker error (LNK2019, unresolved external symbol) for any programs that declared these functions locally without including the appropriate CRT headers.If possible, you should update the code to include the CRT headers (that is, add #include <stdio.h>) and the inline functions, but if you do not want to modify your code to include these header files, an alternative solution is to add an additional library to your linker input, legacy_stdio_definitions.lib.
因此你需要link 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
最后,运行 linker 如下。
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
中的 link 命令,您可以从 Visual Studio 20XX 下的“开始”菜单启动(教程中建议的 Developer Command Prompt for VS 20XX
不工作)。
将此用作 link 命令:
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
已添加
我最近一直在尝试学习汇编,遇到了这个post。笔者使用NASM和微软linker搭建了汇编环境。我按照相同的步骤安装了 NASM。然后我开始编译 hello world 应用程序。编译成功,但是在link阶段报错。错误如下:
hello_world.obj : error LNK2001: unresolved external symbol printf
hello_world_basic.exe : fatal error LNK1120: 1 unresolved external
这是微软 linker(link.exe) 的输出。我 运行 link 来自 Developer Command Prompt 的命令,如 post 中所述,并且因为 hello world 是一个 64 位应用程序,我正确设置了 LIB 环境变量(即使在post ).
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 Studio19\Community\VC\Tools\MSVC.27.29110\ATLMFC\lib\x86;C:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.27.29110\lib\x64;C:\Program Files (x86)\Windows Kits\NETFXSDK.8\lib\um\x86;C:\Program Files (x86)\Windows Kits\lib.0.19041.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\lib.0.19041.0\um\x64
然后 link 变成可执行文件。
link hello_world.obj /subsystem:console /entry:main /out:hello_world_basic.exe "KERNEL32.LIB"
问题是什么?有什么我遗漏的吗?
根据 link Microsoft has moved some standard C stuff into another library @Jester 分享。
The definitions of all of the printf and scanf functions have been moved inline into <stdio.h>, <conio.h>, and other CRT headers. This breaking change leads to a linker error (LNK2019, unresolved external symbol) for any programs that declared these functions locally without including the appropriate CRT headers.If possible, you should update the code to include the CRT headers (that is, add #include <stdio.h>) and the inline functions, but if you do not want to modify your code to include these header files, an alternative solution is to add an additional library to your linker input, legacy_stdio_definitions.lib.
因此你需要link 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
最后,运行 linker 如下。
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
中的 link 命令,您可以从 Visual Studio 20XX 下的“开始”菜单启动(教程中建议的 Developer Command Prompt for VS 20XX
不工作)。
将此用作 link 命令:
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
已添加