【问题标题】:Why "segment register's value must first be multiplied by 16"?为什么“段寄存器的值必须先乘以 16”?
【发布时间】:2017-03-07 01:01:00
【问题描述】:

最近看了一本书,里面提到“段寄存器的值必须先乘以16”。

例如MOV AL, [ES:BX]表示将ES*16+BX的内容移动到寄存器AL。而且我在网上搜索了一些文章,也提到了这样的事情:

  1. https://www.quora.com/What-is-the-use-of-the-stack-segment-and-the-extra-segment-in-8086#
  2. Physical address calculation assembly IAPX8088

我只是想知道为什么 16 在这里? 16 是什么意思?

更新:

  1. 我的意思是,如果我想访问地址 16,MOV BX, 16MOV ES, 1 都一样吗?这对我来说很奇怪。我以为ES是最左边的位,如果ES是1,那么地址就是ES*65536+BX...

【问题讨论】:

  • 为什么是 16?因为这就是芯片的设计方式。
  • 所以这只是一个公式,我不需要,为什么?只记得没关系吗?
  • 20 位地址总线是设计目标。封装无疑起了很大的作用,他们不敢制造超过 40 个引脚的芯片。一兆字节在当时是巨大,它确实持续了超过 15 年。
  • @HansPassant:不清楚为什么他们没有使段移位 8 (ES*256 + BX),但仍然只构建了具有 20 位物理寻址的芯片。这意味着在 CPU 的初始模型中,段寄存器的前 4 位将被忽略(或必须全为零),但会给它增加 16 倍的空间。是否能够将段与此类重叠细粒度控制真的有用吗?还是不想设计一个逻辑地址空间大于物理支持的芯片?
  • 重叠对于处理超过 64KB 的数据(“巨大”指针)很有用。乘数越小,在段大小粒度上浪费的地址空间就越少,使用大指针可以寻址的内存就越多。因此,它与获得 1 MB 地址空间所需的大小一样大。

标签: assembly


【解决方案1】:

在分段内存和 16 位地址空间的时代,它允许您寻址整个 1 MB 内存,这是原始 8086 支持的(它有一个 20 位外部地址总线),仍然保持两者“接近" 16 位宽的指针和段寄存器。

 ssssssssssssssss0000 +    segment (16 bit) * 16 (= left shift 4)
 0000pppppppppppppppp =    near pointer (16 bit)
------------------------
xaaaaaaaaaaaaaaaaaaaa      physical address (20 bit + something)

(实际上你可以在 1 MB 之外增加近 64 KB,这最初会导致环绕,然后导致整个 A20 问题)

【讨论】:

  • 能够通过这种细粒度的控制来重叠片段真的有帮助吗?还是不想设计一个逻辑地址空间大于物理支持的芯片? 8 的细分市场转移似乎很自然,并为未来的扩展留出了 16 倍的空间。 (段寄存器的高 4 位在只有 20 位物理地址的 CPU 上会被忽略,或者要求全为零,但这没关系。)
  • @PeterCordes:对不起,我真的没有答案——但这是一个有趣的问题,我很高兴看到答案。当我最初回答时,在我看来,这个问题更多的是关于“乘以 16 的目的是什么”而不是“为什么恰好 16”。 (实际上,我正在考虑删除这个答案,因为我不知道对这个确切的决定给出准确的答案)
  • 这是对 OP 问题的基本部分的一个很好的回答,其中包括 16 是什么意思?,也许“首先分割的意义是什么? ”。扩展此答案的一个好方法是解决 RaymondChen 在 cmets 中指出的问题:如果您不需要为每个段单独使用 64k,但又不想只使用所有的 Tiny 代码模型,则重叠段很有用他们有相同的基础。 (这回答了“为什么不是 65536”部分)
  • @PeterCordes 我认为 8 的转变可能会奏效,特别是因为小于 64K 的段可能会与前一个段重叠,而不会浪费空间填充最多 256 字节的边界。但我认为这归结为英特尔工程师以相反的方式思考它。他们决定使用 16 位段寄存器和 20 条地址线,因为 20 - 16 = 4,所以段移位应该是这样。如果他们觉得他们只能在其中塞入 19 个地址行,那么班次可能会是 3 个。
【解决方案2】:

获取内存地址的过程是:
基本内存寄存器*16 + 相对内存寄存器。

示例:
[ds:si]
假设 DS 存储值 700h 而 SI 存储值 7h,则指令将充当:
[700h:7h]
这将取消引用 7007h (700h*16+7h = 7007h) 的内存。

因此 [700h:7h] 与 [7007h] 相同。

为什么是 16?,十六进制数乘以 16 将等于将数字向左推所以:
700h*16=7000h

【讨论】:

  • 你什么? 700h:7h 为 700h*10h+7h(或 700h
  • 你的答案仍然是错误的,即使在编辑之后! 7010h (700h*16h+7h = 7010h)。
  • @Fifoernik 'h' 后缀表示值是十六进制值,也就是说 16h 表示十进制的 22,因此 700h*16h+7h != 7010h 。这就是你错的原因。
  • 什么?粗体字正是 YOU 所写的答案。请放心,我知道我的十六进制。不要试图对我聪明!
  • @Fifoernik [link] (stackoverflow.com/questions/3030959/what-does-the-h-suffix-mean) 我不是想“对你聪明”,你声称我错了,但争论没有意义,因为 16 小时是22 以十进制表示。
猜你喜欢
  • 1970-01-01
  • 2012-01-18
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
  • 2014-10-31
  • 2021-01-16
  • 2017-10-29
  • 1970-01-01
相关资源
最近更新 更多