【发布时间】:2016-04-06 05:12:55
【问题描述】:
在汇编语言中,为什么保存在段寄存器中的任何值都要乘以 10?我试图在很多书中找到答案,但我没有。
【问题讨论】:
-
你说的是实模式编程吗?它们没有乘以 10。它们被左移 8 位,因为它们最初是支持 24 位寻址的 16 位架构。
标签: assembly
在汇编语言中,为什么保存在段寄存器中的任何值都要乘以 10?我试图在很多书中找到答案,但我没有。
【问题讨论】:
标签: assembly
首先,汇编不是单一的语言,实现也不是单一的东西。您必须说出您正在谈论的架构,以便任何人给出正确的答案。
其次,段寄存器并不总是乘以 10。我什至会说它们永远不会乘以 10,因为 10 不是二进制系统的自然数。
如果您问为什么,例如,在 x86 架构中,为了获得物理地址,CPU 将段寄存器乘以 0x10(十进制 16)并添加偏移量,答案是:因为设计者选择了。
接下来你会问他们为什么选择这个。一个 16 位的段寄存器可以保存从 0 到 65535 的值。将其乘以 16 可以得到从 0 到 1048575 的地址,即 1MB。 1MB 是一个很好的内存访问量。
其他架构可能有不同的乘数,甚至是非常数的。但它们很可能总是 2 的幂。
【讨论】:
为了理解这个设计决策,我们需要回到 1974 年。
那时我们还没有现在的小型化,一个封装中可以制造的引脚数量非常少。
1974 年是英特尔刚刚推出 8080 的年份,这是一款具有 16 位地址总线的芯片,这意味着最多可寻址 64 KiB 的内存。
然而 8080 主要有 8 位寄存器,因此程序员通常需要将两个寄存器配对以形成 16 位地址。
与此同时,1976 年开始设计新芯片 8086。
设计人员意识到 64 KiB 的内存太少,因此他们决定增加专用于内存寻址的引脚数,但芯片封装的引脚数仍然存在很大限制。
对于这个新芯片,他们选择了 20 位地址,或 1 MiB 的可寻址内存。
在考虑为什么 20 位会进入因果循环时,我们需要考虑两个重要因素:
16 位是不够的,所以他们需要更多位,最简单的解决方案是使用 32 位,将两个寄存器配对。
但是 32 位太多了!
下一个显而易见的选择是 24、16 + 8,因为它是 8 的倍数(一个字节)。
但是 24 位还是太多了。
根据Intel 8008 to 8086 by Stephen P. Morse et a, Pag. 17,他们考虑了这个假设但被拒绝了。
如果它们的大小不能是 8 的倍数,它们至少可以是 4 的倍数(一个半字节)。
所以他们选择了 20 位。
现在出现了一个问题:如何用 16 位数字生成 20 位数字? 英特尔设计人员选择了众所周知的分段机制:将其中一个数字(段)左移 4(乘以 16 或 10h),然后再将两者相加。
更直接的方法是直接从段寄存器的低半字节获取地址的额外 4 位。
他们可能出于各种原因拒绝了这一点,例如:a) 它浪费了段的 12 位 b) 也许它不能重用任何 ALU 组件 c ) 它不允许地址别名。
以某种方式做出了选择,因此每个与 x86 兼容的 CPU 都需要实现这种分段模型,这是历史遗留问题。
此模型自 80286 以来已得到扩展,实际上已在 x64 处理器中弃用。
【讨论】: