0

我正在尝试使用 NASM 创建一个与 Microsoft Visual Studio 2012 生成的目标文件尽可能接近的目标文件。我已经非常接近了,但我正在努力处理导入和重定位。

具体来说,当我使用 and 创建一个目标文件时cl.exedumpbin /all binary.obj我得到以下感兴趣的行:

Offset     Type     Applied To     Symbol Index   Symbol Name
--------   -------  ----------     ------------   -----------
00000007   DIR32      00000000               B    __imp__GetModuleHandleA@4

但是当我这样做时dumpbin /all nasmobj.obj,我会得到一条类似但略有不同的行:

Offset     Type     Applied To     Symbol Index   Symbol Name
--------   -------  ----------     ------------   -----------
00000007   REL32      00000000               7    __imp__GetModuleHandleA@4

所以不同之处在于 MSVC 产生的重定位是“直接”重定位,而我的 NASM 代码产生“相对”重定位。我怎样才能解决这个问题?

我正在编译我的 NASM 代码:

nasm -f win32 nasmtst.s

感兴趣的 NASM 代码是:

SECTION .text
EXTERN __imp__GetModuleHandleA@4
%define GetModuleHandleA (__imp__GetModuleHandleA@4)

; code happens
...
call GetModuleHandleA
...
; more code happens
4

1 回答 1

1

请注意,这__imp__GetModuleHandleA@4是一个导入指针,而不是 GetModuleHandleA 函数的实际代码位置。Win32 PE 通常有一个 .idata 部分,其中收集了所有导入指针,这有点类似于 ELF 的 GOT 表:

SECTION .idata
   __imp__GetModuleHandleA@4 dd ? ; to be filled by system loader

这部分和所有支持的元数据通常由链接器使用导入库生成,但也可以手动生成

在您的情况下,以下内容就足够了:

EXTERN __imp__GetModuleHandleA@4 
call [__imp__GetModuleHandleA@4]

使用一些汇编器/宏包,可以使用类似于:

call GetModuleHandleA

或者

invoke GetModuleHandleA, eax

这将导致调用链接器生成的存根:

GetModuleHandleA:
   jmp [__imp__GetModuleHandleA@4]

这种方法的优点是只有一个重定位需要修补(对于jmp指令),而不是可能的几个(call一个)。

于 2013-07-22T18:02:10.643 回答