第一章

                        第一节 X86 CPU寻址方式
    x86系列是指Itel从16位微处理器8086开始的整个CPU芯片系列,系列中的每种类型都与以前的各种型号保持兼容,主要有8086、8088、80186、80286、80386、80486以及以后各种型号的Pentium芯片。在X86系列中,8086和8088是16位处理器,而从80386开始为32位处理器,802086作为中间的一个个过度产品。
    人们所说的cup是16位或32位,指的是处理器的“逻辑运算单元”(ALU)的宽度。8086的CPU为16位的,内存地址空间为1M,那么地址总线的宽度也就确定了为20位,为了能让16位的CPU能够达到20位的寻址空间,Itel在8086CPU中设置了4个段寄存器:CS、DS、SS和ES,分贝用于可执行代码(即指令)、数据、堆栈和其它。每个段寄存器为16位,物理地址与逻辑地址转换关系为:
                物理地址=段寄存器*10H+逻辑地址
    对于每一个由段寄存器的内容确定的“基地址”,一个进程总是能够访问从此开始的64K字节的连续地址空间,而无法加以限制。而且,用来改变段寄存器内容的指令也不是什么“特权指令”,因此,一个进程可以通过改变段寄存器的内容来访问内存中的任何一个单元。不能对一个进程的内存访问加以限制或者说保护,就谈不上内存管理,也就谈不上现代意义的中央处理器。由于8086缺乏对内存访问的保护的,所欲为了区别后来出现的“保护模式”,就成为“实地址模式”。显然,实地址模式是无法建立起真正意义上的操作系统的。
    32位的80386以及以后的80486、Pentium、Pentium2统称为i386结构。32位的i386的ALU宽度达到了32位,地址总线也达到了32位,寻址空间为4G,但是为了兼容之前的产品,80836必须要维持哪些段寄存器,还必须支持实地址模式,最终采用的方案是有添加了两个寄存器FS和GS。
    为了实现保护机制,光是用段寄存器确定基地址是不够的,还需要一个数据结构,用来保存地址段的长度和一些其他信息,比如访问权限。基本设计思路是:在保护模式下,改变段寄存器的功能,使其从一个单纯的基地址变成一个这样一个数据结构的指针。这样,当一条访问内存的指令发出一个内存地址时,CPU就可以这样来归纳出实际上应该放到数据总线上的地址:
    (1)根据指令的性质来确定使用哪一个寄存器,例如转移指令使用CS,取数指令中使用DS,这与实地址模式相同
    (2)根据确定的段寄存器的bit3~bit15和全局或局部段描述指针,找到相应的“地址段描述结构”
    地址段描述结构地址:
                GDTR/LGTR(基地址)+段寄存器前13位 
    (3)从地址段描述结构中的到基地址,基地址存在于此
    (4)将指令中发出的地址作为位移,语段描述结构中规定的段长度相比,看是否越界
    (5)根据指令的性质和段描述符中的权限来确定是否越权
    (6)将指令中发出的地址作为位移,与基地址相加而得出实际的“物理地址”

    ![段寄存器功能](https://img-blog.csdn.net/20160814175718477)

    全局描述符表GDTR:在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个),寄存器GDTR用来存放GDT的入口地址(基址)和表长的界限

    基地址指向GDT的表头,长度表明GDT表的字节长度值。指令LGDT和SGDT分别用于加载和保存GDTR寄存器的内容。在机器刚加电或处理器复位后,基地址被默认地设置为0,而长度值被设置成0xFFFF。在保护模式初始化过程中必须给GDTR加载一个新值。
    ![这里写图片描述](https://img-blog.csdn.net/20160814180851739)
    段寄存器:16位,前13位为全局或局部描述符索引,T1 = 0代表使用GDTR作为基地址,T1 = 1代表使用LDTR作为基地址,两位的RPL代表特权级,共四级。
    特权级的说明:任务中的每一个段都有一个特定的级别。每当一个程序试图访问某一个段时,就将该程序所拥有的特权级与要访问的特权级进行比较,以决定能否访问该段。系统约定,CPU只能访问同一特权级或级别较低特权级的段。
    例如给出逻辑地址:21h:12345678h转换为线性地址
    a.段寄存器中的21h为0000 0000 0001 0010,意思是:GDT表中的第四个描述符,T1 = 0表示在GDT表中选择
    b.若此时GDT第四个描述符中描述的段基址(Base)为11111111h,则线性地址=11111111h+12345678h=23456789h
    局部描述符表LDTR:LDTR有若干张,内个任务都可以有一张。LDTR为16位,其功能与段寄存器相同,前13位为描述符索引,
                        第二节 i386页式内存管理机制
    段式内存管理机制灵活性和效率都比较差,因此产生了页式内存管理机制,i386的页式内存管理机制是在段式内存管理机制的基础上产生的,以前段式管理内存的物理地址成为了页式内存管理的线性地址,线性地址格式如下:
    ![这里写图片描述](https://img-blog.csdn.net/20160814182140480)
    新添加的寄存器:
        CR3:指向页面和目录的基地址
                        第三节 linux内核源码中的C语言
    linux内核主体是使用GNU的C语言编写的,GNU的C语言在普通的C语言的基础上进行了扩充,GNU为此提供了编译工具gcc。GNU的C和C++是合为一体的,gcc既是C编译又是C++编译。
    inline的作用类似于宏,inline不是C语言的关键字,是C++的关键字,为了防止C文件中的inline变量与C++中的inline关键字冲突,gcc有以下规则
                __inline__等价于inline
                __asm__等价于asm
    为了支持64位CPU结构,gcc增加了新的基本数据类型 long long int,该类型常在内核代码中使用。gcc还支持一个保留关键字“attribute”,用作属性描述,例如:
struct foo {
    char a;
    int x[z]    attribute__((packed));
}
    这里属性描述“packed”表示字符a与整形数组x之间不应该为了与32位长整型边界对齐而留下空洞。这样,“packed”就不会与变量名冲突了。
    linux内核的各种版本有着对gcc版本的依赖。
    inline函数并不能消除对宏操作的使用。复杂宏定义解释:   
#define DUMP_WRITE(addr,nr) do { memcpy(bufp,addr,nr); bufp += nr; } while(0)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值