Orange’s学习笔记(二)

原创 2016年10月13日 09:18:39

保护模式
1、为什么GDT(全局描述符表)中第一个描述符为空
答:全局描述符表实际上是为80386以上的32位cpu在保护模式下提供段式寻址机制的一个索引表,这个表的每一个表项(8个字节)描述了一段地址的起始地址、界限以及属性,原来的实模式下的段寄存器存储的值不在是地址的一部分,而其中的高13位表示的是GDT中表项的索引,低3位分别表示TI(1位)和RPL(2位)。GDT的第一个(索引为0)描述符很特殊,8个字节的值全为0,网上查阅资料基本上有三种说法,说法一:GDT的第一个描述符代表NULL的意思,是针对那些没有LDT的任务或用户进程的程序;说法二:代表GDT的起始地址;说法三:CPU规定(ps:处理器规定,GDT中的第一个描述符必须是空描述符。这是什么原因呢?因为很多时候,寄存器和内存单元的初始值都会为0,再加上程序设计有问题,就会在无意中用全0的索引来选择描述符,这当然是不好的。因此,处理器要求将第一个描述符定义成空描述符;而且在进行特权级变换的长返回时,CPU进行的最后一步工作是:检查ds、es、fs、gs的值,如果其中哪一个寄存器指向的段的DPL小于CPL(此规则不适用于一致代码段),那么一个空描述符会被加载到该寄存器)。
我注释掉了GDT中的第一个描述符就不可以运行了,代码如下:

%include "pm.inc"
org 07c00h
    jmp LABEL_BEGIN

[SECTION .gdt]
G_DESC_BEGIN:
;G_DESC:        Descriptor  0,  0,  0                   
G_DESC_CODE32:  Descriptor  0,  SegCode32Len-1, DA_C|DA_32      ;非一致32位代码段
G_DESC_VIDEO:   Descriptor  0B8000h,    0ffffh, DA_DRW          ;显存段

GdtLen  equ $-G_DESC_BEGIN
GdtPtr  dw  GdtLen-1
        dd  0

SelectorCode32  equ G_DESC_CODE32-G_DESC_BEGIN
SelectorVideo   equ G_DESC_VIDEO-G_DESC_BEGIN

[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
    mov ax,cs
    mov ds,ax

    ;初始化32位代码段描述符
    xor eax,eax
    mov ax,cs
    shl eax,4
    add eax,LABEL_SEG_CODE32
    mov word [G_DESC_CODE32+2],ax
    shr eax,16
    mov byte [G_DESC_CODE32+4],al
    mov byte [G_DESC_CODE32+7],ah

    ;为加载GDTR做准备
    xor eax,eax
    mov ax,ds
    shl eax,4
    add eax,G_DESC_BEGIN
    mov dword [GdtPtr+2],eax

    lgdt [GdtPtr]

    cli

    in al,92h
    or al,00000010
    out 92,al

    mov eax,cr0
    or eax,1
    mov cr0,eax

    jmp dword SelectorCode32:0

[SECTION .s32]
[BITS 32]
LABEL_SEG_CODE32:
    mov ax,SelectorVideo
    mov gs,ax
    mov ah,0Ch
    mov al,'G'
    mov [gs:((80*18+0)*2)],ax
    mov al,'D'
    mov [gs:((80*18+1)*2)],ax
    mov al,'T'
    mov [gs:((80*18+2)*2)],ax
    jmp $

SegCode32Len    equ $-LABEL_SEG_CODE32

2、G_DESC_NORMAL描述符的作用
从保护模式跳转回实模式,在准备结束保护模式回到实模式之前,需要加载一个合适的描述符选择子到有关的段寄存器,以使对应段描述符高速缓冲寄存器 (见后面的解释)中含有合适的段界限和属性(这里正确的段界限显然是64K,即0ffffh,属性应该是DA_DRW,即90h可读写数据段),而且,不能从32位代码段返回实模式,只能从16位代码段中返回。这是因为无法实现从32位代码段返回时cs高速缓冲寄存器中的属性符合实模式的要求(实模式不能改变段属性)。(高速缓冲寄存器: 在实模式下,段寄存器含有段值,为访问存储器形成物理地址时,处理器引用相应的某个段寄存器并将其值乘以16,形成20位的段基地址。在保护模式下,段寄存器含有段选择子,如上所述,为了访问存储器形成线性地址时,处理器要使用选择子所指定的描述符中的基地址等信息。为了避免在每次存储器访问时,都要访问描述符表而获得对应的段描述符,从80286开始每个段寄存器都配有一个高速缓冲寄存器,称之为段描述符高速缓冲寄存器 或描述符投影寄存器,对程序员而言它是不可见的。每当把一个选择子装入到某个段寄存器时,处理器自动从描述符表中取出相应的描述符,把描述符中的信息保存到对应的高速缓冲寄存器中。此后对该段访问时,处理器都使用对应高速缓冲寄存器中的描述符信息,而不用再从描述符表中取描述符。)
新增的Normal描述符,段界限64K,属性DA_DRW,在返回实模式之前把对应选择子SelectorNormal加载到ds、es和ss正好合适。

3、A20地址线
8086有20位地址总线寻址空间为1M,在理论上段:偏移的寻址模式在实模式下最大地址为FFFF:FFFF=10FFEF,这显然超过了20位地址总线所能表示的最大地址值(FFFFF),而试图访问超过1M以上地址的空间并不会造成错误,而是会回卷,即10FFEF只会表示0FFEF(10FFEF%100000)的物理地址值。但是到了80286(24位地址总线)以上,真的可以访问到1M以上的地址空间了,这样的寻址方式会造成向上不兼容,所以IBM提出了一个方案,通过8042键盘控制器控制索引为20(从0开始)的地址位,在实模式下,关闭A20地址线,这时如果cpu有超过20位的地址线,则A20始终为0,所以FFFF:FFFF还是表示0FFEF的地址值,这样8086、80286、80386等等cpu在实模式下寻址方式就很好的兼容起来,绝大多数IBM PC兼容机默认的A20地址线是被关闭的。由于在当时没有更好的方法来解决这个问题,所以IBM使用了键盘控制器来操作A20地址线

《Orange'S:一个操作系统的实现》学习笔记(一)

我使用的操作系统是ubuntu 12.10。 1.首先下载nasm:http://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D 我下载的是2.10.07版...
  • yc21337
  • yc21337
  • 2013年03月16日 11:52
  • 1120

《Orange's 一个操作系统的实现》学习笔记--保护模式进阶

我们虽然成功进入了保护模式,但是并没有体验到保护模式给我们带来的便利,上一个例子中打印了一个红色的p,这在实模式中也很容易做到,但是保护模式能做的远不止如此,上文我们提到在保护模式下的寻址空间可以到达...
  • u014634338
  • u014634338
  • 2015年03月14日 12:51
  • 1056

《orange'S一个操作系统的实现》 笔记

简述: 跟着《orange'S一个操作系统的实现》一书进行操作,将其中需要注意的过程记录下来。   第1章 略。 第2章 搭建bochs开发环境 参考链接 《Orange's 一个操作系统的...
  • iefswang
  • iefswang
  • 2012年12月31日 14:08
  • 3309

Orange's 一个操作系统的实现

学习操作系统的过程中先是看了《现代操作系统》,但是觉得太抽象了,没有实现材料,有些东西觉得很虚,从网上了解到了这本书,据说这本书写的很详细。 这本书很难买到,电子版也很少,淘宝也无能为力,配套光盘资...
  • xiazihao1996
  • xiazihao1996
  • 2017年01月22日 14:33
  • 123

orange's一个操作系统的实现之环境搭建

搭建你的环境 1.  虚拟计算机Bochs 简单来讲,它相当于运行在计算机内的小计算机。这个好理解,我用的vmware 不就是这样的东东嘛。不过,现在看来,我得让Bochs 成为包含在vmware...
  • chenglinhust
  • chenglinhust
  • 2012年04月18日 17:11
  • 6394

《ORANGE’S:一个操作系统的实现》第一个例子的实现

如何在window7下编译运行《ORANGE’S:一个操作系统的实现》第一个例子
  • xrhwxy
  • xrhwxy
  • 2014年11月29日 09:48
  • 1148

Orange’s学习笔记(一)

伪汇编指令ORG 学习操作系统两个多月以来,一直对org这个伪汇编指令似懂非懂,拿Orange’s的一个最简单的引导扇区代码来说...
  • y074085024
  • y074085024
  • 2016年05月30日 17:14
  • 312

《Orange'S:一个操作系统的实现》学习笔记(四)

转自http://blog.csdn.net/yc21337/article/details/8684143 讲bochs的调试 新版本的bochs调试命令和老版本有些不同,作者书中给出的命令无...
  • u013897132
  • u013897132
  • 2015年04月12日 23:08
  • 1226

Orange'S学习笔记(一)

学习环境:      Ubuntu 12.04 +
  • tangximing123
  • tangximing123
  • 2014年10月21日 23:48
  • 375

Orange's:一个操作系统的实现 源码的一处小Bug

最近在学习于渊先生《Orange's:一个操作系统的实现》这本书,源码中有关硬盘驱动程序中的一段代码,似乎有些问题,贴出来与大家分享下。 以上是硬盘驱动程序中读写硬盘的一段代码,在w...
  • u013175644
  • u013175644
  • 2014年09月18日 20:54
  • 929
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Orange’s学习笔记(二)
举报原因:
原因补充:

(最多只允许输入30个字)