在汇编程序中链接到Kernel32.lib



我今天开始学习汇编,并在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函数名称,因为它们出现在文档中。