我今天开始学习汇编,并在 linux 上运行了很多测试,效果非常好!我搬到了我的电脑上,开始尝试在这里写一些东西。我在尝试调用外部函数(再次在 Linux 上运行良好)时遇到问题,我会收到 LINK 2001 Unresolved External 错误,告诉我在使用 nasm 编译后未定义 WriteConsoleA:
nasm -f win32 test.asm -o test.obj
和 cl.exe:
cl test.obj /link libcmt.lib kernel32.lib
我收到这些错误:
test.obj : error LNK2001: unresolved external symbol ExitProcess
test.obj : error LNK2001: unresolved external symbol GetStdHandle
test.obj : error LNK2001: unresolved external symbol WriteConsoleA
test.exe : fatal error LNK1120: 3 unresolved externals
程序集:
extern ExitProcess, GetStdHandle, WriteConsoleA
NULL equ 0
STD_OUTPUT_HANDLE equ -11
section .data
msg db "Hello world!",0xa
msgLen equ $-msg
section .bss
dummy resd 1
section .text
global _main
_main:
push STD_OUTPUT_HANDLE
call GetStdHandle
push NULL
push dummy
push msgLen
push msg
push eax
call WriteConsoleA
push NULL
call ExitProcess
几乎完全复制自 here . 任何帮助深表感谢!谢谢!
最佳答案
首先,cl 不是链接器而是编译器。为什么不像我在您链接到的帖子中显示的那样使用 GoLink?它更容易使用。您可以使用 ld 作为链接器,但您的 externs 会稍微改变。
Windows API 函数使用函数名装饰 - 一个下划线 + FunctionName + @sizeof 参数,这是一个链接器的东西。
因此,ExitProcess 实际上导出为 _ExitProcess@4,因为它需要 1 个 DWORD 参数。 WriteConsoleA 采用 DWORD 大小的 5 个参数,因此它将是 _WriteConsole@20
将您的代码更改为:
extern _ExitProcess@4, _GetStdHandle@4, _WriteConsoleA@20
%define ExitProcess _ExitProcess@4
%define GetStdHandle _GetStdHandle@4
%define WriteConsoleA _WriteConsoleA@20
NULL equ 0
STD_OUTPUT_HANDLE equ -11
section .data
msg db "Hello world!",0xa
msgLen equ $-msg
section .bss
dummy resd 1
section .text
global _main
_main:
push STD_OUTPUT_HANDLE
call GetStdHandle
push NULL
push dummy
push msgLen
push msg
push eax
call WriteConsoleA
push NULL
call ExitProcess
要与 ld 链接,告诉它 lib 目录在哪里,一个不错的选择是: -L "C:\Program Files\Microsoft SDKs\Windows\v6.0\Lib"
然后只需在库中使用 -l
标志
-l kernel32
我的 makefile 使用 NASM 和 ld 作为您的示例代码:
APP= Sample
all: $(APP) clean
$(APP): $(APP).obj
"C:\MinGW\bin\ld" $(APP).obj -o $(APP).exe -L "C:\Program Files\Microsoft SDKs\Windows\v6.0\Lib" -l kernel32
$(APP).obj: $(APP).asm
nasm -f win32 $(APP).asm -o $(APP).obj
clean:
rm $(APP).obj
如果您要像在另一篇文章中那样使用 GoLink,您可以只使用文档中显示的 API 函数名称。
关于winapi - 在汇编程序中链接到 Kernel32.lib,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20063224/