我今天开始学习汇编,并在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复制。 任何帮助深表感谢!谢谢!
答案 0 :(得分:4)
首先,cl不是链接器而是编译器。为什么不直接使用我链接到的帖子中显示的GoLink?它更容易使用。你可以使用ld作为链接器,但你的外部会改变一点。
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函数名称。