linux内核代码注释 赵炯 第三章引导启动程序

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