linux内核代码注释 赵炯 第三章引导启动程序
- linux内核代码注释
第三章引导启动程序
boot目录中的三个汇编代码文件 bootsect.s和setup.s采用近似intel的汇编语法,需要8086汇编器连接器as86和ld86
head.s用GNU的汇编程序格式 并且运行在保护模式下,需要GNU的as进行编译。为AT&T语法的汇编语言程序。GNU只支持386后的cpu 不支持实模式下的程序
总体功能
pc加电-》cpu进入实模式-》从0xfff0开始执行程序代码(bios地址),进行系统检测,并在物理地址0处开始初始化中断向量--》启动设备的第一个扇区 引导扇区 512字节,读入到内存0x7c00处,并且跳转到此。
linux系统最前面的部分就是boot/bootsect.s 由bios读入到内存绝对地址0x7c00 (31k)--》当此程序执行时,会将自己移动到绝对地址0x90000 576k处--》将启动设备中后2k字节代码boot/setup.s读入到内存0x90200处,而内处的其他部分 system模块 则被读入到从地址0x10000开始处,,后面的setup程序会把system模块移动到内存起始处。 看上图
整个系统从地址0x10000移动到0x0000处,进入保护模式并跳转到系统的鱼虾部分 在0x0000处。此时所有的32位运行方式的设置启动完成,IDT GDT 以及LDT被加载,cpu和协处理器已经确认,分页机制也已经准备就绪
然后嗲用init/main.c程序
一bootsect.s 程序
(1)
磁盘引导块程序 驻留在磁盘的一个扇区中 引导扇区,0磁道 柱面,0磁头,第1个扇区。pc机加电rom-bios自检后,引导扇区由bios加载到内存0x7c00处,然后将自己移动到内存0x90000处。
作用:
1.将setup模块 (由setup.s编译而成)从磁盘加载到内存,紧接着bootsect的后面位置0x90200、
2.利用BIOS中断0x13取磁盘参数表中当前启动引导盘的参数
3.在屏幕上显示loading system... 字符串
4.将system模块从磁盘加载到内存0x10000开始处,
5.确定根文件系统的设备号 若未指定,则根据所保存的引导盘的每磁道扇区数判别处盘的类型和种类 并保存其设备号于root_dev 引导块0x508地址处,最后长跳转到setup程序的开始处 0x90200 执行setup程序。
(2)代码注释
- !
- ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
- ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
- ! versions of linux
- !
- SYSSIZE = 0x3000
- !
- ! bootsect.s (C) 1991 Linus Torvalds
- !
- ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
- ! iself out of the way to address 0x90000, and jumps there.
- !
- ! It then loads 'setup' directly after itself (0x90200), and the system
- ! at 0x10000, using BIOS interrupts.
- !
- ! NOTE! currently system is at most 8*65536 bytes long. This should be no
- ! problem, even in the future. I want to keep it simple. This 512 kB
- ! kernel size should be enough, especially as this doesn't contain the
- ! buffer cache as in minix
- !
- ! The loader has been made as simple as possible, and continuos
- ! read errors will result in a unbreakable loop. Reboot by hand. It
- ! loads pretty fast by getting whole sectors at a time whenever possible.
- .globl begtext, begdata, begbss, endtext, enddata, endbss //段定义
- .text
- begtext:
- .data
- begdata:
- .bss
- begbss:
- .text
- 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 setup程序所在段
- SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). 系统模块段
- ENDSEG = SYSSEG + SYSSIZE ! where to stop loading 停止加载的位置
- ! ROOT_DEV: 0x000 - same type of floppy as boot. 软盘类型
- ! 0x301 - first partition on first drive etc 硬盘类型
- ROOT_DEV = 0x306 启动盘设备类型
- entry start 程序入口地址
- start:
- mov ax,#BOOTSEG
- mov ds,ax ds段基地址
- mov ax,#INITSEG
- mov es,ax es段基地址
- mov cx,#256
- sub si,si si和di均清0
- sub di,di
- rep 循环256次 共512个字节的内容
- movw 传送字 将bootseg段的代码移动到es指向的initseg段
- jmpi go,INITSEG 跳转到initseg段的go标号位置
- go: mov ax,cs cs ds es指向相同的位置
- mov ds,ax
- mov es,ax
- ! put stack at 0x9ff00.
- mov ss,ax ss堆栈段基址位0x9ff00
- mov sp,#0xFF00 ! arbitrary value >>512 sp指针的位置调整ss:sp=0x90000:ff00位置 此时位空栈 以上为初始化
- ! load the setup-sectors directly after the bootblock.
- ! Note that 'es' is already set up.
- load_setup: 加载setup程序
- mov dx,#0x0000 ! drive 0, head 0 驱动器0 磁头0 dh磁头 dl驱动器号
- mov cx,#0x0002 ! sector 2, track 0 扇区2 磁道0 ch磁道号 柱面号 cl开始扇区
- mov bx,#0x0200 ! address = 512, in INITSEG 512个字节
- mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors ah=2 功能号为2 al=4 扇区数量
- int 0x13 ! read it 中断13 读磁盘的功能 读如到es:bx 数据缓冲区
- jnc ok_load_setup ! ok - continue 判断cf标志位 cf=0正常 cf=1 出错
- mov dx,#0x0000
- mov ax,#0x0000 ! reset the diskette 重设寄存器
- int 0x13 调用中断13号 复位磁盘
- j load_setup 跳转load_setup
- ok_load_setup:
- ! Get disk drive parameters, specifically nr of sectors/track 以下为获取磁盘驱动器的参数
- mov dl,#0x00
- mov ax,#0x0800 ! AH=8 is get drive parameters
- int 0x13 中断13 ah为8调用获取磁盘参数
- mov ch,#0x00 ch清0
- seg cs 找cs段执行指令 下一条指令在cs段
- mov sectors,cx 保存每磁道扇区数
- mov ax,#INITSEG es指向0x9000的段处
- mov es,ax
- ! Print some inane message
- mov ah,#0x03 ! read cursor pos
- xor bh,bh
- int 0x10 中断 读取光标位置
- mov cx,#24 共24个字符
- mov bx,#0x0007 ! page 0, attribute 7 (normal) bh为页 bl为属性
- mov bp,#msg1 es:bp指向要显示的字符串
- mov ax,#0x1301 ! write string, move cursor ah为13 显示字符串功能, al为1表示写方式
- int 0x10 中断调用
- ! ok, we've written the message, now
- ! we want to load the system (at 0x10000)
- mov ax,#SYSSEG es指向0x1000处
- mov es,ax ! segment of 0x010000
- call read_it 调用子程序 134行
- call kill_motor 关闭马达 214行
- ! After that we check which root-device to use. If the device is
- ! defined (!= 0), nothing is done and the given device is used.
- ! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
- ! on the number of sectors that the BIOS reports currently.
- seg cs
- mov ax,root_dev
- cmp ax,#0
- jne root_defined
- seg cs
- mov bx,sectors
- mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
- cmp bx,#15
- je root_defined
- mov ax,#0x021c ! /dev/PS0 - 1.44Mb
- cmp bx,#18
- je root_defined
- undef_root:
- jmp undef_root
- root_defined:
- seg cs
- mov root_dev,ax
- ! after that (everyting loaded), we jump to
- ! the setup-routine loaded directly after
- ! the bootblock:
- jmpi 0,SETUPSEG
- ! This routine loads the system at address 0x10000, making sure
- ! no 64kB boundaries are crossed. We try to load it as fast as
- ! possible, loading whole tracks whenever we can.
- !
- ! in: es - starting address segment (normally 0x1000)
- !
- sread: .word 1+SETUPLEN ! sectors read of current track 磁道中已经读取的扇区数 开始时已经读取1扇区 bootsect和setup程序所占的扇区数为setuplen
- head: .word 0 ! current head
- track: .word 0 ! current track
- read_it:
- mov ax,es
- test ax,#0x0fff es必须是64k边界 es实际指向的内存为0x10000共20位 相与的是高16位 数值结果不保存
- die: jne die ! es must be at 64kB boundary
- xor bx,bx ! bx is starting address within segment bx指向段基地址
- rp_read:
- mov ax,es
- cmp ax,#ENDSEG ! have we loaded all yet? 判断es是否等于停止加载的段地址
- jb ok1_read 小于时跳转到ok1_read标号处继续执行,否则返回
- ret
- ok1_read:
- seg cs cs段的指令执行
- mov ax,sectors 取每磁道扇区数
- sub ax,sread ax-sread 等于未读取的扇区数 结果送ax
- mov cx,ax
- shl cx,#9 左移9位 相当于乘以512 结果为未读扇区的字节数
- add cx,bx 加上bx(段内偏移值) 此次读操作后段内读入字节数
- jnc ok2_read cf标志位判断 是否有进位 如果不等于1 则跳转,即没有超过64k
- je ok2_read 等于64k则跳转 156行处
- xor ax,ax 超过64k 即加上此次将读磁道上所有未读扇区时会超过64k ,则ax清0
- sub ax,bx ax-bx 计算此次能读入的字节数 64k-bx(段内读偏移)
- shr ax,#9 再次将字节数转换成扇区数 右移9位 相当于除以512
- ok2_read:
- call read_track 调用read_track
- mov cx,ax
- add ax,sread
- seg cs
- cmp ax,sectors
- jne ok3_read
- mov ax,#1
- sub ax,head
- jne ok4_read
- inc track
- ok4_read:
- mov head,ax
- xor ax,ax
- ok3_read:
- mov sread,ax
- shl cx,#9
- add bx,cx
- jnc rp_read
- mov ax,es
- add ax,#0x1000
- mov es,ax
- xor bx,bx
- jmp rp_read
- read_track:
- push ax
- push bx
- push cx
- push dx
- mov dx,track
- mov cx,sread
- inc cx
- mov ch,dl
- mov dx,head
- mov dh,dl
- mov dl,#0
- and dx,#0x0100
- mov ah,#2
- int 0x13
- jc bad_rt
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- bad_rt: mov ax,#0
- mov dx,#0
- int 0x13
- pop dx
- pop cx
- pop bx
- pop ax
- jmp read_track
- /*
- * This procedure turns off the floppy drive motor, so
- * that we enter the kernel in a known state, and
- * don't have to worry about it later.
- */
- kill_motor:
- push dx
- mov dx,#0x3f2
- mov al,#0
- outb
- pop dx
- ret
- sectors:
- .word 0
- msg1:
- .byte 13,10
- .ascii "Loading system ..."
- .byte 13,10,13,10
- .org 508
- root_dev:
- .word ROOT_DEV
- boot_flag:
- .word 0xAA55
- .text
- endtext:
- .data
- enddata:
- .bss
- endbss:
linux内核代码注释 赵炯 第三章引导启动程序的更多相关文章
- 《Linux内核设计与实现》第三章学习笔记
第三章 进程管理 姓名:王玮怡 学号:20135116 一.进程 1.进程的含义 进程是处于执行期的程序以及相关资源的总称,程序本身并不是进程,实际上就是正在执行的代码的实时结果.Linux内核通 ...
- Linux内核分析 读书笔记 (第三章)
第三章 进程管理 3.1 进程 1.进程: 进程就是处于执行期的程序. 进程就是正在执行的程序代码的实时结果. 进程是处于执行期的程序以及相关的资源的总称. 进程包括代码段和其他资源. 2.线程:执行 ...
- linux及安全《Linux内核设计与实现》第三章——20135227黄晓妍
第三章 (由于linux不区分进程和线程,所以它们在linux中被称为task,也叫任务) 总结:本章主要包括进程以及线程的概念和定义,Linux内核如何管理每个进程,他们在内核中如何被列举,如何创建 ...
- 《Linux内核设计与实现》第三章读书笔记
一.进程(任务)描述 1.进程是处于执行期的程序:除了可执行程序代码,还包括打开的文件.挂起的信号.内核内部数据.一个或者多个执行线程等多种资源 线程是在进程活动中的对象:内核调度的对象是线程而不是进 ...
- 《Linux内核设计与实现》 第三章学习笔记
一.进程 1.进程就是处于执行期的程序(目标码存放在某种存储介质上).但进程并不仅仅局限于一段可执行程序代码,通常进程还要包含其他资源.执行线程,简称线程(thread),是在进程中活动的对象. 2. ...
- 《linux内核设计与实现》第三章
1.进程 进程就是正在执行的程序代码的实时结果,不仅包含可执行代码,还包括其他资源,比如:打开的文件,挂起的信号,内核内部数据结构,处理器状态,一个或多个具有内存映射的内存地址空间及一个或多个执行线程 ...
- 【读书笔记】Linux内核设计与实现(第三章)
3.1 进程 处于执行期的程序. 进程就是正在执行的程序代码的实时结果.内核需要有效而又透明地管理所有细节. 执行线程(简称线程):在进程中活动的对象.每个线程都拥有一个独立的程序计数器.进程栈和一组 ...
- 《Linux内核》课本读书笔记 第三章
- 第三次阅读赵炯博士的《linux内核代码完全注释》:序
这是我第三次阅读linux内核代码完全注释了,当然前两次也没有读完,第一次读到第五章,第二次第七章. 所以说,赵炯博士对我最大的帮助时介绍了intel386的结构,以及内核编程的方法. 至于真正的内核 ...
随机推荐
- 3D图形引擎决定三维产业差异化
从2009年中国3D产业初步兴起开始,短短几年间中国的3D技术得到了飞速的发展,3D打印机.3D投影仪.Web3D.虚拟现实.场景漫游等等产业应用应运而生,设备制造商和内容提供商都开始发挥自主创新的优 ...
- 64位Windows系统下32位应用程序连接MySql
1.首先得安装“Connector/ODBC”,就是Mysql的ODBC驱动,这个是与应用程序相关的,而不是与操作系统相关的,也就是说,不管你的系统是x64还是x86,只要你的应用程序是x86的那么, ...
- JavaScript模板引擎的使用
为了将数据库中的一组记录转换成HTML输出到界面上,大家都采用哪些做法呢? 在WebForm时代我们经常使用datagrid.repeater,当MVC问世后我们开始直接在视图上编写C#循环语句,而现 ...
- SAP成都研究院DevOps那些事
今天的文章来自我的同事平静静,SAP成都研究院一位程序媛.平静静2010年加入SAP,熟悉她的人一般都叫她平静.在她待过的每个小组,平静静都不是最引人瞩目的开发人员,然而她总是能一如既往,保质保量地完 ...
- [C++讨论课] 课堂记录(一)
今天第一次参加c++讨论课,记录下了各组同学的展示的问题或者解决方法,也有一些知识点上的内容,供以后复习参考. 1.常量指针和指针常量问题 常量指针:指向常量的指针,例如const int *p = ...
- hd - MFM/IDE 硬盘设备
描述 DESCRIPTION hd* 开头的设备是以裸模式(raw mode)访问MFM/IDE类型硬盘的块设备. 第一个IDE驱动控制器上的主盘(主设备号3)是 hda ;从盘是 hdb. 第二个I ...
- python_97_类的继承2
# 经典类与新式类差别主要体现在多继承上 #多继承是从左到有 class People():#经典类 #class People(object):#新式类 def __init__(self,name ...
- mysql如何让自增id从1开始设置方法
有两种方式 第一种: 如果表中数据没有用.如果直接删除数据,自动增长ID还是不会从1开始的,可以利用“清空数据表”.这样自动增长ID也将会从1开始. 清空表的sql如下 truncate table ...
- web.xml 中 resource-ref 的注意事项
配置说明: web.xml 中配置 <resource-ref> <description>Employees Database for HR Applications< ...
- c3p0,dbcp和proxool
关于c3p0.dbcp和proxool,之类的比较,配置在网上有很多的文章,我这边就不浪费大家的时间了,主要讲下我用过这三个之后的体会. dbcp:框架以前使用的是dbcp,网上说,有很多BUG,至少 ...