Luc*_*s S 2 assembly winapi nasm
我今天开始学习汇编,并在 linux 上运行了许多测试,效果很好!我转移到我的电脑上并开始尝试在这里写一些。我在尝试调用外部函数时遇到了一个问题(这在 linux 上也能正常工作),我会得到 LINK 2001 Unresolved External 错误,告诉我在使用 nasm 编译后未定义 WriteConsoleA:
nasm -f win32 test.asm -o test.obj
Run Code Online (Sandbox Code Playgroud)
并使用 cl.exe:
cl test.obj /link libcmt.lib kernel32.lib
Run Code Online (Sandbox Code Playgroud)
我收到这些错误:
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
Run Code Online (Sandbox Code Playgroud)
大会:
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
Run Code Online (Sandbox Code Playgroud)
几乎完全从这里复制。任何帮助深表感谢!谢谢!
首先,cl 不是链接器,而是编译器。为什么不像我在您链接到的帖子中显示的那样使用 GoLink?使用起来要容易得多。您可以使用 ld 作为链接器,但您的 extern 会发生一些变化。
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
Run Code Online (Sandbox Code Playgroud)
要与 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
Run Code Online (Sandbox Code Playgroud)
如果您像在另一篇文章中那样使用 GoLink,则可以使用文档中显示的 API 函数名称。