linuxlinux0.11源码学习——bootsect.s学习
由于一直想写一个自己的操作系统,网上推荐了《linux内核完全注释》。自学了一个星期,感觉这本书还是很好的,同时写下关于内核代码的理解,如果有什么不对的对方,欢迎大家一起来交流。
在内核引导启动程序中,有3个文件,bootsec.s,setup.s head.s。关于这3个源代码,网上有很多人都有详细的解释,但是有很多人的文章中都是对每行代码的解释,但是关于整个代码的整体框架没有很多的解释。在这里我想提出自己对代码的理解,我不会每行都解释,只是对很重要的部分做出自己的理解。
关于bootsec.s主要做了如下的几件事:
- 由于PC开机后,BIOS将可移动的设备的第一个扇区,读入到了0x7c00处,总共512B,bootsec.s就在这里,它将自己移到了ox9000处来执行;
- 初始化堆栈;关于这个堆栈我对它的理解就是在后面的程序,比如read_track中就用到了pop和push之类的指令,因此在这设置了‘
- 将setup.s的模块装载在bootsec.s的后面;
- 获取驱动器的参数,这里应该是值软盘,主要获取到每个磁道的扇区数量;
- 在屏幕中输出“loading system.....”,然后装载system模块即内核模块;
- 确定根文件系统设备;
- 段间跳转,到setup.s中执行;
下面是我对bootsec.s中部分代码的理解。
bootsec.s代码移动到ox9000中
[html] view plain copy- mov ax,#BOOTSEG
- mov ds,ax
- mov ax,#INITSEG
- mov es,ax
- mov cx,#256
- sub si,si
- sub di,di
- rep
- movsw
在这里主要是提醒大家,关于cx的值,由于是要移动一个扇区的数据,一个扇区的大小是512B,这里的cx=256,但是movsw表示移动两个B,所以256*2=512B,这里大家会忽略,没注意;
关于load_setup
[html] view plain copy- mov dx,#0x0000
- mov cx,#0x0002
- mov bx,#0x0200
- mov ax,#0200+SETUPLEN
- int ox13
仔细看int 0x13这个中断的各个参数,这里比较重要的是es:bx 将指向setup模块的在内存中的位置。在移动bootsec.s的代码最后有一个jmpi go,INITSEG这个指令,此时的cs=0x900不再时0x7c00了,es=cs,于是es:bx指向了0x900:0200处,从而实现了装载setup模块的功能。
关于ok_load_setup
[html] view plain copy- seg cs
- mov sectors,cx
这里主要是来谈谈这两条指令。从代码的第241行中可以看出sectors是个标量指向一个word长的地址。seg cs表明了sectors的段地址是cs,而不是ds。而且seg cs 的作用范围只有下一行,不会延生到其他地方。
最后介绍这篇文章中最重要的read_it
[html] view plain copy- read_it:
- mov ax,es
- test ax,#0x0fff
- die: jne die ! es must be at 64kB boundary
- xor bx,bx ! bx is starting address within segment
- rp_read:
- mov ax,es
- cmp ax,#ENDSEG ! have we loaded all yet?
- jb ok1_read
- ret
- ok1_read:
- seg cs
- mov ax,sectors
- sub ax,sread
- mov cx,ax
- shl cx,#9
- add cx,bx
- jnc ok2_read
- je ok2_read
- xor ax,ax
- sub ax,bx
- shr ax,#9
- ok2_read:
- call 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
不知道大家在读这段代码的时候是怎么理解的,反正我理解了很长时间,不知道它到底想干什么。网上很多都是注释了每一行,但是没有解释总的在干什么,整体的流程是什么。
标量间代码作用
- ok1_read:主要的功能是确定了ax的值,其实严格的说是确定了al的值,因为al的值是代表了要读取的扇区的值,关于最后的几行代码
[html] view plain copy
- xor ax,ax
- sub ax,bx
- shr ax,#9
这几行代码是我当时极度不能理解的因为当时我认为ax=0,bx=0,最后不都是0吗?:),我想说这几行代码是以后执行的,到时后bx的值不再是0,而是代表了一个段内读取了的数据,sub是不带进位的0-bx正好是64k-段内已读的数据(不得不佩服linus的基本功),从而得到了段内剩余的空间,从而可以求出还可以读取最大的扇区数。
- ok2_read:调用了read_track(),read_track()的功能其实可以看成read_track(ax),根据ax,主要是al来确定一个磁道内从哪个扇区开始读数据,从而读取一个磁道的数据;然后ax=read_track(ax)(伪代码而已),ax表示读取的扇区的值,然后再加上已读的扇区数后比较是否等于每个磁道的扇区数,如果不等,则调用ok3_read(),否则读取下一个磁头1,(软盘有两个磁头,0和1,这和硬盘不一样,硬盘磁头比较多)
- ok4_read:这里为什么不从ok3_read写起呢,主要是因为linus的代码能力的厉害之处,大家慢慢也会懂的,只可意会。ok_read4的主要的功能是重新赋值磁头和ax即扇区的起始地址。
- ok3_read:主要是确定了bx的值和es的值。
[html] view plain copy
- 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
这里add bx,cx 是确定了bx的值,即段内已经读取的数据大小,如果bx没有溢出即超过0xffff,则跳转到开始的循环,否则段基址es+=0x1000,再从新循环。
整个代码流程
接下了主要讲一下关于我对这段代码的理解。由于软盘只有两个磁头0和1,且只有18个扇区,每个扇区的大小是512B从而代码开始处的流程应该是如下的
- 在ok1_read中从0磁头读取的数目最多(18-6)*512B,不会溢出,则会进入到ok2_read()中;如果bx不等于0,且数值比较接近0xffff时会溢出,则却确定该段内剩余的地址可以读取最大的扇区数;
- 到ok2_read中,从0磁头读取从能够ax开始的整个磁道剩余的扇区数,cx=读取的扇区数,在加上已读的扇区数确定是否全部读完,若是则下一步,否则到4;
- 到ok4_read,磁头变成了1,(只有两个磁头,如果原磁头是1,则增加磁道track),ax=0。
- 到ok3_read中,此时ok3_read的操作是针对下一次循环的,根据这一次的循环设置下一次循环的一些变量,bx=段内已经读取的数据的大小,如果超出64k则增加段基址,由于add是无进位的(这里又体现了linus的高明了);
- 从新返回到1,执行循环,知道es的值>ENDSEG;
到这可以理解为什么我要先介绍ok4_read了,而不是ok3_read了,如果在源代码中把ok3_read放在ok4_read之前那么代码会多加几个jmp命令,虽然便于我们理解,但是代码长度变长了,原来的代码体现了代码的魅力。
转载的时候请注明出处。
linuxlinux0.11源码学习——bootsect.s学习的更多相关文章
- 曹工说Spring Boot源码(26)-- 学习字节码也太难了,实在不能忍受了,写了个小小的字节码执行引擎
曹工说Spring Boot源码(26)-- 学习字节码也太难了,实在不能忍受了,写了个小小的字节码执行引擎 写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean De ...
- JDK1.8源码分析01之学习建议(可以延伸其他源码学习)
序言:目前有个计划就是准备看一下源码,来提升自己的技术实力.同时现在好多面试官都喜欢问源码,问你是否读过JDK源码等等? 针对如何阅读源码,也请教了我的老师.下面就先来看看老师的回答,也许会有帮助呢. ...
- jQuery1.11源码分析(1)-----Sizzle源码概览[原创]
最近在啃jQuery1.11源码,上来就遇到Sizzle这个jQuery的大核心,虽然已经清楚了Sizzle的用途,先绕过去也没事,但明知山有虎偏向虎山行才是我们要做的. 本文面向的阅读对象:正在学习 ...
- Linux 0.11源码阅读笔记-中断过程
Linux 0.11源码阅读笔记-中断过程 是什么中断 中断发生时,计算机会停止当前运行的程序,转而执行中断处理程序,然后再返回原被中断的程序继续运行.中断包括硬件中断和软件中断,硬中断是由外设自动产 ...
- Linux 0.11源码阅读笔记-总览
Linux 0.11源码阅读笔记-总览 阅读源码的目的 加深对Linux操作系统的了解,了解Linux操作系统基本架构,熟悉进程管理.内存管理等主要模块知识. 通过阅读教复杂的代码,锻炼自己复杂项目代 ...
- Linux 0.11源码阅读笔记-文件管理
Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件. 磁盘分区 生磁盘可以被分区,分区中可以安装文件系统, ...
- 框架源码系列五:学习源码的方法(学习源码的目的、 学习源码的方法、Eclipse里面查看源码的常用快捷键和方法)
一. 学习源码的目的 1. 为了扩展和调优:掌握框架的工作流程和原理 2. 为了提升自己的编程技能:学习他人的设计思想.编程技巧 二. 学习源码的方法 方法一: 1)掌握研究的对象和研究对象的核心概念 ...
- 【整站源码分享】分享一个JFinal3.4开发的整站源码,适合新手学习
分享这个源码是14年开发上线的<威海创业者>站点的全套整站源码,前后端都在一个包里.当时开发使用的是JFinal1.4,最近改成了JFinal3.4.使用的JSP做的页面.有一定的参考价值 ...
- REDIS源码中一些值得学习的技术细节01
redis.c/exitFromChild函数: void exitFromChild(int retcode) { #ifdef COVERAGE_TEST exit(retcode); #else ...
随机推荐
- 零基础逆向工程20_PE结构04_任意节空白区_新增节_扩大节添加代码
向代码节添加代码实现 作者经过一周不断的失败,再思考以及无数次调试终于实现. 思路:八个步骤 1. 文件拷到文件缓冲区(FileBuffer) //图示见(零基础逆向工程18之PE加载过程) 2. 文 ...
- JDBC事务--软件开发三层架构--ThreadLocal
JDBC事务--软件开发三层架构--ThreadLocal 一.JDBC事务 1.概述: 事务是指逻辑上的一组操作!这一组操作,通常认为是一个整体,不可拆分! 特点:同生共死;事务内的这一组操作要么全 ...
- filter和map的使 使得数组对象变数组
let UnitList = this.paytypeData.filter( item => item.CheckBox === true ).map(axis => axis.Unit ...
- python爬虫之路——变量和变量类型
变量类型: ①单值:int ②多值:数组 ③复杂:类 变量类型:就是变量的数据结构,表示这个变量所代表的内容的格式是怎样的. (多值)四种基本数据结构: 列表,字典,元组,集合 列表: ①元素可变, ...
- 如何对ABAP SE80 workbench做增强
流程如下: 要获取更多Jerry的原创文章,请关注公众号"汪子熙":
- UVA 1616 Caravan Robbers 商队抢劫者(二分)
x越大越难满足条件,二分,每次贪心的选区间判断是否合法.此题精度要求很高需要用long double,结果要输出分数,那么就枚举一下分母,然后求出分子,在判断一下和原来的数的误差. #include& ...
- 爬虫3_python2
# coding=utf-8 import urllib params=urllib.urlencode({'t':1,'eggs':2,'bacon':0})#现在大多数网站都是动态网页,需要你动态 ...
- 绘制方式和OpenGL枚举对应关系
绘制方式和OpenGL枚举对应关系 图元类型 OpenGL枚举量 点 GL_POINTS 线 GL_LINES 条带线 GL_LINE_STRIP 循环线 GL_LINE_LOOP 独立三角形 GL_ ...
- Mysql command line
show databasename; use databasename; show tables; desc tablename;
- fei33423 工作 职场 格言
对老板: 1. 老板不知道你做的事情(目标设定) 2. 老板要的是规划(对上报告), 自己给自己设定 金字塔四位下的目标,各种维度.如何细化. 2.1 明确老板期望 2.2 与老板达成共识 2.3 ...