gpt4 book ai didi

dll - 我如何将调用 DLL 的 NASM 程序与 FreePascal 链接?

转载 作者:行者123 更新时间:2023-12-04 20:27:42 24 4
gpt4 key购买 nike

问题

我有一个用汇编程序 (nasm) 编写的函数“bob”,它使用了 kernel32.dll 中的函数。我在 FreePascal 中有一个名为“bob”的程序。

我将 nasm 用于:

nasm -fwin32 bob.asm

在 FreePascal 中我声明:

{$link bob.obj}

function bob(s:pchar):longint; stdcall; external name 'bob';

但是当我用 fpc 编译时出现错误,告诉它找不到 GetStdHandle 和 WriteConsoleA(没有 @n 后缀),它们在 bob.asm 中声明为 extern。我想告诉 fpc 在 kernel32.dll 或足够的导入库中查找它们。

但是,当我在纯汇编程序中使用相同的函数时,它在 nasm 和 golink 上工作正常。当我不调用 DLL 函数时,我可以毫无问题地与 FreePascal 链接。

如何将 kernel32 函数与 FreePascal 链接起来,以便汇编函数“看到”它们?


解决方案

由贝尼贝拉提供。我改了名字,这样事情就很容易理解了。

program dlltest;

function WindowsGetStdHandle(n: longint): longint; stdcall;
external 'kernel32.dll' name 'GetStdHandle';

{$asmmode intel}
procedure WrapperGetStdHandle; assembler; public name 'AliasGetStdHandle';
asm
jmp WindowsGetStdHandle
end;


{$link myget.obj}

function AsmGetStdHandle(n: longint): longint; stdcall;
external name 'gethandle';

const STDOUT = -11;

begin
writeln(AsmGetStdHandle(STDOUT));
writeln(WindowsGetStdHandle(STDOUT));
end.

在汇编中,在 myget.asm 中:

section .text

extern AliasGetStdHandle

global gethandle

gethandle:
mov eax, [esp+4]
push eax
call AliasGetStdHandle
ret 4

WindowsGetStdHandle 是 kernel32.dll 中 GetStdHandle 的别名。

WrapperGetStdHandle只跳到前面,这里是为了 alias public name 能力:我们为外部对象命名为 AliasGetStdHandle。这是重要的部分,函数对汇编程序可见。

AsmGetStdHandle 是汇编函数 gethandle 在 FreePascal 中的名称。它调用 WrapperStdHandle(昵称 AliasGetStdHandle),它跳转到 WindowsGetStdHandle,DLL 函数。

我们完成了,现在可以链接汇编程序,而无需更改其中的任何内容。所有重命名机制都在调用它的 Pascal 程序中完成。

唯一的缺点:需要一个包装函数,但它对于名称的精细控制来说并不过分。


另一种解决方案

如果在 WindowsGetStdHandle 的声明中未指定 kernel32.dll,但使用 {$linklib kernel32},则该符号在 pascal 程序链接的目标文件中可见。然而,似乎只有 $linklib 指令是不够的,仍然必须在 pascal 中声明一些引用它的函数

program dlltest;

{$linklib kernel32}

function WindowsGetStdHandle(n: longint): longint; stdcall;
external name 'GetStdHandle';

{$link myget.obj}

function AsmGetStdHandle(n: longint): longint; stdcall;
external name 'gethandle';

const STDOUT = -11;

begin
writeln(AsmGetStdHandle(STDOUT));
writeln(WindowsGetStdHandle(STDOUT));
end.

用下面的汇编程序。 AliasGetStdHandle 替换为 GetStdHandle,后者现在直接指向 kernel32 函数。

section .text

extern GetStdHandle

global gethandle

gethandle:
mov eax, [esp+4]
push eax
call GetStdHandle
ret 4

但这仅在使用外部链接器 (gnu ld) 和命令时有效

fpc -Xe dlltest.pas

当省略 opton '-Xe' 时,fpc 给出以下错误

Free Pascal Compiler version 2.6.0 [2011/12/25] for i386
Copyright (c) 1993-2011 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling dlltest.pas
Linking dlltest.exe
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_dir_kernel32.dll
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_names_kernel32.dll
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_fixup_kernel32.dll
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_dll_kernel32.dll
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_names_end_kernel32.dll
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_fixup_end_kernel32.dll
dlltest.pas(17,1) Fatal: There were 6 errors compiling module, stopping
Fatal: Compilation aborted

最佳答案

我不知道如何直接解决链接问题,但您可以声明从 Pascal 源代码导出这些函数的公共(public)包装函数。

例如:

{$ASMMODE INTEL}
procedure WrapperGetStdHandle; assembler; public; alias: '_GetStdHandle@4';
asm jmp GetStdHandle end;
procedure WrapperWriteConsoleA; assembler; public; alias: '_WriteConsoleA@20';
asm jmp WriteConsoleA end;

关于dll - 我如何将调用 DLL 的 NASM 程序与 FreePascal 链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14726346/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com