32位汇编没有基址跟偏移地址的概念

32位汇编没有基址跟 偏移地址 的概念
你没发现call后面是DWORD PTR吗?这说明什么?
这说明call能寻址所有4GB地址空间
楼下的那个回答更是扯谈
32位的PE文件根本就不能用debug调试
楼主给出的明显是32位汇编代码
别拿你的16位汇编过来了!


楼主我想告诉你的是32位汇编没有段地址 偏移地址的概念
如果真的要跟16位汇编联系起来
那么你可以这么认为所有段地址寄存器在程序中都是0(实际上 段寄存器 保存的是段描述符)
所有在程序中给出的地址都是32位偏移地址,也就是程序地址空间的 绝对地址
call dword ptr [408030];这条指令我估计你是在OD这些调试工具下面看到的


对于408030这个问题
如果不是API函数而是程序自身函数
一般在程序中是直接call 函数首地址的
但是对于API函数因为是在把程序运行的时候才装入内存的


编译的时候根本不知道函数会被装入内存的哪个地方
所以不能call 绝对地址 来寻址


InitCommonControls是comctl32.dll在程序运行的时候被加载到程序地址空间之后
API函数InitCommonControls所在的首地址


如果 源代码 使用类似:
MessageBox(NULL,"Hello","Hello",MB_OK)
那么得到的 反汇编 代码不是你这样的而是这样的:
call 0040101A
........
:0040101A jmp dword [00402008]指向MessageBox函数
为什么要用效率这么低的方式呢?
因为编译器无法区别输入函数的调用和普通函数的调用


这里的call 0040101A指令从实际源代码中来而并非来自输入表的 函数指针


接下去会call到一个jmp指令,jmp指令来自于为输入函数准备的输入库(lib)
所以call以后的代码 都不是你能控制的了,因为这由输入库决定了


你给出的那种调用方式
源代码中是这样定义函数的(这些都在头文件中,有兴趣自己去找下):
void __declspec(dllimport) InitCommonControls(void);
这样就会产生call dword ptr [408030]; 而不是call XXXXXXXX
此外编译器讲给函数加上_imp_前缀,然后送给 连接器 ,这样可以直接把_imp_XXX送给输入表这样就不要jmp指令了


对于你的问题
我自己先写一段:

#include<windows.h>
#include<commctrl.h>
#pragma comment(lib,"comctl32.lib")


//_declspec(dllimport) void InitCommonControls(void);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int iCmdShow)
{
InitCommonControls();
MessageBox(NULL,"Hello","Hello",MB_OK);
return 0;
}




对initCommonControls函数的调用我得到的反汇编代码是call dword ptr ds:[42A1D0](不同操作系统,编译器编译出来地址不一样的)
由于这个函数怎么也不做编译器在编译的时候直接给出自己的代码mov eax,eax而并没有真正调用Windows API 所以你在PE文件中找不到这个函数
下面来说明MessageBox地址是怎么找到的:
在反汇编中 这个函数地址是

0042A320H


我们现在要知道的就是在exe没有被装入内存之前PE文件内部0042A320里面放的究竟是什么


先分析下 文件
由于建议装入地址是00400000
所以0042A320实际上处于相对 虚拟地址 (RVA)2A320处
正好处于idata节区内
因为2A000对应文件偏移28000
所以2A320对应文件便宜281D0
所以2A320对应文件便宜28320处
用WinHex查看文件28320结果是

0002A350这显然不会是MessageBox的内存地址
但是这也还是个RVA,处在idata中减去节首地址0002A000H是350H
相对节首28000H偏移350
查看文件偏移00028350H处发现过去两个字节就是MessageBox函数名了


有了函数名就能在内存中找到函数地址
有了函数地址就能调用了


楼主还有问题吗?看不懂的话仔细研究下PE文件的输入表和仔细分析下lib库文件就懂了
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值