能力值:
( LV2,RANK:10 )
|
-
-
2 楼
编译的时候编译器决定的值就是不变的。反汇编出来看起来像硬编码的东西就是基址了。还有函数、全局变量之类的,他们的偏移是固定的,加上所在模块起始地址就是实际地址,这个也可以做基址
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
天堂猪:编译的时候编译器决定的值就是不变的。反汇编出来看起来像硬编码的东西就是基址了
------------------------------
再请教一下,关于“编译的时候编译器决定的值就是不变的”,其中这个值,编译器是根据什么来决定的?
这个值代表的是什么?
程序运行的时候,这个值与进程的地址空间有什么关系?
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
其实有可能会变:
LoadLibrary, LoadLibraryEx 不能指定载入的位址, 所以不做
特别的处理, 基址不变.
但是我可以在载入真正的数值运算DLL 之前, 先载入乱数(1 ~ N) 个
无用的DLL, 占用DLL 的位址空间, 这样基址就变了.
载入的基址可以用下列的简化的想法来思考.
主程序: M, 基本上位置不变. 载入的顺序基本不变.
系统DLL: AAAA(长度代表大小), BBB, CCCCC, DDDDDD,
游戏 DLL: II, J, KKKKK, LLLLLL
所以每次载入的基址都一样:
M AAAABBBCCCCCDDDDDDIIJKKKKKLLLLLL
如果Windows 改版, DLL 大小变了, 基址就变了. (AAAA->AAA)
M AAABBBCCCCCDDDDDDIIJKKKKKLLLLLL
如果游戏改版, DLL 大小变了, 基址就变了. (II->III, J->JJJJJ)
M AAABBBCCCCCDDDDDDIIIJJJJJJKKKKKLLLLLL
DLL 的大小一样时, Windows 每次载入的位置固定.
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
其实摆渡一下就好了
内存里面放的是运行程序的编码
要运行那些东西 先把硬盘里的数据移动到内存里
然后按寻址 找到相应程序的内容 即基址
0X之类的是内存地址来的
WINDOS XP 是运行在在支持虚拟地址空间的计算机上,虚拟地址空间或者映射到一段真实的物理内存,或者映射到交换文件中的页帧。不同的应用程序可能会操作同一个虚拟地址,但是其对应的物理地址不一定相同,比如进程A和进程B都访问adrs1地址,进程A的地址经过全局表和局部表转换后变为一个指向物理a1内存的地址,而进程B 的地址经过全局表和局部表转换后变为一个指向物理b1内存的地址,而且这个地址所在页并不在物理内存中,而是在交换文件中,于是系统就进行内存交换,将相应的页读入进行操作
文件偏移也比较好理解,文件开始的第一个字节偏移量为0之后每经过一个字节偏移量就加1
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
enthos:您说主程序M载入的基址 基本上位置不变。
能不能把这块详细的说一下,我就是不明白为什么程序每次运行的时候,主程序的基址都一样呢。
是不是这个基址就是指的主程序的入口点?
如果是,那么这个入口点是在编译的时候就确定的么?
。。。。。。。。。。。又回到我第二次的问题了。
希望能帮我解答一下。
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
爱已绑定:谢谢您的回复,不过,我想知道的是,为什么程序每次运行,所谓的基址都是不变化的呢
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
刚查资料:
主程序的入口点的地址,在编译的时候就是确定的。
执行程序代码之前,需要通过PE文件头来找到入口点的地址,然后执行代码指令
------------------------
过程中可能很复杂
--------
然后根据enthos的说明,就可以理解了,基址基本不变的原因。
谢谢上面各位的热心帮助。希望有人再补充,明天我会结贴!
|
能力值:
( LV3,RANK:20 )
|
-
-
9 楼
网游的基地址一般情况下是不变的,对于未加壳的exe程序,由于其无需重定位,其基地址你可以查看器pe结构中的ImageBase获得。对于dll,其在内存中的地址可能每次都不一样(重定位的原因),对于系统dll(kernel32.dll,user32.dll....)在同一个版本系统中加载地址是不变的,这与windows为了提高加载效率对其基地址分别设置了不同的值。
由于pe文件是由连接器生成的,故基地址通常还跟编译器有关,在windows下,exe的基地址通常为0x400000,对于dll,在6.0下的基地址和vs下的基地址都不一样……
对于编译后的二进制文件,其内部内存结构一般情况下是固定的,除非你loadlibrary,随机数等等……
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
连接器链接时把目标文件构建成pe格式文件,pe 格式中有代码段数据段的大小,偏移,以及载入内存后载入的位置,操作系统执行exe程序时解析pe格式,根据格式载入指定内存位置。所以最终还是由连接器决定,连接器链接程序时把段信息设置为默认值,当然所有段基址也自定义,比如ld就有脚本可以指定段的内存位置等等。
所以全局的变量和代码等都是固定位置的,像函数局部变量这些存储于堆栈,根据函数调用顺序的不同最终的地址也不同,还有动态分配的空间(new和malloc分配)和动态分配的资源,内存地址不一定每次都会相同。
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
我是这样理解的:
程序每次编译以后,长度是固定的,而里面的变量、函数需要定位地址(而不是使用我们编程时的变量名或者函数名),这个地址相对于此程序某个起始位置是相对一定的,你在程序中定义的常量(比如角色)的地址相对于这个起始地址也是一定的,那个这个常量的相对地址就可以理解为基址。
|
能力值:
( LV2,RANK:10 )
|
-
-
12 楼
都说了是编译的时候都已经确定了全局变量,全局类,函数等的地址,而且主程序每次加载的地址都是一样的,那怎么会变,偏移至少都是不会改变的,更新除外。
|
能力值:
( LV2,RANK:10 )
|
-
-
13 楼
已经结贴了,不过希望路过的能够继续补充自己的理解!
|
能力值:
( LV9,RANK:280 )
|
-
-
14 楼
编译链接的时候确定的;每次更新的时候,都会patch一下主程序;至于这个地址,不一定就是imagebase或者entrypoint,只要找到每次加载程序时的一个固定的不变的地址,通过偏移能找到其他的数据地址,就可以作为基址。这个很灵活的
|
|
|