我正在尝试使用与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
答案 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
个)。