【问题标题】:Call exported functions of DLL in assembly without .lib file在没有 .lib 文件的程序集中调用 DLL 的导出函数
【发布时间】:2021-02-15 13:07:20
【问题描述】:

所以我目前正在尝试在我的程序集文件中调用 dll 的导出函数。 DLL 与我的 asm 程序在同一目录中,我没有 .lib 文件。

这是我的代码:

EXTERN __imp__CreateCompressor@12:PROC
EXTERN __imp__Compress@24:PROC
EXTERN __imp__CloseCompressor@4:PROC

.code
START:
            push 2 ;COMPRESS_ALGORITHM_MSZIP
            push 0
            push  OFFSET hCompress
            call    __imp__CreateCompressor@12

            push 0 ;CompressedDataSize
            push DWORD ptr [DataSize] ;CompressedBufferSize
            push eax ;CompressedBuffer
            push DWORD ptr [DataSize]
            push DWORD ptr [pBuf3]
            push DWORD ptr [hCompress]
            call __imp__Compress@24

            push DWORD ptr [hCompress]
            call __imp__CloseCompressor@4
END START

但是我得到了错误:

file.obj : error LNK2001: unresolved external symbol ___imp__CreateCompressor@12
file.obj : error LNK2001: unresolved external symbol ___imp__Compress@24
file.obj : error LNK2001: unresolved external symbol ___imp__CloseCompressor@4
file.exe : fatal error LNK1120: 3 unresolved externals

我是这样组装的: ml file.asm /link /subsystem:console /entry:START

有什么想法吗?

【问题讨论】:

  • EXTERN __imp__CreateCompressor@12:DWORD 必须是。不是PROC 等等 __imp_ 符号
  • 比你需要添加 Cabinet.lib 用于链接器输入
  • 您必须拥有 .lib 文件才能解决链接器错误。不难获得,它包含在 Windows SDK 中。

标签: windows assembly dll masm


【解决方案1】:

您必须使用LoadLibrary() 和GetProcAddress() 函数来加载库并从您要调用的函数中获取地址。

【讨论】:

  • 可以,但不是必须的。与 Cabinet.lib 更好的链接
  • @RbMm,OP说他没有lib文件,所以他必须动态加载dll。
  • 这个库是 microsoft SDK 的一部分。所以所有需要 - 只需下载它
  • @RbMm,在这种情况下,这确实是一个解决方案。 :)
  • lib-files 并不是特别神奇,您可以获取函数名称列表并使用 lib 实用程序从中制作 lib-file .. OP 甚至没有需要这样做,因为这个 lib-file 已经存在
【解决方案2】:

要启用Load-Time Dynamic Linking,链接器需要一个导入库。

如果没有导入库,您将不得不使用Run-Time Dynamic Linking。

或者,您可以自己生成一个导入库。最简单的方法是编写一个适当的Module-Definition (.Def) File 并让Microsoft Librarian Manager (LIB.exe) 生成一个导入库。

【讨论】:

  • 不认为 .def 在这里就足够了。如果只使用def,我们无法设置多少个参数有作用。所以不可能生成说__imp__Compress@24。但可能将 def 与 c/c++ 结合使用,我们在其中定义了虚拟函数“实现”,例如void __stdcall Compress(int,int,int,int,int,int){} - 这已经在 lib 中给出了__imp__Compress@24
  • @rbm .def 文件足以创建导入库。导入库足以描述在哪里可以找到符号,这就是问题所要求的。
  • 你错了 - 链接器怎么知道,如何只在 x86 中用 def 装饰符号?如果我们声明Compress - lib 中必须有什么符号? _Compress ? _Compress@0 ? _Compress@4 ? _Compress@24 ? _Compress@32 ? @Compress@8 ?
  • @rbm 没有人建议链接器需要猜测。链接器只解析符号。由于 .def 文件包含修饰符号名称,因此在使用从该 .def 文件生成的导入库时无需进行事后猜测。
  • 好的,我们把Compress@24放到def文件中。链接器将_Compress@24 和__imp__Compress@24 放入库中,但_Compress@24 在生成的PE 中作为导入名称。但我们需要Compress(因为cabinet.dll导出这样的Compress没有装饰)
猜你喜欢
  • 2013-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多