如何使用NASM以Microsoft Visual Studio的方式生成重定位?

时间:2013-07-22 17:13:38

标签: assembly nasm

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

具体来说,当我使用cl.exe创建一个目标文件并执行dumpbin /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

1 个答案:

答案 0 :(得分:1)

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

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

此部分和所有支持元数据通常由链接器使用导入库生成,但也可以generate it manually生成。

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

EXTERN __imp__GetModuleHandleA@4 
call [__imp__GetModuleHandleA@4]

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

的内容
call GetModuleHandleA

invoke GetModuleHandleA, eax

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

GetModuleHandleA:
   jmp [__imp__GetModuleHandleA@4]

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