有时您也许会想,为什么4 K的页面大小,而虚拟 Alloc函数所分配的内存却只有64 K (而非4 K)?
这要从 AlphaAXP处理器开始
在 AlphaAXP处理器中,所有的指令都不会与“装载32位凭证”相匹配,而是会装载两个16位整数,再将其组合为32位。
因此,如果存储器配置的颗粒不超过64 K,一个要重置的 DLL就必须在每次重置的位址上做两次调整:第一次为较高的16位元,第二次为较低的16位元。如果在两个一半的地址间,用进或借位来表示,那将会更糟糕。(举例来说,把4 K的资料从0x1234F000移动至0x12350000,就会强制改变较低的16比特和较高的15比特的地址。虽然移动的地址数量比64 K少得多,但是因为有进位的缘故,这个动作还是会对16- bit的地址有影响。)
除此之外,还有更糟糕的情况。
AlphaAXP处理器将把2个16比特信号的整数合并为一个32比特的整数。举例来说,想要加载0x1234ABCD,你必须先用 LDAH指令将0x1234加载到目标寄存器的高16位,之后再用 LDA指令,再加一个带符号的整数-0x5433 (因为,0x5433=0x10000–0 xABCD),这样你就可以得到你想要的结果0x1234ABCD。
所以,若因重新放置而造成位址在64 K区块的「下半区」与「上半区」间转移,就需要做其他校正,以保证位址上半区的演算法已被适当地调整。因为编译器有重新排列指令顺序的倾向,所以这个 LDAH指令很有可能是在很长的一段距离内,这样的话,重置记录的下半区就必须通过一些方法去寻找上半区的匹配。
另外,编译器会在同一64 K范围内的两个变量间共享 LDAH指令,这是非常智能的。如果重新分配的结果不是64 K,那么编译器就不能再进行这种最佳化了,因为重新分配后,这两个变量就不在一个64 K的内存中了。
将内存配置到64 K的大小可以解决上述问题。
如果你更仔细地看,就会明白为何在2 GB的边界处会出现64 K的“无人之地”。请看一个0x7FFFABCD的计算方式:因为16个比特中的16个比特位于64 K,所以这个数值只能用减法来计算,不能用加法。一种更普遍的方法是:
展开全文
以上方法不起作用
Alpha AXP是64位的处理器,所以0x8000并不适用于16位有符号的整数,所以只能用-0x8000 (负数)来表示。那么,事实是这样的:
你必须加上第三个命令才能清理出32比特。一种聪明的方法就是把0相加,然后让处理器把它当作一个32比特的整数,把它的正负号扩大到64比特。
如果一个位址被允许存取64 K的位址,那么在每个记忆体位址的计算中,上述的第三个 ADDL指示必须输入,以防这个位址被重新指派到靠近2 GB位址的“危险区域”。
要存取最后一个64 K的地址空间,成本很高:为了避免实际中从未出现过的情况,对所有的地址计算来说,性能损失了50%。所以,还是永久关闭这个区域比较好。
返回搜狐,查看更多