zoukankan      html  css  js  c++  java
  • 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:
  • 相关阅读:
    C++ 将对象写入文件 并读取
    IronPython fail to add reference to WebDriver.dll
    How to Capture and Decrypt Lync Server 2010 TLS Traffic Using Microsoft Tools
    .net code injection
    数学系学生应该知道的十个学术网站
    Difference Between Currency Swap and FX Swap
    Swift开源parser
    谈谈我对证券公司一些部门的理解(前、中、后台)[z]
    JDK8记FullGC时候Metaspace内存不会被垃圾回收
    JVM源码分析之JDK8下的僵尸(无法回收)类加载器[z]
  • 原文地址:https://www.cnblogs.com/dongguolei/p/7896283.html
Copyright © 2011-2022 走看看