;标题:简单内核引导启动程序
;作者:黄旭冬
;程序描述:
;   该程序首先跳到0x07c00处,这是BIOS开始时将本程序加载到的位置,
;   然后本程序将内核代码(head.s代码)加载到0x10000处,再移动到0x0处0,
;   注意;加载到0x0处是为了设置GDT表时可以简单一些,因而也可以让head.s程序尽量短一些,
;   但不能一开始就加载到0x0处是因为加载操作需要使用BIOS提供的中断过程,而BIOS使用的
;   中断限量表正处于内存0开始的地方,并且在内存1KB开始处是BIOS程序使用的数据区,所以
;   若直接将head代码加载于此将导致BIOS中断过程不能正常运行。
;   最后进入保护模式,并转到0x0处继续运行。
;日期: 2012年11月28日
BOOTSEG = 0x07c0   ;BIOS初始时将本引导程序加载到的位置
SYSSEG = 0x1000    ;将head.s加载于此
SYSLEN = 17    ;内核占用的最大磁盘扇区数,为了简化程序,这里只能加载长度不超过16个扇区的内核,这个作为BIOS的读扇区功能的参数。问:既然仅限制16个扇区,为何以17作为读入扇区数?
entry start ;这个的作用是什么呢?答:汇编器汇编时必须有一个start指明入口地址,否则出现汇编错误。
start:
jmpi    go, #BOOTSEG    ;jmpi是段间跳转指令,执行的结果是CS寄存器值变为0x7c0,接下来执行BOOTSEG:go处的指令。问:为什么需要这句话呢?不写不也是从下面顺序执行吗?
go: mov     ax, cs  ;ax是属于通用寄存器之一的累加寄存器
mov     ds, ax
mov     ss, ax  ;让两个段寄存器ds和ss指向0x7c0段,问:1.为何需要让这两个段寄存器指向这里?    2.为何要通过ax间接传递数据而不能直接赋值呢?
mov     sp, #0x400  ;设置临时栈指针。其值大于程序末端并有一定空间即可。问:1.为何需要一个临时栈指针?    2.这个值怎么定,程序末端在哪里如何计算?
;现在加载内核代码(head.s程序)至0x10000开始处
load_system:    ;问:标号有没有实际作用?
;首先介绍一下BIOS的0x13的0x02号功能
;BIOS INT 0x13的0x02号功能 - 读扇区
;INT 0x13/AH=0x02 - 将磁盘上的扇区读入内存
;AH = 0x02
;AL = 要读入的扇区数
;CH = 柱面(磁道)号的低8位
;CL = 位7、6是柱面(磁道号)高2位,位5-0是读入的起始扇区号(从1计)    ;问:为什么从1计,是规定吗?
;DH = 磁头号
;DL = 驱动器号
;ES:BX = 缓冲区(用于保存读入扇区)的位置
;返回值:
;AH = 状态码
;AL = 读到的扇区数
;CF = 失败为1,成功为0
mov ch, #0x00
mov cl, #0x02   ;问:为什么是加载2号扇区?答:因为磁盘的第一扇区放置的即是本程序,而紧邻的第二扇区开始则放置内核代码
mov dh, #0x00
mov dl, #0x00   ;问:驱动器是指什么?
mov ax, #SYSSEG         ;不能直接执行mov es, #SYSSEG,编译时会出现illegal immediate mode错误
mov es, ax
xor bx, bx  ;将内核放置于1000:0000位置处
mov ah, #0x02
mov al, #SYSLEN
int 0x13    ;设置好各项参数后即可调用BIOS的0x13功能
jnc ok_load ;jnc指令是???,这行指令表示未发生错误(根据AH中的状态码)则跳转继续运行,否则死循环
die:    jmp die     ;死循环指令
;到目前为止我们已将内核代码从磁盘读入到内存中指定位置了,下面就开始将内核代码转移到0x0这个内存开始位置。共移动8K字节((16个扇区*512B/每扇区)/1024=8KB)。
ok_load:
cli ;关中断    问:为何在开始移动时要关中断,是为了防止什么事件的发生吗?若不关会怎样?
;在搬移之前先介绍一下REP指令及MOVW指令
;REP:重复前缀
;字符串操作本身每次只处理一个内存值,但如果使用重复前缀的话,该指令就会使用ECX作为计数器进行重复。换句话说,就是可以用一条指令处理整个数组。
;MOVW:将DS:SI(源变址寄存器)的内容送至ES(附加段数据寄存器):DI(目的变址寄存器),是复制过去,原来的代码还在。
;附:ES和DS的功能相同,程序中设有多个数据段时,可以选用ES寄存器。一般在串处理时用得比较多。
;   比如将一段内存空间存储的数据复制到另一段空间,可以分别设置DS:SI指向源存储数据的地址,ES:DI指向目的存储数据的地址
mov ax, #SYSSEG     ;移动开始位置:DS:SI=0x1000:0;目的位置:ES:DI=0:0
mov ds, ax
xor ax, ax
mov es, ax
mov cx, #0x1000 ;设置共移动4K次,每次1个字(即移动16个扇区的代码)注意!进制上别粗心了,之前我写成#2000了。
sub si, si
sub di, di
rep             ;执行重复移动指令
movw
;加载IDT和GDT基地址寄存器IDTR和GDTR
mov ax, #BOOTSEG
mov ds, ax  ;让DS重新指向0x7c0段(问:1.不一定要让数据段指向这个位置吧,这样做应该是正好利用不再有用的空间(本程序的代码段的那部分空间)吧? 答:这里必须让ds重新指向0x07c0段,因为lidt和lgdt隐含的完整格式实际上是ds:idt_operand和ds:gdt_operand,会在ds:operand这个位置去寻找它们的六字节操作数。 2.这时的情况是不是:0x0-0x2000:简单内核的代码区;0x7c00:数据段起始地址;根据上述,sp寄存器存了0x400,那么这个临时栈指针可访问的堆栈的区域是哪里呢?)
lidt idt_48     ;加载IDTR。6字节操作数:2字节表长度,4字节线性基地址
lgdt gdt_48     ;加载GDTR。6字节操作数:2字节表长度,4字节线性基地址
;设置好了中断描述符表IDT和全局描述符表GDT,并且加载好IDTR和GDTR后,即准备进入保护模式
;设置控制寄存器CR0(即机器状态字),进入保护模式。段选择符值8对应GDT表中第2个段描述符
;附:控制寄存器(CR0、CR1、CR2和CR3)用于控制和确定处理器的操作模式以及当前执行任务的特性。
;   CR0中含有控制处理器操作模式和状态的系统控制标志
;   CR1保留不用
;   CR2含有导致页错误的线性地址
;   CR3含有页目录表物理内存基地址(因此该寄存器也被称为页目录基地址寄存器PDBR)
mov ax, #0x0001 ;(操作数的第四位是0x1=0001,将传给CR0)
;先介绍一下LMSW指令:
;   LMSW: Load Machine Status Word(置处理器状态字)
;   只有操作数的低4位被存入CR0,只有PE(位0),MP(位1)和EM(位2)和TS(位3)被改写,CR0其他位不受影响。
lmsw    ax      ;设置CR0
;先介绍一下JMPI指令(段间跳转指令,用于x86实模式下):
;先注意此指令是用于实模式下,JMPI B, A 即跳到位置A:B处去执行
;而JMP指令与它的区别是它是段内的跳转,但它俩都是无条件的跳转
jmpi    0, 8    ;然后跳转至段选择符指定的段中,偏移0处
;注意此时段值已是段选择符。该段的线性基地址是0。
;(问:1.这样应该是跳转到8:0处吧,怎么会跳到段选择符指定的段中?        2.这个8是怎么来的,是相对于DS寄存器所指定的位置0x7c0吗?)
;下面是全局描述符表GDT的内容。其中包含3个段描述符。第1个不用,另2个是代码和数据段描述符。
gdt:    .word   0,0,0,0 ;段描述符0,不用。每个描述符项占8字节。(注意这种描述方式,这里使用了4个2字节的字表示了一个共占64位的描述符项)
.word   0x07FF
.word   0x0000
.word   0x9A00
.word   0x00C0
.word   0x07FF
.word   0x0000
.word   0x9200
.word   0x00C0
;下面分别是LIDT和LGDT指令的6字节操作数
idt_48: .word   0
.word   0,0
gdt_48: .word   0x7ff
.word   0x7c00+gdt,0
.org 510    ;(问:这是什么?答:我经分析认为.org NUM是指定从NUM处开始填入下面的内容)
.word   0xAA55

Linux 0.00简单多任务内核boot.s超详注释相关推荐

  1. Linux 0.00简单多任务内核head.s超详注释

    # head.s包含32位保护模式初始化设置代码.时钟中断代码.系统调用中断代码和两个任务的代码. # 在初始化完成之后程序移动到任务0开始执行,并在时钟中断控制下进行任务0和1之间的切换操作. LA ...

  2. Linux 0.00 代码解析(一)

    <Linux内核完全剖析>这本书在第4章给出了一个简单多任务内核示例程序,作者称之为Linux 0.00系统. 源码的下载地址和实验方法可以参考我的博文 http://blog.csdn. ...

  3. Linux 0.00 的编译和运行

    <Linux内核完全剖析>这本书在第4章给出了一个简单多任务内核示例程序,我们称之为Linux 0.00系统.本文介绍了一种把它跑起来的方法. 一.实验环境 Win7(64位)+Vmwar ...

  4. Linux 0.00 Makefile 说明

    关于Linux-0.00 的编译和运行可以参考我的博文:http://blog.csdn.net/longintchar/article/details/78757065 为了能在64位的Ubuntu ...

  5. 4.9一个简单的多任务内核实例

    第四章第9节 本节描述了一个简单多任务内核的设计和实现方法,这个内核包括两个特权级3的用户任务和一个系统调用中断过程. 本节给出的内核实例由两个文件构成.一个是使用as86语言编制的引导启动程序boo ...

  6. bochs调试linux内核学习4 - bochs配置文件的$BXSHARE变量、bochs的System BIOS must end at 0xfffff错误、运行内核0.00版本

    经过前面的一些操作,目前只能用bochs调试linux 0.11内核的启动部分:下面来继续学习相关内容: 根据资料,在内核0.11之前,还有更小的内核0.00版本需要认识:在此下载: http://o ...

  7. linux 0.11根文件系统,linux内核与根文件系统之间的关联的理解

    学者 于 2011-10-19 12:46:08发表: 哦,原来还有一个initrd镜像,后缀名为".img",我一直以为只有一个内核镜像呢: 还有引导程序的路径表示与系统不同啊! ...

  8. Linux 0.11内核分析02:系统启动

    目录 1. 内核镜像的构建 1.1 内核源码结构 1.1.1 boot 1.1.2 fs 1.1.3 include 1.1.4 init 1.1.5 kernel 1.1.6 lib 1.1.7 m ...

  9. linux 0.11 内核学习 -- bootsect.s, 万里长征第一步

    呵呵,终于将linux 0.11 下面的boot文件夹下的三个文件读完,下面是相关注释,没有汇编基础的人也是可以读的.废话少说,下面就是linux的源码了. 参考资料 Linux内核完全注释.pdf ...

最新文章

  1. RESTful 规范
  2. Spring JTA multiple resource transactions in Tomcat with Atomikos example--转载
  3. Javascript之旅——第四站:parseInt中要注意的坑
  4. NamingException
  5. HTML-HTML基本语法和标签
  6. 我的 IDEA 使用 配置策略
  7. 蓝桥杯2017年第八届C/C++省赛C组第七题-Excel地址
  8. visio安装后导致excel滑动滚动条闪退的问题
  9. 频率相噪中相关公式、名词注释详解
  10. java与VUE有啥不同_React的世界观及与Vue之比较
  11. C盘清理后遗症总结(C盘清理)
  12. python变量、运算符
  13. OpenCV在线文档目录翻译(一)
  14. Matlab读取shp文件及存储形式
  15. java基础之数据类型
  16. 软件工程工作量评估中的ILF,EIF,EI,EO,EQ术语解释
  17. 东南大学计算机2020初试成绩公布,东南大学2020考研复试分数线已公布
  18. 中国科大84届计算机系杰出校友,中科大校友回国加盟清华,女儿放弃美国国籍,回国效力...
  19. Spring @Pointcut
  20. 中国奶牛智能领口标签市场趋势报告、技术动态创新及市场预测

热门文章

  1. 来自GDPR的警示:是时候关注您的客户数据了
  2. 关于openGL, openGL ES, openVG及android中2D调用关系的报告
  3. 四种计算机硬件故障检修方法,计算机硬件检测及维修几点认识.doc
  4. oracle怎么备份bak文件,[转载]如何将sqlserver的bak文件中的数据还原到oracle数据库中...
  5. 电子科技大学计算机博士要求,博士研究生发表论文的要求-电子科技大学.PDF
  6. 华为自研操作系统Project Z曝光
  7. 软考 - 软件设计师 - 下午-案例分析 做题技巧与考点整理
  8. Java笔记总结(一)
  9. Mysql里where语句里不能使用SUM聚合函数筛选怎么办?
  10. Apollo 星火计划踩坑记录 dreamview启动报错“No such file or directory: ‘ping‘: ‘ping‘”