【问题标题】:Why is any value saved in a segment register multiplied by 10?为什么段寄存器中保存的任何值都要乘以 10?
【发布时间】:2016-04-06 05:12:55
【问题描述】:

在汇编语言中,为什么保存在段寄存器中的任何值都要乘以 10?我试图在很多书中找到答案,但我没有。

【问题讨论】:

  • 你说的是实模式编程吗?它们没有乘以 10。它们被左移 8 位,因为它们最初是支持 24 位寻址的 16 位架构。

标签: assembly


【解决方案1】:

首先,汇编不是单一的语言,实现也不是单一的东西。您必须说出您正在谈论的架构,以便任何人给出正确的答案。

其次,段寄存器并不总是乘以 10。我什至会说它们永远不会乘以 10,因为 10 不是二进制系统的自然数。

如果您问为什么,例如,在 x86 架构中,为了获得物理地址,CPU 将段寄存器乘以 0x10(十进制 16)并添加偏移量,答案是:因为设计者选择了。

接下来你会问他们为什么选择这个。一个 16 位的段寄存器可以保存从 0 到 65535 的值。将其乘以 16 可以得到从 0 到 1048575 的地址,即 1MB。 1MB 是一个很好的内存访问量。

其他架构可能有不同的乘数,甚至是非常数的。但它们很可能总是 2 的幂。

【讨论】:

    【解决方案2】:

    为了理解这个设计决策,我们需要回到 1974 年。
    那时我们还没有现在的小型化,一个封装中可以制造的引脚数量非常少。

    1974 年是英特尔刚刚推出 8080 的年份,这是一款具有 16 位地址总线的芯片,这意味着最多可寻址 64 KiB 的内存。
    然而 8080 主要有 8 位寄存器,因此程序员通常需要将两个寄存器配对以形成 16 位地址。

    与此同时,1976 年开始设计新芯片 8086。
    设计人员意识到 64 KiB 的内存太少,因此他们决定增加专用于内存寻址的引脚数,但芯片封装的引脚数仍然存在很大限制。
    对于这个新芯片,他们选择了 20 位地址,或 1 MiB 的可寻址内存。
    在考虑为什么 20 位会进入因果循环时,我们需要考虑两个重要因素:

    1. 引脚数。它必须尽可能低。
    2. 寄存器的大小。如何用 16 位数字组成 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 处理器中弃用。

    【讨论】:

      猜你喜欢
      • 2017-03-07
      • 1970-01-01
      • 2017-05-03
      • 2014-10-31
      • 2020-08-25
      • 2023-03-23
      • 2017-10-29
      • 2021-08-09
      • 1970-01-01
      相关资源
      最近更新 更多