对8086中的段的理解

来源:互联网 发布:raptor编程1到100之和 编辑:程序博客网 时间:2024/06/10 19:21

8086结构

8086内部结构

在8086CPU中,主要由总线接口部件(BIU)执行部件(EU)组成。总线接口部件(BIU)负责与存储器、外部设备之间进行信息交换;执行部件(EU)负责指令的执行。

我们知道,8086是16位的CPU,内部的寄存器之间,寄存器和运算器之间的数据交换一次最多只能传输16位,而8086的外部地址总线却有20位,也就是说,8086可以寻找的内存单元范围是0-0xFFFFF

如果CPU要访问地址为0x123C8的内存单元该怎么办?很明显,8086里面一次性只能存放16位的地址,并不能存放20位的地址,因此8086一次只能向外输出16位的地址,并不能直接访问地址为20位的内存单元。

有一个常识大家都知道,对于随意给出的一个十进制数,我们都可以通过采用不同的数进行各种数学运算,然后结果正好等于给定的十进制数。比如1000,可以通过500 + 500、666 + 334、1200 - 200、100*10 + 0等不同的方式得出。既然十进制可以这样,那么给定一个十六进制的数,自然也能通过不同的十六进制数进行算术运算组合。

于是,对于8086不能直接访问20位地址的问题,8086的设计者们也许就想到了这个方法,通过将20位地址进行拆分组合,事实上他们也是这样做的,他们给出的解决方案是:在CPU内部,通过两个16位的寄存器分别存放用于组合成20位地址的两个数,其中一个当做基础地址,另一个当做偏移地址,具体的组合方式是基础地址 + 偏移地址 = 内存单元的实际物理地址,其中基础地址 = 段地址*16

也就是说8086中,用一个寄存器存放段地址,用另一个寄存器存放偏移地址,然后需要访问由这两个寄存器所组合而成地址的内存单元的时候,CPU会把这两个寄存器中的内容送入内部的一个叫做地址加法器的运算部件中,由它将两个16位的寄存器所表示的两个数组合成一个20位数的地址,并输送到总线控制单元,最后通过BIU送入外部20位的地址总线,从而存取内存单元的内容。

地址加法器

至于加法运算器是怎么将两个16位的寄存器进行操作,从而得到一个20位的地址,具体的物理实现我们不去管它(有知道的同学可以谈谈),只要记住,地址加法器通过将用于存放段地址的那个寄存器进行左移4位,右边多出的4位补0(相当于16进制数扩大16倍),然后和用于存放偏移地址的寄存器中的数进行相加,即可得到一个20位的地址。

上面忘了说了,用于存放段地址的寄存器有个专门的名称,叫做段寄存器,8086中提供了4个段寄存器:CSDSESSS(后面有描述)。

另外,通过基础地址 = 段地址*16我们可以发现,可以用作基础地址的内存单元的编号一定是16的倍数,由于20位地址可以有1M的内存空间,1024*1024/16=65536,也就是说可以有65536个地址可以用来做基础地址;再看看偏移地址,由于寄存器只有16位,因此偏移地址最多可以打到FFFF,也就是一个段最多可以有64KB的大小。通过上面的十进制组合例子我们可以举一反三,对于20位的地址,我们也可以通过不同的段地址和偏移地址进行组合,也就是说一个20位的物理地址,可以有多种基础地址 + 偏移地址的组合,前提是只要基础地址是16的倍数就行。

一开始的时候,对这个段地址中的段不太明白,通过各种资料查阅,下面说说自己对的理解:,不是内存单元的属性,内存单元只是内存单元,像一个有限的线性盒子排列在一起,每个盒子都有唯一的一个编号,这个编号在计算机中被称作地址;由于8086CPU自身结构设计的问题,不能通过内部一次性的给出20位的内存单元地址,因而他们想了一个办法,为了解决这个问题,他们用CPU内部的两个寄存器通过地址加法部件组合成一个20位的物理地址,然后通过BIU进行控制,最终可以存取内存单元的内容。是CPU内部将一个实实在在的物理内存地址通过拆解,用不同的段地址*16 + 偏移地址的方式进行表示,从而获取指定内存单元的内容。所以可以说,段其实是8086CPU用于对内存管理的一种方法,内存表示一脸懵逼,完全不知道CPU是怎么得到它的地址,也不必要知道CPU是如何得到,内存所要关心的是我要给CPU什么,从CPU那得到什么,至于你CPU是通过GPS导航到我家的还是通过其它什么方法知道我家的,一概与我无关。

最后说一个比较有趣的问题,在8086CPU加电启动后(即CPU刚开始工作),CSIP被设置为CS = 0xFFFFIP = 0x0000,即在8086PC机刚启动时,CPU从内存0xFFFF0单元中读取指令执行,0xFFFF0单元中的指令是8086PC机开机后执行的第一条指令。

SI DI BP SP IP CS DS ES SS

DS is called data segment register. It points to the segment of the data used by the running program. You can point this to anywhere you want as long as it contains the desired data. ES is called extra segment register. It is usually used with DI and doing pointers things. The couple DS:SI and ES:DI are commonly used to do string operations. SS is called stack segment register. It points to stack segment.

The register SI and DI are called index registers. These registers are usually used to process arrays or strings. SI is called source index and DI is destination index. As the name follows, SI is always pointed to the source array and DI is always pointed to the destination. This is usually used to move a block of data, such as records (or structures) and arrays. These register is commonly coupled with DS and ES.

The register BP, SP, and IP are called pointer registers. BP is base pointer, SP is stack pointer, and IP is instruction pointer. Usually BP is used for preserving space to use local variables. SP is used to point the current stack. Although SP can be modified easily, you must be cautious. It’s because doing the wrong thing with this register could cause your program in ruin. IP denotes the current pointer of the running program. It is always coupled with CS and it is NOT modifiable. So, the couple of CS:IP is a pointer pointing to the current instruction of running program. You can NOT access CS nor IP directly.


参考

《汇编语言》(第3版 王爽)

(完)

原创粉丝点击