自从我开始使用8086汇编语言编程以来,我一直在思考这些段和段寄存器。我面临的问题是我无法看到我脑海中存在哪些片段的视觉图像,因此我不清楚这些概念。
问题1:
据我所知,在启用了20地址线的16位实模式下,我们可以将物理内存分成16段,每段64KiB。第一部分从0x00000
开始。下一段的起始地址是什么。是通过添加0x10000
(65536 = 64KiB)?
问题2:
这个问题在这里有点奇怪,但仍然是我唯一的选择。假设我的偏移地址为0x6000
,我如何找到它所属的段以便解决它。
谢谢
答案 0 :(得分:6)
...我们可以将物理内存分成16段,每段64KiB。
是的,但更准确的是将其称为“16 非重叠段”,因为还可以将内存划分为65536个重叠段。
当启用A20线路时,我们可以使用超过1MB的线路。 (1048576 + 65536-16)当将相关段寄存器设置为0xFFFF时,我们可以访问0x0FFFF0和0x10FFEF之间的存储器。
两种细分的主要特征是:
重叠片段
内存中相隔16个字节。
有时您会看到人们将16字节的内存块称为段,但显然这是错误的。然而,对于如此大量的记忆,有一个广泛使用的名称:“段落”。
假设我的偏移地址为0x6000,我怎样才能找到它所属的段以便解决它。
这里的问题还在于措辞!
如果通过“偏移地址0x6000”表示偏移量,就像我们通常在实际地址模式编程中使用的那样,那么问题就无法回答,因为在每个存在的段中存在这样的偏移量0x6000 < / STRONG>!
另一方面,如果“偏移地址为0x6000”的措辞实际上是指线性地址 0x6000,那么段寄存器有很多解决方案:
segment:offset
--------------
0000:6000
0001:5FF0
0002:5FE0
0003:5FD0
...
05FD:0030
05FE:0020
05FF:0010
0600:0000
正如您所看到的,可能有0x0601段寄存器设置到达线性地址0x6000 以上适用于确实启用A20线路的情况。如果A20处于非活动状态,则可以精确地以0x1000(4096)方式达到线性地址0x6000(就像0到1MB-1之间的任何其他线性地址一样):
segment:offset
--------------
F601:FFF0
F602:FFE0
F603:FFD0
...
FFFD:6030
FFFE:6020
FFFF:6010
0000:6000
0001:5FF0
0002:5FE0
0003:5FD0
...
05FD:0030
05FE:0020
05FF:0010
0600:0000
答案 1 :(得分:5)
在这个答案中,我只是给出了真实模式的解释。在保护模式下,分割有点复杂,因为你可能永远不会编写分段保护模式程序,我不打算解释这个。
实际上细分非常简单。 8086 CPU有四个段寄存器,名为cs
,ds
,es
和ss
。当您访问内存时,CPU会像这样计算物理地址:
physical_address = segment * 16 + effective_address
其中effective_address
是内存操作数指示的地址,segment
是该内存访问的段寄存器的内容。默认情况下,当CPU取代码时使用cs
,ss
用于堆栈推送和弹出以及使用bp
作为基址寄存器的内存操作数,es
为用于某些特殊说明,ds
用于其他任何地方。可以使用段前缀覆盖段寄存器。
这在实践中意味着什么? 8086有16位寄存器,因此使用寄存器存储地址允许我们寻址高达65536字节的RAM。使用段寄存器的想法是我们可以在段中存储地址的附加位,允许程序员寻址超过2 20 = 1048576 bytes = 1内存的MiB。该RAM被分成65536个重叠段,每段65536字节,其中每个段是一个可以加载到段寄存器中的值。
这些段中的每一个都从一个16的倍数开始,如上面的地址计算逻辑所示。您可以使用16个非重叠片段(如您在问题中所述)标注整个1 MiB物理地址空间值0x0000
,0x1000
,...,0xf000
但您可以使用您喜欢的任何细分选择器。
答案 2 :(得分:2)
通常,段是使用内部索引系统的内存间隔。
如果您将内存视为一长串字节mem[0x100000]
,您可以指定连续切片seg=mem[a:a+b]
,其中len(seg)=b
其中
seg[0]
存储在mem[a]
seg[1]
存储在mem[a+1]
seg[b-1]
存储在mem[a+b-1]
。使用分段的优点是,分段内的地址(seg的索引)可以更短,例如,在8086的情况下,可寻址存储器上升到物理地址(mem的索引)2 20 -1,(在后继上你甚至可以更进一步,在段中有16位地址) 。 将程序放在内存中的任何位置都相当简单,因为您只需要分配一个或几个空闲段,并且大多数地址在专用段内运行而无需调整它们。
在8086上,所有段都是2 16 字节长,因此段内地址适合16位,这使得它们易于处理。对于起始地址,您可以选择物理内存中可以除以16且等于或低于0xFFFF0
的任何地址。这意味着任何物理地址都位于多个段中。这些段由16位数字描述,它是起始地址除以16。
因此,细分0xBADA
对应于从0xBADA0
开始的细分。