[英]Unresolved external symbol printf in Windows x64 Assembly Programming with NASM
我最近一直在嘗試學習匯編,並偶然發現了這篇文章。 作者使用NASM和微軟鏈接器搭建匯編環境。 我按照相同的步驟安裝了 NASM。 然后我開始編譯 hello world 應用程序。 編譯成功,但是在鏈接階段出現錯誤。 錯誤如下:
hello_world.obj : error LNK2001: unresolved external symbol printf
hello_world_basic.exe : fatal error LNK1120: 1 unresolved external
這是微軟鏈接器(link.exe)的輸出。 我按照帖子中的描述從開發人員命令提示符運行鏈接命令,並且因為 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
在閱讀了 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.