linux0.11内核源码——boot和setup部分
https://blog.csdn.net/KLKFL/article/details/80730131
https://www.cnblogs.com/joey-hua/p/5528228.html
参考的两篇博客
x86系统在刚开机时CPU处于实模式
计算机在刚打开电源时 :CS=0xFFFF,IP=0x0000
即寻址为0xFFFF0(ROM BIOS映射区)
然后将 0磁道0扇区 的512个字节读入0x7c00处
然后设置 CS=0x07c0,IP=0x0000
此时0x7c00出存放的代码就是从磁盘的引导扇区读入的那512个字节bootsect
此时一些宏的定义:
BOOTSEG = 0x07c0
INITSEG = 0x9000
SETUPSEG = 0x9020
SYSSEG = 0x1000
表示bootsect先被加载到了0x07c0段,然后bootsect的512个字节会被移动到0x9000段,紧跟着的setup段就从0x9020段开始,system段从0x1000开始
bootsect做的事就是把setup加载到内存上,然后显示logo
entry _start !程序的入口是_start _start:
!下面是调用0x10中断,显示光标操作
mov ah,#0x03
xor bh,bh
int 0x10 mov cx,# !字符串msg的长度
mov bx,#0x0007 !调用0x10中断时,bx寄存器=0x0007表示显示树形
mov bp,#msg1
mov ax,#0x07c0
mov es,ax !es:bp表示要显示的字符串的地址,当前段(bootsect)就是0x07c0,字符串的地址已经赋值给bp
mov ax,#0x1301
int 0x10 !调用中断显示logo !设置一个死循环保证不退出
inf_loop:
jmp inf_loop !这就是要显示的logo
msg1:
.byte ,
.ascii "Hello OS world, my name is LZJ"
.byte ,,, !boot_flag是设置引导扇区的标记,必须由这个才能进行引导,且必须放在最后两个字节
!bootsect的大小是512个字节,所以boot_flag得放在第510个字节处
.org
boot_flag:
.word 0xAA55
然后用bootsect读取setup
先把setup.s编写好
entry _start
_start:
mov ah,#0x03
xor bh,bh
int 0x10 mov cx,#
mov bx,#0x0007
mov bp,#msg2
mov ax,cs
mov es,ax !此时已经将setup加载到了0x9020处,所以字符串的断地址直接设置为cs即可
mov ax,#0x1301
int 0x10 !调用中断 inf_loop: !死循环防止退出
jmp inf_loop
msg1:
.byte ,
.ascii "Hello OS world, my name is LZJ"
.byte ,,, .org !这里还是和bootsect一样
boot_flag:
.word 0xAA55
然后对上面的bootsect.s进行修改让bootsect能够读入setup
SETUPLEN= !自定义的setup段的长度为2个扇区
SETUPSEG=0x07e0 !因为自定仪的代码没有将bootsect移到0x9000出,所以setup段的开始地址在磁盘的的0x07e0处
entry _start
_start:
mov ah,#0x03
xor bh,bh
int 0x10 mov cx,#
mov bx,#0x0007
mov bp,#msg1
mov ax,#0x07c0
mov es,ax
mov ax,#0x1301
int 0x10 load_setup: !从这里开始进行载入setup !0x13号中断是BIOS读磁盘扇区的中断
mov dx,#0x0000 !dh=磁头号,dl=驱动器号
mov cx,#0x0002 !ch=柱面号,cl=开始扇区
mov bx,#0x0200 !表示将读取的内容放在内存es:bp处,es是0x7c0,bp是0x200(前200字节)
mov ax,#0x0200+SETUPLEN !ah=0x02表示读磁盘,al=扇区数量,本来应该是4,但是自己写的setup只占用了2个扇区(512字节)
int 0x13 !调用中断读取setup jnc ok_load_setup !读入成功则跳转 mov dx,#0x0000 !读入失败则调用0x13中断进行复位重启,再次进行读入
mov ax,#0x0000
int 0x13
jmp load_setup !再次进行读写 ok_load_setup:
jmpi ,SETUPSEG !cs:ip跳转到0x07e0:0x0000处,即跳转到setup执行 msg1:
.byte ,
.ascii "Hello OS world, my name is LZJ"
.byte ,,, !自己写的setup.s只占用了512个字节(两个扇区),实际上linux0.11用了4个扇区
.org
boot_flag:
.word 0xAA55
然后用makefile进行编译,可能要修改下build.c
make BootImage
实际上,bootsect在读完setup后还会读入system,其地址为0x10000-0x8ffff
然后是setup需要完成的工作:
完成os启动前的设置,使系统进入保护模式:
首先读入的就是硬件信息:光标,扩展内存数,显卡参数,跟设备号
然后将system模块向下移动到0地址
但是,0地址处本来有重要内容,比如int中断,如何避免冲突?
此时setup让硬件进入保护模式,即int和cs:ip的寻址电路被改变,igt(中断描述符表:用来查中断)和gdt(全局描述符表:用来查cs值对应的段的地址)就是改变后的寻址方式
cs在保护模式中也称为选择子,表示段的编号
具体的实现:
在system移动结束(end_move)后,新建一张临时的gdt表,其内容设置为
    
下面是gdt表的格式
    
有一个寄存器叫做cr0,其末尾PE=1为启动保护模式,
所以先把cr0的末尾置为1来进入保护模式,然后执行指令
\
jmpi ,8 !cs=0x0008,ip=0x0000
cs=8,对应的gdt从第8个字节开始后的内容恰好为0,所以要跳转的地址为0x0000:0x0000
即system的开头head.s文件
到此为止setup也完成了任务,系统开始执行head.s

参考了一张图片,表示的是在每个阶段每个块的位置
模仿linux0.11的代码
mov ax,#INITSEG
! 设置 ds = 0x9000
mov ds,ax
mov ah,#0x03
! 读入光标位置
xor bh,bh
! 调用 0x10 中断
int 0x10
! 将光标位置写入 0x90000.
mov [],dx ! 读入内存大小位置
mov ah,#0x88
int 0x15
mov [],ax ! 从 0x41 处拷贝 个字节(磁盘参数表)
mov ax,#0x0000
mov ds,ax
lds si,[*0x41] !把内存记录磁盘参数的值赋值给si
mov ax,#INITSEG
mov es,ax !INITSEG赋值给es
mov di,#0x0004 !
mov cx,#0x10 !
! 重复16次
rep
movsb
最后是setup.s的全代码
INITSEG = 0x9000
entry _start
_start:
! Print "NOW we are in SETUP"
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#
mov bx,#0x0007
mov bp,#msg2
mov ax,cs
mov es,ax
mov ax,#0x1301
int 0x10 mov ax,cs
mov es,ax
! init ss:sp
mov ax,#INITSEG
mov ss,ax
mov sp,#0xFF00 ! Get Params
mov ax,#INITSEG
mov ds,ax
mov ah,#0x03
xor bh,bh
int 0x10
mov [],dx
mov ah,#0x88
int 0x15
mov [],ax
mov ax,#0x0000
mov ds,ax
lds si,[*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0004
mov cx,#0x10
rep
movsb ! Be Ready to Print
mov ax,cs
mov es,ax
mov ax,#INITSEG
mov ds,ax ! Cursor Position
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#
mov bx,#0x0007
mov bp,#msg_cursor
mov ax,#0x1301
int 0x10
mov dx,[]
call print_hex
! Memory Size
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#
mov bx,#0x0007
mov bp,#msg_memory
mov ax,#0x1301
int 0x10
mov dx,[]
call print_hex
! Add KB
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#
mov bx,#0x0007
mov bp,#msg_kb
mov ax,#0x1301
int 0x10
! Cyles
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#
mov bx,#0x0007
mov bp,#msg_cyles
mov ax,#0x1301
int 0x10
mov dx,[]
call print_hex
! Heads
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#
mov bx,#0x0007
mov bp,#msg_heads
mov ax,#0x1301
int 0x10
mov dx,[]
call print_hex
! Secotrs
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#
mov bx,#0x0007
mov bp,#msg_sectors
mov ax,#0x1301
int 0x10
mov dx,[]
call print_hex inf_loop:
jmp inf_loop print_hex:
mov cx,#
print_digit:
rol dx,#
mov ax,#0xe0f
and al,dl
add al,#0x30
cmp al,#0x3a
jl outp
add al,#0x07
outp:
int 0x10
loop print_digit
ret
print_nl:
mov ax,#0xe0d ! CR
int 0x10
mov al,#0xa ! LF
int 0x10
ret msg2:
.byte ,
.ascii "NOW we are in SETUP"
.byte ,,,
msg_cursor:
.byte ,
.ascii "Cursor position:"
msg_memory:
.byte ,
.ascii "Memory Size:"
msg_cyles:
.byte ,
.ascii "Cyls:"
msg_heads:
.byte ,
.ascii "Heads:"
msg_sectors:
.byte ,
.ascii "Sectors:"
msg_kb:
.ascii "KB" .org
boot_flag:
.word 0xAA55
linux0.11内核源码——boot和setup部分的更多相关文章
- linux0.11内核源码剖析:第一篇 内存管理、memory.c【转】
		转自:http://www.cnblogs.com/v-July-v/archive/2011/01/06/1983695.html linux0.11内核源码剖析第一篇:memory.c July ... 
- linux-0.11 内核源码学习笔记一(嵌入式汇编语法及使用)
		linux内核源码虽然是用C写的,不过其中有很多用嵌入式汇编直接操作底层硬件的“宏函数”,要想顺利的理解内核理论和具体实现逻辑,学会看嵌入式汇编是必修课,下面内容是学习过程中的笔记:当做回顾时的参考. ... 
- linux0.11内核源码——进程各状态切换的跟踪
		准备工作 1.进程的状态有五种:新建(N),就绪或等待(J),睡眠或阻塞(W),运行(R),退出(E),其实还有个僵尸进程,这里先忽略 2.编写一个样本程序process.c,里面实现了一个函数 /* ... 
- Linux0.11内核源码——内核态进程切换的改进
		本来想自己写的,但是发现了一篇十分优秀的博客 https://www.cnblogs.com/tradoff/p/5734582.html system_call的源码解析:https://blog. ... 
- Linux0.11内核源码——内核态线程(进程)切换的实现
		以fork()函数为例,分析内核态进程切换的实现 首先在用户态的某个进程中执行了fork()函数 fork引发中断,切入内核,内核栈绑定用户栈 首先分析五段论中的第一段: 中断入口:先把相关寄存器压栈 ... 
- 自制操作系统小样例——参考部分linux0.11内核源码
		详细代码戳这里. 一.启动引导 采用软件grub2进行引导,基于规范multiboot2进行启动引导加载.multiboot2的文档资料戳这里. 二.具体内容 开发环境 系统环境:Ubuntu 14. ... 
- linux0.11内核源码——用户级线程及内核级线程
		参考资料:哈工大操作系统mooc 用户级线程 1.每个进程执行时会有一套自己的内存映射表,即我们所谓的资源,当执行多进程时切换要切换这套内存映射表,即所谓的资源切换 2.但是如果在这个进程中创建线程, ... 
- ubuntu14.04 64位系统下编译3.13.11内核源码
		该过程一共分为四步: 1.下载内核:我下载的是3.13.11这个版本的内核! 2.解压内核:我将其解压/home/jello/Downloads/linux-3.13.11目录下!下文将会基于此目录编 ... 
- linux0.01内核源码结构
		目录 boot 系统引导. fs 文件系统. include 头文件.一些C标准库,系统核心库. init 入口.main.c. kernel 内核. lib 库.C源程序,一些基本核心的程序. mm ... 
随机推荐
- python安装centos7
			1.安装git (需root权限) yum -y install git 2.安装依赖包 yum -y install gcc make patch gdbm-devel openssl-devel ... 
- 剑指offer第二版面试题5:从尾到头打印链表(JAVA版)
			题目描述: 输入一个链表,从尾到头打印链表每个节点的值.返回新链表. import java.util.Stack; //定义链表结构 class ListNode { int value; List ... 
- Django csrf,xss,sql注入
			一.csrf跨站请求伪造(Cross-site request forgery) CSRF的攻击原理:简单说就是利用了高权限帐号(如管理员)的登录状态或者授权状态去做一些后台操作,但实际这些状态并没有 ... 
- resultType和resultMap一对一查询小结
			resultType和resultMap一对一查询小结 SELECT orders.*, USER .username,USER.birthday,USER.sex,USER.address FROM ... 
- (转载)Solr4.x在Tomcat下的部署
			Step1 下载安装包: 下载最新版本安装包 点击此处下载Tomcat 点击此处下载Solr Step2 解压: 解压Tomcat和Solr Step3 拷贝War包: 拷贝\solr-4.x\ ... 
- java_第一年_JavaWeb(9)
			JavaBean是一个遵循某种特定写法的Java类,有以下特点: 必需具有一个无参的构造函数 属性必需私有化 私有化的属性必需通过public类型的方法暴露给其它程序,其方法命名也有一定的规范 范例: ... 
- elementUI 导航栏点击之后改变背景色,背景色悬停
			一开始设置的是: .menuLeft .el-menu-item:hover{ background: #6db6ff !important; } .menuLeft .el-submenu__tit ... 
- 源码分析--HashMap(JDK1.8)
			在JDK1.8中对HashMap的底层实现做了修改.本篇对HashMap源码从核心成员变量到常用方法进行分析. HashMap数据结构如下: 先看成员变量: 1.底层存放数据的是Node<K,V ... 
- Django--Forms组件使用
			Forms组件的使用 在html表单验证中,需要通过各种信息的验证,比如注册界面的姓名.密码.邮箱.电话等的验证,是否符合定义好的规则,不可能每次都要取出对应的字段一一判断,django内置了Form ... 
- linux中设置虚拟域名
			一.打开tomcat安装目录下conf/server.xml这个文件在server.xml文档中找到 </Engine></Service> 接着添加上面添加以下内容(暂时先说 ... 
