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

时间:2013-11-19 04:27:33

标签: winapi assembly nasm

我今天开始学习汇编,并在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复制。 任何帮助深表感谢!谢谢!

1 个答案:

答案 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函数名称。