1.2.2 加载第二部分代码—setup(1)
来源:互联网 发布:和合期货软件下载 编辑:程序博客网 时间:2024/05/03 08:27
1.2.2 加载第二部分代码—setup(1)
1. bootsect对内存的规划
现在,BIOS已经把bootsect(也就是引导程序)载入内存了,它的作用就是把第二批和第三批程序陆续加载到内存中。为了把第二批和第三批程序加载到内存中的适当位置,bootsect首先做的工作就是规划内存。
通常,我们是用高级语言编写应用程序,这些程序是在操作系统的平台上运行的。我们只管写高级语言的代码和数据,至于这些代码和数据在运行的时候放在内存的什么地方,是否会相互覆盖,我们都不用操心,因为操作系统和高级语言的编译器替我们做了大量的看护工作,以确保不会出错。现在我们讨论的是操作系统本身,启动代码使用的是汇编语言,没有高级语言编译器替其提供保障,只有靠操作系统的设计者把内存的安排想清楚,确保无论操作系统如何运行,都不会出现代码与代码、数据与数据、代码与数据之间相互覆盖的情况。为了更准确地理解操作系统的运行机制,我们必须清楚操作系统的设计者是如何规划内存的。
在实模式状态下,寻址的最大范围是1MB,为了规划内存,bootsect首先设计了如下的代码:
- //代码路径:boot/bootsect.s
- SETUPLEN = 4 ! nr of setup-sectors
- BOOTSEG = 0x07c0 ! original address of boot-sector
- INITSEG = 0x9000 ! we move boot here-out of the way
- SETUPSEG = 0x9020 ! setup starts here
- SYSSEG = 0x1000 ! system loaded at 0x10000 (65536)
- ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
这些源代码的作用就是对后续操作所涉及的内存位置进行设置,包括将要加载的setup程序的扇区数(SETUPLEN)和被加载到的位置(SETUPSEG)、启动扇区被BIOS加载的位置(BOOTSEG)和将要移动到的新位置(INITSEG)、内核(kernel)被加载的位置(SYSSEG)、内核的末尾位置(SYSEND)和根文件系统设备号(ROOT_DEV),这些位置在图1-5中都明确地标注了出来。设置这些位置就是为了确保将要载入内存的代码和已经载入内存的代码及数据各在其位,互不覆盖,并且它们各自有够用的内存空间。大家在后续的章节会逐渐看到内存规划的意义和作用。
从现在起,我们的头脑中要时刻牢记这样一个概念:操作系统的设计者要全面、整体地考虑内存的规划。我们会在后续的章节中不断地了解到,精心安排内存是操作系统设计者时时刻刻都要关心的事。我们带着这样的观念继续讲解bootsect程序的执行。
图1-5 实模式下的内存使用规划2.复制bootsect
接下来,bootsect启动程序将它自身(全部的512B内容)从内存0x07C00(BOOTSEG)处复制至内存0x90000(INITSEG)处,这个动作和目标位置如图1-6所示。
图1-6 bootsect复制自身执行这个操作的代码如下:
- //代码路径:boot/bootsect.s
- mov ax, #BOOTSEG
- mov ds, ax
- mov ax, #INITSEG
- mov es, ax
- mov cx, #256
- sub si, si
- sub di, di
- rep
- movw
在这次复制过程中,ds(0x07C0)和si(0x0000)联合使用,构成了源地址0x07C00;es(0x9000)和di(0x0000)联合使用,构成了目的地址0x90000(参看图1-6左边),而mov cx, #256这一行循环控制量,提供了需要复制的“字”数(一个字为两个字节),256个字正好是512字节,即第一扇区的字节数。
通过代码我们还可以看出,图1-5提到的BOOTSEG和INITSEG现在开始发挥作用了。注意,此时CPU的段寄存器(CS)指向0x07C0 (BOOTSEG),即原来bootsect程序所在的位置。
点评
由于“两头约定”和“定位识别”的作用,所以bootsect在开始时“被迫”加载到0x07C00位置。现在将其自身移至0x90000处,说明操作系统开始根据自己的需要安排内存了。
bootsect复制到新位置后,bootsect会执行下面这行加粗的代码:
- //代码路径:boot/bootsect.s
- rep
- movw
- jmpi go, INITSEG
- go: mov ax,cs
- mov ds,ax
从图1-6中我们已经了解到当时CS的值为0x07C0,执行完这个跳转后,CS值变为0x9000 (INITSEG),IP的值为从0x9000(INITSEG)到go: mov ax, cs 这一行对应指令的偏移。换句话说,此时CS:IP指向go: mov ax, cs这一行,程序从这一行开始往下执行。图1-7形象地表示了跳转到go: mov ax, cs这一行执行时CS和IP的状态,如图右下方所示。
图1-7 跳转到go处继续执行- 1.2.2 加载第二部分代码—setup(1)
- 1.2.2 加载第二部分代码—setup(2)
- 1.2.3 加载第三部分代码—system模块(2)
- 1.2.1 加载第一部分代码—引导程序(bootsect)
- 1.2.3 加载第三部分代码—system模块(1)
- 代码2:Hello Viewer示例源代码(第二部分)
- 代码大全——第二部分
- 老代码, 第二部分
- 第18章 (第二部分)类加载器机制
- Python代码优化:第二部分
- 手势识别代码详细说明1(第二部分见下一篇)
- 【算法导论(第三版)】第二章部分习题代码
- 阅读《代码大全》后的读书笔记(第二部分)
- Setup Factory 打包工具部分功能代码解
- Setup Factory 打包工具部分功能代码解
- 经济学原理(第1部分)第二章—7
- 经济学原理(第1部分)第二章—8
- 经济学原理(第1部分)第二章—9
- 学习方法总结
- 1.2.1 加载第一部分代码—引导程序(bootsect)
- Pascal's Triangle II
- iOS—修改AFNetworking源文件可接收text/html的方法
- ViewPager不显示加载的图片或者报错
- 1.2.2 加载第二部分代码—setup(1)
- Reverse Integer
- 实时系统的基本特性?
- CodeForces 3A Shortest path of the king(贪心)——Codeforces Beta Round #3
- 1.2.2 加载第二部分代码—setup(2)
- 1.2.3 加载第三部分代码—system模块(1)
- 1.2.3 加载第三部分代码—system模块(2)
- Learning Spark 第四章 处理键值对 已翻译整理完毕,PDF可下载
- 1.3.1 关中断并将system移动到内存地址起始位置0x00000