8086的储存器编址
值得注意的是JOS是采用8086进行操作系统搭建的!
本来觉得一无是处的8086,现在觉得真要好好学学了,因为JOS,哈哈
在操作系统底层常常会遇到"逻辑地址"的概念,各种地址混淆在一起,极易头疼...
http://blog.csdn.net/cinmyheart/article/details/39843857
上面的Link是我对虚拟地址,线性地址,物理地址进行的分析.
----------------------------------------------------------------------------------------------------------------------------------
首先引出一个问题,很多人都知道,段寻址的方式是
segment:offset,比如0x0:0x7c2d
这是8086在实模式下的物理寻址方式.
问题: 你有没有想过,为什么是这样寻址? 根本的原因在哪儿?
这篇blog就试图回答这个问题.
8086有20根地址线,2^(20) == 1MB的储存器地址空间.这1MB的储存单元按照0x00000~0xFFFFF来编址.
8086有16根数据线,2^(16) == 64KB.
矛盾就凸显出来了,试问,能用寄存器直接对所有的地址空间进行寻址嘛? 明显不能, 数据线的宽度小于地址线的宽度!
所以,为了对所有1MB的储存器地址空间进行寻址,有人想出了,"一块块寻址"的办法 ---- 分段寻址机制.
想想,整个内存可以达到16个段(2^4).
在为程序分配内存空间的时候,一个程序可以有代码段CS,数据段DS,堆栈段SS和附加段ES
于是就有了段寻址, seg:offset. == (seg << 4) + offset.
这里seg和offset都可以用16位的寄存器存储,进而构造出了20bit的物理地址.
假设我们要对代码段内的某个指令进行寻址,我们可以
CS:IP
如果我们要对数据段内某个数据进行寻址,我们可以
DS:register 这里register可以是IP,甚至可以是BX
如果我们要对堆栈段进行寻址,我们可以
SS:SP 或SS:BP
等等.
接着还有个问题,为什么我们电脑关机之后再重新冷启动,按下启动电源键.
电脑每次都正确无误的启动,是不是按下电源键之后,电脑都进行了"某些相同的动作"?
当然, 每次按下电源键, CPU都会复位, 一切从新开始.
而对于8086来说,复位后,所有寄存器的值都是0,除了CS == 0xFFFF,即代码段(这都是硬件工程师故意设计好的)
接着,这是实模式,于是进行段寻址,
CS:IP == 0xFFFF0
寻址结果显示,复位之后,第一条CPU应该执行的指令在物理地址0xFFFF0处.
于是计算机就开始启动啦~ 每次都从0xFFFF0开始.
可以发现,开机后第一条指令,当前地址是0xFFFF0. 在此之前,CS == 0x0000
细心点会发现,第一条语句在段0xF000内, 此时,CS == 0xF000
CS = 0xFFFF IP = 0x0000的时候 CPU在自己初始化,
CPU初始化完成之后,系统马上进入实模式,CS变成 0xF000 IP=0xFFF0
我们利用JOS进行验证
The IBM PC starts executing at physical address 0x000ffff0, which is at the very top of the 64KB area reserved for the ROM BIOS.
The PC starts executing with CS = 0xf000 and IP = 0xfff0.
The first instruction to be executed is a jmp instruction, which jumps to the segmented address CS = 0xf000 and IP = 0xe05b .
update: 2014.12.21
补充一下,有意思的是根据CSAPP得知,core i7 的地址线长度和数据线长度分别是48bits,52bits
强调一下,以上讨论寻址,都是讨论的实模式下的寻址.
如有错漏,恳请指正交流 : )
update :2015.04.19
修正了之前关于系统启动时CS段的笔误
摄于南苑