1

几天前我开始玩PE格式。我已经完成了小型 PE 加载器,它能够根据它们的虚拟地址将部分加载到内存中。例如,我有.text关于虚拟地址0x1000的部分,或.data关于0x2000. 使用我的小汇编代码,我在某个空闲位置 ( 0x10000) 上加载了 PE 文件,并从它的位置加载了 PE 部分。所以,部分.text0x110000x10000 + 0x1000)上,.data0x12000等等......但是当我从位置引用我的汇编数据时.code,我发现(在反汇编中)它指向0x402000. 在互联网上,我找到了特定于每种图像类型的图像库之类的东西......但我不明白如何.exe加载到0x402000例如,当在 Windows 中运行大量可执行文件时。有人为什么会这样,它是如何工作的,我如何在我非常基本的系统中理论上实现它?

请帮忙。

4

3 回答 3

3

虚拟内存意味着计算机上的每个进程都可以使用“相同”的地址,因为每个进程的地址空间都是独立的。进程 A 的 0x400000 被操作系统映射到与进程 B 的 0x400000 不同的物理地址,即使它们是相同的虚拟地址(不同的虚拟地址空间)。

可执行文件的默认基地址是 0x400000。您的链接器将基地址硬编码到可执行文件中,并将适当地调整地址引用。当程序启动时,您的可执行文件将被加载到该地址。您的汇编器或链接器应该为您提供更改此默认基地址的方法。

请注意,另一方面,DLL 必须在唯一的地址加载,因为它们必须共存于同一进程中。出于这个原因,DLL 通常是可重定位的,即它们在加载时可以具有任何基地址,以应对将它们置于唯一地址的要求。(在系统上拥有多个不可重定位的 DLL 可能会导致问题,但在系统上拥有多个不可重定位的 .exe 则完全没有问题。)

于 2013-03-10T16:37:09.130 回答
3

每个可执行文件都在其自己的虚拟地址空间中运行。因此,即使两个可执行文件具有相同的 0x400000 映像库,它们也会驻留/使用不同的物理内存。将其视为图像库的基础不同。

To get the image base of a module loaded into your running process you can use GetModuleHandle. It returns a handle to the module which incidently equals the image base. Alternatively you can get the image base from the ImageBase field in the PE Headers IMAGE_OPTIONAL_HEADER structure (see here).

于 2013-03-10T16:49:12.613 回答
1

这是一个复杂的主题,但是由于虚拟内存和硬件辅助的进程分离,每个进程都被加载,并且给人的印象是它拥有自己的整个地址空间。因此,所有镜像库都可以从同一个地址开始,因为虚拟内存中的地址可以映射到内存的任何位置,就它而言,进程拥有无限的内存。

于 2013-03-10T16:38:21.297 回答