为什么64位进程不能调用32位dll

来源:互联网 发布:键盘输入监测软件 编辑:程序博客网 时间:2024/04/30 14:02
我想把它标为原创, 因为这不是一篇合格的翻译; 我最终把它标为翻译, 因为这更不是一篇合格的原创。

在此之前, 告诉你一个秘密:16位代码是可以调入32位代码的, 注意, 是可以。聪明的同学知道这个秘密后会问既然这样子为什么32b代码不能调入64b代码呢?更聪明的同学会做出如下解释(抠鼻, 我只是个翻译, 哈哈):

地址空间, 16位系统和32位系统都住在一个线性空间地址, 16和32俩个数字是什么意思呢? 对你我就真是个数字, 对于选择器来说它代表相对偏移量。 那么问题来了, 选择器又是什么?(我喜欢爱问为什么的同学, 打住, 我只喜欢爱问为什么的女同学, 暴露性取向了, 狂吐)。 在16位系统中, 地址是被选择器和偏移量按某种格式被指定, 举个栗子:一个的地址0x0123:0x4567, 意思是相对选择器0x0123偏移0x4567字节, 每个选择器在一个描述符表有一个相对入口表达了它是哪种类型的选择器(它可用于读数据? 写数据? 执行代码?), 但是对于现在这个问题我们更关心它所包含的另外俩个信息:基地址和限制。再举个栗子:0x0123入口对于选择器可能想说, 0x0123是一个只读数据选择器, 它起始于线性地址0x00524200(不要问我这个数字是哪来的, 我只是个翻译, 作为一个优秀的翻译不会表达自己的意见, 但我不是, 随手拿来的一个数字呗)和一个0x7fff的限制。这意味着0x0123:n指向线性地址0x00524200+n, 其中n<=0x7fff。

随着80386引入, 一个选择器的最高限制从0xffff提高到0xffffffff。 聪明的你会不会创造一个选择器呢, 设置起始地址为0x00000000和0xffffffff的限制, 使用这个选择器我们可以访问整个32位线性地址空间, 我们不在需要把它切分为64KB块的16位的日子里, 我们声明所有的地址都是这种格式, 也不需要纠结用哪个限制的选择器, 因为它隐含了可访问所有位置。

你造吗, 你发明了32位寻址方案! 当然并不是说没有了选择器, 只是变成了唯一。
现在是时候看看这种trunk模式带来的后果。

首先, 你有没有注意到16位全指针需要一个16位段地址(基地址)和一个16位偏移量, 共32位, 而32位指针需要一个32位大小的值; 所以0x0123:0x4567 可以表示一个16位全指针, 亦可表达一个32位指针, 我们压根不需要改变它们结构, 它们就如此相像, 是不是一个很神奇的发现。

接下来, 注意到16位地址空间完全有能力指向32位的每个地址, 因为俩个系统底层有相同的线性地址空间; 区别仅仅是16位的一次只能看到64KB, 需要多次看完所有, 而32位的一目十行, 虽然聪明的32位这么牛逼, 但勤奋的16位分多次也可以达到相同效果, 好像说的真的勤能补拙一样。  只是16位需要一个本本(临时地址)计算并记录。

说了这么多貌似跑题了, 因为上面说的这些不适用与32位到64位, 首先指针大小变了, 意味着32位和64位转换会改变结构, 而64位的地址访问能力为32位的40亿倍。 如果内存中存在64位偏移:0x0000 06fb 0123 4567, 32位根本没法访问。 不要问我为什么, 因为他们没有一个本本(临时地址)来计算并记录, 32为放弃了选择器, 你造吗?

俩个人用不同的词描述同一事物时, 如果一方甚至没有谈论那事物的能力, 作为一个翻译耸耸肩双手一摊未尝不可。

http://blogs.msdn.com/b/oldnewthing/archive/2008/10/20/9006720.aspx


ps:后续会补充64位进程调用32位dll的解决方案
0 2
原创粉丝点击