我今天开始学习汇编,并在linux上运行了许多测试,效果非常好!我移到我的电脑上,开始尝试在这里写一些。我在尝试调用外部函数时遇到了一个问题(在linux上运行良好),在那里我会得到LINK 2001 Unsolved 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
几乎完全是从这里复制的。非常感谢您的帮助!谢谢
首先,cl不是一个链接器,而是一个编译器。为什么不像我在你链接的帖子中显示的那样使用GoLink呢?它更容易使用。您可以使用ld作为链接器,但您的外部会有一些变化。
Windows API函数使用函数名称装饰-下划线+FunctionName+@sizeof参数,这是链接器的事情。
因此,ExitProcess实际上导出为_ExitProcess@4因为它采用1个DWORD参数。WriteConsoleA采用5个DWORD大小的参数,因此_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 SDK \Windows\v6.0\Lib"
那么只需将-l
标志与库一起使用-l kernel32
我的makefile使用NASM和ld作为您的示例代码:
APP= Sample
all: $(APP) clean
$(APP): $(APP).obj
"C:MinGWbinld" $(APP).obj -o $(APP).exe -L "C:Program FilesMicrosoft SDKsWindowsv6.0Lib" -l kernel32
$(APP).obj: $(APP).asm
nasm -f win32 $(APP).asm -o $(APP).obj
clean:
rm $(APP).obj
如果你像在另一篇文章中一样使用GoLink,你可以只使用API函数名称,因为它们出现在文档中。