1. 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)代码注释

  1. !
  2. ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
  3. ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
  4. ! versions of linux
  5. !
  6. SYSSIZE = 0x3000
  7. !
  8. ! bootsect.s (C) 1991 Linus Torvalds
  9. !
  10. ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
  11. ! iself out of the way to address 0x90000, and jumps there.
  12. !
  13. ! It then loads 'setup' directly after itself (0x90200), and the system
  14. ! at 0x10000, using BIOS interrupts.
  15. !
  16. ! NOTE! currently system is at most 8*65536 bytes long. This should be no
  17. ! problem, even in the future. I want to keep it simple. This 512 kB
  18. ! kernel size should be enough, especially as this doesn't contain the
  19. ! buffer cache as in minix
  20. !
  21. ! The loader has been made as simple as possible, and continuos
  22. ! read errors will result in a unbreakable loop. Reboot by hand. It
  23. ! loads pretty fast by getting whole sectors at a time whenever possible.
  24. .globl begtext, begdata, begbss, endtext, enddata, endbss //段定义
  25. .text
  26. begtext:
  27. .data
  28. begdata:
  29. .bss
  30. begbss:
  31. .text
  32. SETUPLEN = 4 ! nr of setup-sectors 扇区数量    定义
  33. BOOTSEG  = 0x07c0 ! original address of boot-sector 开始段
  34. INITSEG  = 0x9000 ! we move boot here - out of the way 初始段
  35. SETUPSEG = 0x9020 ! setup starts here setup程序所在段
  36. SYSSEG   = 0x1000 ! system loaded at 0x10000 (65536). 系统模块段
  37. ENDSEG   = SYSSEG + SYSSIZE ! where to stop loading 停止加载的位置
  38. ! ROOT_DEV: 0x000 - same type of floppy as boot. 软盘类型
  39. ! 0x301 - first partition on first drive etc 硬盘类型
  40. ROOT_DEV = 0x306 启动盘设备类型
  41. entry start 程序入口地址
  42. start:
  43. mov ax,#BOOTSEG
  44. mov ds,ax ds段基地址
  45. mov ax,#INITSEG
  46. mov es,ax es段基地址
  47. mov cx,#256
  48. sub si,si si和di均清0
  49. sub di,di
  50. rep 循环256次    共512个字节的内容
  51. movw 传送字 将bootseg段的代码移动到es指向的initseg段
  52. jmpi go,INITSEG 跳转到initseg段的go标号位置
  53. go: mov ax,cs cs   ds    es指向相同的位置
  54. mov ds,ax
  55. mov es,ax
  56. ! put stack at 0x9ff00.
  57. mov ss,ax ss堆栈段基址位0x9ff00
  58. mov sp,#0xFF00 ! arbitrary value >>512 sp指针的位置调整ss:sp=0x90000:ff00位置  此时位空栈        以上为初始化
  59. ! load the setup-sectors directly after the bootblock.
  60. ! Note that 'es' is already set up.
  61. load_setup: 加载setup程序
  62. mov dx,#0x0000 ! drive 0, head 0 驱动器0   磁头0   dh磁头   dl驱动器号
  63. mov cx,#0x0002 ! sector 2, track 0 扇区2 磁道0      ch磁道号  柱面号    cl开始扇区
  64. mov bx,#0x0200 ! address = 512, in INITSEG 512个字节
  65. mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors ah=2  功能号为2        al=4 扇区数量
  66. int 0x13 ! read it 中断13  读磁盘的功能     读如到es:bx  数据缓冲区
  67. jnc ok_load_setup ! ok - continue 判断cf标志位   cf=0正常   cf=1 出错
  68. mov dx,#0x0000
  69. mov ax,#0x0000 ! reset the diskette 重设寄存器
  70. int 0x13 调用中断13号  复位磁盘
  71. j load_setup 跳转load_setup
  72. ok_load_setup:
  73. ! Get disk drive parameters, specifically nr of sectors/track 以下为获取磁盘驱动器的参数
  74. mov dl,#0x00
  75. mov ax,#0x0800 ! AH=8 is get drive parameters
  76. int 0x13 中断13   ah为8调用获取磁盘参数
  77. mov ch,#0x00 ch清0
  78. seg cs 找cs段执行指令   下一条指令在cs段
  79. mov sectors,cx 保存每磁道扇区数
  80. mov ax,#INITSEG es指向0x9000的段处
  81. mov es,ax
  82. ! Print some inane message
  83. mov ah,#0x03 ! read cursor pos
  84. xor bh,bh
  85. int 0x10 中断  读取光标位置
  86. mov cx,#24 共24个字符
  87. mov bx,#0x0007 ! page 0, attribute 7 (normal) bh为页    bl为属性
  88. mov bp,#msg1 es:bp指向要显示的字符串
  89. mov ax,#0x1301 ! write string, move cursor ah为13 显示字符串功能,  al为1表示写方式
  90. int 0x10 中断调用
  91. ! ok, we've written the message, now
  92. ! we want to load the system (at 0x10000)
  93. mov ax,#SYSSEG es指向0x1000处
  94. mov es,ax ! segment of 0x010000
  95. call read_it 调用子程序    134行
  96. call kill_motor 关闭马达 214行
  97. ! After that we check which root-device to use. If the device is
  98. ! defined (!= 0), nothing is done and the given device is used.
  99. ! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
  100. ! on the number of sectors that the BIOS reports currently.
  101. seg cs
  102. mov ax,root_dev
  103. cmp ax,#0
  104. jne root_defined
  105. seg cs
  106. mov bx,sectors
  107. mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
  108. cmp bx,#15
  109. je root_defined
  110. mov ax,#0x021c ! /dev/PS0 - 1.44Mb
  111. cmp bx,#18
  112. je root_defined
  113. undef_root:
  114. jmp undef_root
  115. root_defined:
  116. seg cs
  117. mov root_dev,ax
  118. ! after that (everyting loaded), we jump to
  119. ! the setup-routine loaded directly after
  120. ! the bootblock:
  121. jmpi 0,SETUPSEG
  122. ! This routine loads the system at address 0x10000, making sure
  123. ! no 64kB boundaries are crossed. We try to load it as fast as
  124. ! possible, loading whole tracks whenever we can.
  125. !
  126. ! in: es - starting address segment (normally 0x1000)
  127. !
  128. sread: .word 1+SETUPLEN ! sectors read of current track 磁道中已经读取的扇区数  开始时已经读取1扇区   bootsect和setup程序所占的扇区数为setuplen
  129. head: .word 0 ! current head
  130. track: .word 0 ! current track
  131. read_it:
  132. mov ax,es
  133. test ax,#0x0fff es必须是64k边界   es实际指向的内存为0x10000共20位  相与的是高16位     数值结果不保存
  134. die: jne die ! es must be at 64kB boundary
  135. xor bx,bx ! bx is starting address within segment      bx指向段基地址
  136. rp_read:
  137. mov ax,es
  138. cmp ax,#ENDSEG ! have we loaded all yet?    判断es是否等于停止加载的段地址
  139. jb ok1_read 小于时跳转到ok1_read标号处继续执行,否则返回
  140. ret
  141. ok1_read:
  142. seg cs cs段的指令执行
  143. mov ax,sectors 取每磁道扇区数
  144. sub ax,sread ax-sread  等于未读取的扇区数  结果送ax
  145. mov cx,ax
  146. shl cx,#9 左移9位  相当于乘以512  结果为未读扇区的字节数
  147. add cx,bx 加上bx(段内偏移值)   此次读操作后段内读入字节数
  148. jnc ok2_read cf标志位判断   是否有进位  如果不等于1  则跳转,即没有超过64k
  149. je ok2_read 等于64k则跳转    156行处
  150. xor ax,ax 超过64k   即加上此次将读磁道上所有未读扇区时会超过64k ,则ax清0
  151. sub ax,bx ax-bx  计算此次能读入的字节数    64k-bx(段内读偏移)
  152. shr ax,#9 再次将字节数转换成扇区数    右移9位 相当于除以512
  153. ok2_read:
  154. call read_track 调用read_track
  155. mov cx,ax
  156. add ax,sread
  157. seg cs
  158. cmp ax,sectors
  159. jne ok3_read
  160. mov ax,#1
  161. sub ax,head
  162. jne ok4_read
  163. inc track
  164. ok4_read:
  165. mov head,ax
  166. xor ax,ax
  167. ok3_read:
  168. mov sread,ax
  169. shl cx,#9
  170. add bx,cx
  171. jnc rp_read
  172. mov ax,es
  173. add ax,#0x1000
  174. mov es,ax
  175. xor bx,bx
  176. jmp rp_read
  177. read_track:
  178. push ax
  179. push bx
  180. push cx
  181. push dx
  182. mov dx,track
  183. mov cx,sread
  184. inc cx
  185. mov ch,dl
  186. mov dx,head
  187. mov dh,dl
  188. mov dl,#0
  189. and dx,#0x0100
  190. mov ah,#2
  191. int 0x13
  192. jc bad_rt
  193. pop dx
  194. pop cx
  195. pop bx
  196. pop ax
  197. ret
  198. bad_rt: mov ax,#0
  199. mov dx,#0
  200. int 0x13
  201. pop dx
  202. pop cx
  203. pop bx
  204. pop ax
  205. jmp read_track
  206. /*
  207. * This procedure turns off the floppy drive motor, so
  208. * that we enter the kernel in a known state, and
  209. * don't have to worry about it later.
  210. */
  211. kill_motor:
  212. push dx
  213. mov dx,#0x3f2
  214. mov al,#0
  215. outb
  216. pop dx
  217. ret
  218. sectors:
  219. .word 0
  220. msg1:
  221. .byte 13,10
  222. .ascii "Loading system ..."
  223. .byte 13,10,13,10
  224. .org 508
  225. root_dev:
  226. .word ROOT_DEV
  227. boot_flag:
  228. .word 0xAA55
  229. .text
  230. endtext:
  231. .data
  232. enddata:
  233. .bss
  234. endbss:

linux内核代码注释 赵炯 第三章引导启动程序的更多相关文章

  1. 《Linux内核设计与实现》第三章学习笔记

    第三章  进程管理 姓名:王玮怡  学号:20135116 一.进程 1.进程的含义 进程是处于执行期的程序以及相关资源的总称,程序本身并不是进程,实际上就是正在执行的代码的实时结果.Linux内核通 ...

  2. Linux内核分析 读书笔记 (第三章)

    第三章 进程管理 3.1 进程 1.进程: 进程就是处于执行期的程序. 进程就是正在执行的程序代码的实时结果. 进程是处于执行期的程序以及相关的资源的总称. 进程包括代码段和其他资源. 2.线程:执行 ...

  3. linux及安全《Linux内核设计与实现》第三章——20135227黄晓妍

    第三章 (由于linux不区分进程和线程,所以它们在linux中被称为task,也叫任务) 总结:本章主要包括进程以及线程的概念和定义,Linux内核如何管理每个进程,他们在内核中如何被列举,如何创建 ...

  4. 《Linux内核设计与实现》第三章读书笔记

    一.进程(任务)描述 1.进程是处于执行期的程序:除了可执行程序代码,还包括打开的文件.挂起的信号.内核内部数据.一个或者多个执行线程等多种资源 线程是在进程活动中的对象:内核调度的对象是线程而不是进 ...

  5. 《Linux内核设计与实现》 第三章学习笔记

    一.进程 1.进程就是处于执行期的程序(目标码存放在某种存储介质上).但进程并不仅仅局限于一段可执行程序代码,通常进程还要包含其他资源.执行线程,简称线程(thread),是在进程中活动的对象. 2. ...

  6. 《linux内核设计与实现》第三章

    1.进程 进程就是正在执行的程序代码的实时结果,不仅包含可执行代码,还包括其他资源,比如:打开的文件,挂起的信号,内核内部数据结构,处理器状态,一个或多个具有内存映射的内存地址空间及一个或多个执行线程 ...

  7. 【读书笔记】Linux内核设计与实现(第三章)

    3.1 进程 处于执行期的程序. 进程就是正在执行的程序代码的实时结果.内核需要有效而又透明地管理所有细节. 执行线程(简称线程):在进程中活动的对象.每个线程都拥有一个独立的程序计数器.进程栈和一组 ...

  8. 《Linux内核》课本读书笔记 第三章

  9. 第三次阅读赵炯博士的《linux内核代码完全注释》:序

    这是我第三次阅读linux内核代码完全注释了,当然前两次也没有读完,第一次读到第五章,第二次第七章. 所以说,赵炯博士对我最大的帮助时介绍了intel386的结构,以及内核编程的方法. 至于真正的内核 ...

随机推荐

  1. C# 初始学习心情

    当听说需要转做.net的时候.内心是忐忑不安的.因为突然从前端转向后端,几乎完全颠倒了...一个注重界面实现功能.一个注重逻辑的开发,然并卵,服从需求吧. 虽说公司需要你转.但是时间是不允许的,所以只 ...

  2. Android--View事件传递

    Android--View事件传递 View事件传递首先要明白以下要素: 事件就是MotionEvent.该对象包含了传递的事件中的所有信息 事件的来源是Window(即PhoneWindow),包含 ...

  3. Java TCP通信

    1.Socket原理 1)Socket简介 socket通常称作“套接字”,用于描述IP地址和端口号,是一个通信链的句柄.在Internet上的主机一般运行了多个服务软件,同时提供几种服务.每种服务都 ...

  4. 洛谷——普及练习场 普及组选手可冲刺训练,提高组选手亦可在此巩固基础。(Loading...)

    简单的模拟 关卡2-1,6 道题 开始普及组的训练!所谓模拟,就是直接根据题意编写,思维难度简单. //T1 铺地毯 #include <cstdio> #define N 10005 i ...

  5. 剑指offer18 树的子结构

    另一种写法 class Solution { public: bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) { bool result = f ...

  6. 【转】pDc->SelectObject(pOldBrush)恢复画刷

    请看下面的代码:  CDC *pDc=new CClientDC(this); CBrush brush; brush.CreateSolidBrush(RGB(0,255,0)); CBrush * ...

  7. Mac brew 安装amp环境

    |首先加入Homebrew官方的几个软件源 $ brew tap homebrew/dupes $ brew tap homebrew/versions $ brew tap homebrew/php ...

  8. spring boot自动配置实现

    自从用了spring boot,都忘记spring mvc中的xml配置是个什么东西了,再也回不去.为啥spring boot这么好用呢, 约定大于配置的设计初衷, 让我们只知道维护好applicat ...

  9. jenkins 全局工具配置

  10. 转载:将画布(canvas)图像保存成本地图片的方法

    之前我曾介绍过如何将HTML5画布(canvas)内容转变成图片形式,方法十分简单.但后来我发现只将canvas内容转变成图片输出还不够,如何能将转变后的图片保存到本地呢? 其实,这个方法也是非常简单 ...