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的结构,以及内核编程的方法. 至于真正的内核 ...
随机推荐
- C# 初始学习心情
当听说需要转做.net的时候.内心是忐忑不安的.因为突然从前端转向后端,几乎完全颠倒了...一个注重界面实现功能.一个注重逻辑的开发,然并卵,服从需求吧. 虽说公司需要你转.但是时间是不允许的,所以只 ...
- Android--View事件传递
Android--View事件传递 View事件传递首先要明白以下要素: 事件就是MotionEvent.该对象包含了传递的事件中的所有信息 事件的来源是Window(即PhoneWindow),包含 ...
- Java TCP通信
1.Socket原理 1)Socket简介 socket通常称作“套接字”,用于描述IP地址和端口号,是一个通信链的句柄.在Internet上的主机一般运行了多个服务软件,同时提供几种服务.每种服务都 ...
- 洛谷——普及练习场 普及组选手可冲刺训练,提高组选手亦可在此巩固基础。(Loading...)
简单的模拟 关卡2-1,6 道题 开始普及组的训练!所谓模拟,就是直接根据题意编写,思维难度简单. //T1 铺地毯 #include <cstdio> #define N 10005 i ...
- 剑指offer18 树的子结构
另一种写法 class Solution { public: bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) { bool result = f ...
- 【转】pDc->SelectObject(pOldBrush)恢复画刷
请看下面的代码: CDC *pDc=new CClientDC(this); CBrush brush; brush.CreateSolidBrush(RGB(0,255,0)); CBrush * ...
- Mac brew 安装amp环境
|首先加入Homebrew官方的几个软件源 $ brew tap homebrew/dupes $ brew tap homebrew/versions $ brew tap homebrew/php ...
- spring boot自动配置实现
自从用了spring boot,都忘记spring mvc中的xml配置是个什么东西了,再也回不去.为啥spring boot这么好用呢, 约定大于配置的设计初衷, 让我们只知道维护好applicat ...
- jenkins 全局工具配置
- 转载:将画布(canvas)图像保存成本地图片的方法
之前我曾介绍过如何将HTML5画布(canvas)内容转变成图片形式,方法十分简单.但后来我发现只将canvas内容转变成图片输出还不够,如何能将转变后的图片保存到本地呢? 其实,这个方法也是非常简单 ...