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 ...
随机推荐
- day17—Flex弹性布局详解(一)
转行学开发,代码100天——2018-04-02 今天看到一篇大神的文章,关于flex布局的详解,对flex用法介绍的相当详细,非常有助于我等初学者更深入了解这种布局方式. 文章链接 [基础知识]Fl ...
- shtml与html
前言 在浏览网页的时,忽然发现了一个网址不是以[.html]结尾,而是[.shtml].顿时勾起了我的好奇心,这是什么鬼?于是打开google,开始维基. SHTML 什么是 SHTML 使用SSI( ...
- CSAPP:局部性原理
一个编写良好的计算机程序常常具有良好的局部性(locality).局部性通常有两种不同的形式:时间局部性(temporal locality)和空间局部性(spatial locality).在一个具 ...
- netcore之mysql中文乱码问题解决记录
尝试了netcore代码里面设置基本无效了 https://dev.mysql.com/doc/connector-net/en/connector-net-entityframework-core- ...
- Lambda -语法使用,代码简化
使用Lambda的方式实现线程 线程中()是run方法的(),可用来接受参数,格式: new Thread(()->{ System.out.println(Thread.currentThre ...
- Mysql基础篇(笔记)
mysql数据库是由DB跟DBMS跟sql组成 DB 数据库仓库 DBMS 数据库管理系统 SQL 一门通用的数据库语言 数据库启动命令 : 关闭->net stop MySQL || 开启 ...
- Day6----Python的pyinstall库的使用
Python的pyinstaller库 pyinstaller的安装 介绍:pyinstaller是Python的第三方库,主要用于将Python代码打包成 可执行文件 ,以此达到就算没安装P ...
- dataTable获取所有数据
"drawCallback": function(settings,e) { var api = new $.fn.dataTable.Api( settings ); resul ...
- Tesseract-OCR识别中文与训练字库
转自:https://www.cnblogs.com/lcawen/articles/7040005.html 关于中文的识别,效果比较好而且开源的应该就是Tesseract-OCR了,所以自己亲身试 ...
- 关于javascript中的构造函数和普通函数探索 [转]
这是第一篇关于javascript模块的文章,在javascript入门的目录下,主要是记录一些对网上精彩的js研读碰到的疑惑,并做一些实验和探索 关于js中的对象和方法的定义博主感到非常的迷惑.针对 ...