知识大全 自己动手写操作系统(三)

Posted 寄存器

篇首语:人生在勤,不索何获本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 自己动手写操作系统(三)相关的知识,希望对你有一定的参考价值。

    在上两期中(自己动手写操作系统 ) 我向大家讲述了如何使用Linux提供的开发工具在软盘的启动扇区写一些代码 以及如何调用BIOS的问题 现在 这个操作系统已经越来越接近当年Linus Torvalds的那个具有 历史意义 的Linux内核了 因此 要马上把这个系统切换到保护模式之下     什么是保护模式    自从 年推出第一个微处理器以来 Intel处理器就在不断地更新换代 从 到 奔腾 奔腾Ⅱ 奔腾 等 其体系结构也在不断变化 以后 提供了一些新的功能 弥补了 的一些缺陷 这其中包括内存保护 多任务及使用 KB以上的内存等 并仍然保持和 家族的兼容性 也就是说 仍然具备了 和 的所有功能 但是在功能上有了很大的增强 早期的处理器是工作在实模式之下的 以后引入了保护模式 而在 以后保护模式又进行了很大的改进 在 中 保护模式为程序员提供了更好的保护 提供了更多的内存 事实上 保护模式的目的不是为了保护程序 而是要保护程序以外的所有程序(包括操作系统)     简言之 保护模式是处理器的一种最自然的模式 在这种模式下 处理器的所有指令及体系结构的所有特色都是可用的 并且能够达到最高的性能     保护模式和实模式    从表面上看 保护模式和实模式并没有太大的区别 二者都使用了内存段 中断和设备驱动来处理硬件 但二者有很多不同之处 我们知道 在实模式中内存被划分成段 每个段的大小为 KB 而这样的段地址可以用 位来表示 内存段的处理是通过和段寄存器相关联的内部机制来处理的 这些段寄存器(CS DS SS和ES)的内容形成了物理地址的一部分 具体来说 最终的物理地址是由 位的段地址和 位的段内偏移地址组成的 用公式表示为     物理地址=左移 位的段地址+偏移地址     在保护模式下 段是通过一系列被称之为 描述符表 的表所定义的 段寄存器存储的是指向这些表的指针 用于定义内存段的表有两种 全局描述符表(GDT)和局部描述符表(LDT) GDT是一个段描述符数组 其中包含所有应用程序都可以使用的基本描述符 在实模式中 段长是固定的(为 KB) 而在保护模式中 段长是可变的 其最大可达 GB LDT也是段描述符的一个数组 与GDT不同 LDT是一个段 其中存放的是局部的 不需要全局共享的段描述符 每一个操作系统都必须定义一个GDT 而每一个正在运行的任务都会有一个相应的LDT 每一个描述符的长度是 个字节 格式如图 所示 当段寄存器被加载的时候 段基地址就会从相应的表入口获得 描述符的内容会被存储在一个程序员不可见的影像寄存器(shadow register)之中 以便下一次同一个段可以使用该信息而不用每次都到表中提取 物理地址由 位或者 位的偏移加上影像寄存器中的基址组成 实模式和保护模式的不同可以从图 和图 中很清楚地看出来      图 实模式的寻址     图 保护模式下的寻址    图 段描述俯的格式    此外 还有一个中断描述符表(IDT) 这些中断描述符会告诉处理器到那里可以找到中断处理程序 和实模式一样 每一个中断都有一个入口 但是这些入口的格式却完全不同 因为在切换到保护模式的过程中没有使用到IDT 所以在此就不多做介绍了     进入保护模式     有 个 位控制寄存器 名字分别为CR CR CR 和CR CR 是保留在未来处理器中使用的 在 中没有定义 CR 包含系统的控制标志 用于控制处理器的操作模式和状态 CR 和CR 是用于控制分页机制的 在此 我们关注的是CR 寄存器的PE位控制 它负责实模式和保护模式之间的切换 当PE= 时 说明处理器运行于保护模式之下 其采用的段机制和前面所述的相应内容对应 如果PE= 那么处理器就工作在实模式之下     切换到保护模式 实际就是把PE位置为 为了把系统切换到保护模式 还要做一些其它的事情 程序必须要对系统的段寄存器和控制寄存器进行初始化 把PE位置 后 还要执行跳转指令 过程简述如下      创建GDT表;      通过置PE位为 进入保护模式;      执行跳转以清除在实模式下读取的任何指令     下面使用代码来实现这个切换过程     需要的东西    ◆ 一张空白软盘     ◆ NASM编译器     下面是整个程序的源代码      x c ; 起始地址是 : c   jmp short begin_boot  ; 跳过其它的数据 跳转到引导程序的开始处  bootmesg db Our OS boot sector loading   pm_mesg db Switching to protected mode   dw  ; 每一扇区的字节数  db  ; 每一簇的扇区数  dw  ; 保留的扇区号  db     dw x e     dw x b     db x f     dw     dw     dw  ; 读写扇区号  dw  ; 隐藏扇区号  print_mesg :  mov ah x  ; 使用中断 h的功能 在屏幕上写一个字符串  mov al x  ; 决定调用函数后光标所处的位置  mov bx x   ; 设置显示属性  mov cx x  ; 在此字符串长度为   mov dx x   ; 光标的起始行和列  int x  ; 调用BIOS的中断 h  ret ; 返回调用程序  get_key :  mov ah x    int x  ; Get_key使用中断 h的功能 读取下一个字符  ret  clrscr :  mov ax x  ; 使用中断 h的功能 实现卷屏 如果al= 则清屏  mov cx x  ; 清屏  mov dx x f ; 卷屏至   mov bh  ; 使用颜色 来填充  int x  ; 调用 h中断  ret  begin_boot :  call clrscr  ; 先清屏  mov bp bootmesg ; 提供串地址  call print_mesg ; 输出信息  call get_key  ; 等待用户按下任一键  bits   call clrscr ; 清屏  mov ax xb  ; 使gs指向显示内存  mov gs ax ; 在实模式下显示一个棕色的A  mov word [gs: ] x  ; 显示  call get_key ; 调用Get_key等待用户按下任一键  mov bp pm_mesg ; 设置串指针  call print_mesg ; 调用print_mesg子程序  call get_key ; 等待按键  call clrscr ; 清屏  cli ; 关中断  lgdt[gdtr] ; 加载GDT   mov eax cr     or al x  ; 设置保护模式位  mov cr eax ; 将更改后的字送至控制寄存器中  jmp codesel:go_pm  bits   go_pm :   mov ax datasel    mov ds ax ; 初始化ds和es 使其指向数据段  mov es ax   mov ax videosel ; 初始化gs 使其指向显示内存  mov gs ax   mov word [gs: ] x ; 在保护模式下显示一个白色的字符A  spin : jmp spin ; 循环  bits   gdtr :  dw gdt_end gdt  ; gdt的长度  dd gdt ; gdt的物理地址  gdt  nullsel equ $ gdt ; $指向当前位置 所以nullsel = h  gdt  ; 空描述符  dd       dd  ; 所有的段描述符都是 位的  codesel equ $ gdt ; 这是 h也就是gdt的第二个描述符  code_gdt       dw x ffff ; 段描述符的界限是 Gb  dw x      db x         db x a     db x cf     db x     datasel equ $ gdt     data_gdt       dw x ffff       dw x       db x         db x   db x cf  db x   videosel equ $ gdt     dw       dw x  ; 基址是 xb   db x b  db x       db x       db x   gdt_end  times ($ $$) db    dw x aa      把上面的代码存在一个名为abc asm的文件之中 使用命令nasm abc asm 将得出一个名为abc的文件 然后插入软盘 输入命令 dd if=abc of=/dev/fd 该命令将把文件abc写入到软盘的第一扇区之中 然后重新启动系统 就会看到如下的信息     *Our os booting   * A (棕色)   * Switching to protected mode   * A (白色)    对代码的解释    上面给出了所有的代码 下面我对上述代码做一些解释     ◆ 使用的函数     下面是代码中一些函数的说明     print_mesg 该子程序使用了BIOS中断 h的功能 h 即向屏幕写一字符串 属性控制是通过向一些寄存器中送入不同的值来实现的 中断 h是用于各种字符串操作 我们把子功能号 h送到ah中 用于指明要打印一个字符串 al寄存器中的 说明了光标返回的起始位置 表示调用函数后光标返回到下一行的行首 如果al为 则表示光标位于最后一个字符处     显存被分成了几页 在同一时 cha138/Article/program/Oracle/201311/16515

相关参考

知识大全 自己动手写操作系统(一)

  自由软件社区是一个充满自由和梦想的地方在余年的时间里它创造了一个又一个奇迹然而这些奇迹的创造者不只是Stallman也不只是LinusTorvalds而是活跃在世界各地的不计其数的开发人员    

知识大全 本人的动手能力比较差,做事情有种手忙脚乱的感觉,现在想去学小车驾照,但又害怕自己操作能力不行,

本人的动手能力比较差,做事情有种手忙脚乱的感觉,现在想去学小车驾照,但又害怕自己操作能力不行,跟你的动手能力无关,是你自己没有信心而已。做事之前都暗示自己“这个我能做好么?我能不出错么?”所以,你啥都

知识大全 小学三年级两百字作文写自己过生日原本以为没人记得然后晚上他们给了一个惊喜

小学三年级两百字作文写自己过生日原本以为没人记得然后晚上他们给了一个惊喜早在前两天,我们就准备好了一切东西,蛋糕,礼物,贺卡,节目……想要在5月20号的中午给老师一个惊喜……我们准备的蛋糕都是自己捐钱

知识大全 自己写的数据库操作类

ASP教程:自己写的数据库操作类  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  程序代码lish

知识大全 自己动手编写组件

ASP讲座之十:自己动手编写组件  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  一组件编写速成—

人体奥秘 自己动手摘除阑尾

   阑尾炎是一种常见病,多发病,弄不好容易有生命危险。所以,得了急性阑尾炎要及时治疗。   1961年冬天,前苏联医生列奥尼德?罗戈佐夫随

知识大全 小学三年级家风家训作文格式怎么写

小学三年级家风家训作文格式怎么写家风家训征文范文一:每个家都有属于自己家的家风、家规、家训,要说起我家的家风、家规、家训,那可就要跟我小时候的几件事有关了。从我懂事起,妈妈就告诉我做人的道理,首先要勤

教你自己动手粉刷涂料

天花板用的时间长了难免会显得破旧,有时还会发现墙面起泡、开裂,甚至整片剥落。这时候,我们就要重新粉刷它。如果想感受一下粉刷的乐趣,就自己动手吧,一定要记得先用刷子刷天花板、灯具边缘,再用滚筒作大面积的

自己动手能治疗银屑病

银屑病是一种难以治愈的皮肤顽疾,但它并不是什么难治之症,这种皮肤病还是可以完全治愈的。其实在生活中,银屑病就可以自己经常动手做一些菜品或食物就能治疗银屑病。下面就为大家简单介绍几种治疗银屑病的食物:1

自己动手能治疗银屑病

银屑病是一种难以治愈的皮肤顽疾,但它并不是什么难治之症,这种皮肤病还是可以完全治愈的。其实在生活中,银屑病就可以自己经常动手做一些菜品或食物就能治疗银屑病。下面就为大家简单介绍几种治疗银屑病的食物:1