`
film
  • 浏览: 225289 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

实现OS中BOOTLOADER过程,并进入保护模式的代码

 
阅读更多
  1. ;;;;;;;实现进入进入保护模式,简单实现gdt,还没实现idt,用fat格式,这样利于内核文件的扩展。编写好内核之后,
  2. ;;;;;;;;可以直接放到软盘的根目录下。不需要在用镜像文件写入磁盘。
  3. ;;;;;;;;内存分配,堆栈在8FFFF,内核在500H,目录文件名被读取到7E00,等待扩展保护模式中断,完善磁盘读文件过程
  4. [bits16]
  5. [org0x7c00];告诉编译器程序加载到7c00处
  6. CATALOGequ0x7E00;catalogloadedat0x7e00
  7. KERNELequ0x500;kernel.binloadedat0x500.
  8. jmpStart
  9. ;引导区文件系统数据
  10. ;----------------------------------------------------------------------------
  11. brOEMDB"T'sOS";0003h-引导程序的名字
  12. brBPSDW0x200;000Bh-每扇区的字节数512
  13. brSPCDB0x01;000Dh-每簇扇区数
  14. brResCountDW0x0001;000Eh-保留扇区数
  15. brFATsDB0x02;0010h-FAT备份数
  16. brRootEntriesDW0x00e0;0011h-根目录文件数
  17. brSectorCount
  18. DW2880;0013h-磁盘容量扇区数<32MB
  19. brMediaDB240;0015h-媒体描述符
  20. brSPFDW9;0016h-每FAT扇区数
  21. brSPHDW18;0018h-每磁道扇区数
  22. brHPCDW2;001Ah-盘面数
  23. brHiddenDD0;001Ch-隐藏扇区数
  24. brSectorsDD0;0020h-如果大于32m的扇区总数
  25. DB0;0024h-物理驱动器号
  26. DB0;0025h-系统保留
  27. DB29H;0026h-扩展扇区标记(包含29h)
  28. brSerialNumDD00000006H;0027h-卷ID
  29. brLabelDB'NONAME';002Bh-卷标
  30. brFSIDDB'FAT12';0036h-系统保留
  31. ;------------------------------------------------------------------------
  32. Start:
  33. movax,cs
  34. movds,ax
  35. moves,ax
  36. movax,0x8000;栈放在0x1F00段里,这里栈有问题(栈放在0x1F00段里,会覆盖掉中断程序。)!!!!!!!!!!!!!!!
  37. movss,ax
  38. movsp,0xffff;堆栈入口8FFFF
  39. callDispStr;调用显示字符串例程
  40. callLoadFile;把目录区读入到200的地方,bios
  41. callFindFile;在7E00的地方找kernel.bin,读出来放到500的地方,并显示读取成功
  42. callClrscr;先清屏
  43. ;=============================================
  44. ;SwitchPro建立GDT,进入保护模式
  45. ;=============================================
  46. SwitchPro;
  47. ;打开A20
  48. inal,92h
  49. oral,00000010b
  50. out92h,al
  51. ;end打开A20
  52. ;设置GDT
  53. cli
  54. ;movax,KERNEL;lgdt指令加载gdtr是以ds为数据段加载
  55. ;movds,ax
  56. ;leasi,[dwordgdtr]
  57. lgdt[gdtr]
  58. ;leasi,[dwordidtr]
  59. ;lidt[dwordgdtr]
  60. moveax,cr0
  61. oreax,1
  62. movcr0,eax
  63. jmpdwordselcode:0;进入保护模式,并且跳到下面的段中
  64. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;jmpKERNEL保护模式下,跳到kenel.bin开始执行内核.等待内核编码完成在实现
  65. [bits32]
  66. CODE32:
  67. sti
  68. moveax,codesel_gdt
  69. movebx,datasel_gdt
  70. movax,ProMessage
  71. movbp,ax
  72. movcx,ProMsglength
  73. ;callPrintMsg;保护模式中断有问题,需要修改这里,最好能利用实模式下的bios中断程序。
  74. ;===================
  75. movax,videosel;初始化gs,使其指向显示内存
  76. movgs,ax
  77. movword[gs:0],0x741;在保护模式下显示一个白色的字符A
  78. ;===================
  79. jmp$;到此停止!!!!!!!!!!!!!!!!!!!!!!!
  80. [bits16]
  81. ;===================================================================
  82. ;初始化gdtr和gdt
  83. ;===================================================================
  84. gdtr:
  85. dwgdt_end-gdt-1;gdt的长度--16位(800H)GDT界限gdtlimit=2048,256GDTentries
  86. ;这里应该是伪长度7,15,23,31,因为从0开始计算的
  87. ddgdt;gdt的物理地址--32位GDT基地址
  88. ;0x00007c930017!!!!!!!!
  89. gdt:
  90. gdt0:
  91. dw0,0,0,0;一定要为0
  92. codesel_gdt:
  93. dw0xffff;界限Limit值=0x100000*0x1000=4GB
  94. dwCODE32;0x0000;基地址=CODE32.!!!!!!!是不是最好设置从0开始?
  95. db0x00
  96. db0x9A;表示存在可执行可读代码段
  97. db0xCF;粒度以及32位代码1100=0XC
  98. db0x00
  99. datasel_gdt:
  100. dw0xffff;界限4GB
  101. dw0x0000;基地址
  102. db0x00
  103. db0x92;表示存在可读写数据段
  104. db0xCF;粒度以及数据锻大小4G,1100=0XC
  105. db0x00
  106. ;========================
  107. videoselequ$-gdt
  108. dw3999
  109. dw0x8000;基址是0xb8000
  110. db0x0b
  111. db0x92
  112. db0x00
  113. db0x00
  114. ;========================
  115. gdt_end:
  116. selcodeequcodesel_gdt-gdt;索引值1,2,3....
  117. seldataequdatasel_gdt-gdt
  118. ;=============================================
  119. ;DispStr显示boot已经启动!
  120. ;=============================================
  121. DispStr:
  122. movax,BootMessage
  123. movbp,ax;es:bp=串地址
  124. movcx,Msglength;cx=串长度
  125. callPrintMsg
  126. ret
  127. ;=============================================
  128. ;LoadFile把目录从软盘中读出来!
  129. ;=============================================
  130. LoadFile:
  131. movax,19;开始的扇区
  132. movbx,CATALOG;目录放在7E00H的地方!!!!!!!!!!!!!!!!!!!!!!!!!!!
  133. movcx,14;目录扇区个数
  134. loopreadsec:
  135. pushax
  136. pushbx
  137. pushcx
  138. callLBACHS;调用转换
  139. movdl,0;因为是a:所以为0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  140. movah,0x02;BIOS读取扇区命令
  141. moval,0x01;一个扇区
  142. int0x13;调用中断
  143. nop
  144. popcx
  145. popbx
  146. popax
  147. addbx,200
  148. incax
  149. looploopreadsec
  150. ret
  151. ;=============================================
  152. ;转换逻辑块访问为读取磁盘所使用的磁道,盘面,扇区
  153. ;相对扇区=(逻辑扇区/每磁道扇区数)+1
  154. ;相对盘面=(逻辑扇区/每磁道扇区数)MOD盘面数
  155. ;相对磁道=逻辑扇区/(每磁道扇区数*盘面数)
  156. ;=============================================
  157. LBACHS:
  158. xordx,dx;dx=0
  159. movcx,18
  160. divcx;div:ax/18->商:ax余数:dx
  161. incdl;sec;
  162. movcl,dl;sector
  163. xordx,dx;dx=0
  164. pushbx
  165. movbx,2
  166. divbx;ax/2->商:ax余数:dx
  167. popbx
  168. movch,al;track
  169. movdh,dl;head
  170. ret
  171. ;=============================================
  172. ;FindFile查找文件名,并且装到0x500,显示LoadKernel.binSuccess!
  173. ;=============================================
  174. FindFile:
  175. cld;地址自动增加
  176. movcx,224;根目录共有224个文件
  177. movdi,CATALOG;目录放在7E00H的地方!!!!!!!!!!!!!!!!!!!!!
  178. .l_findfile:
  179. pushcx
  180. leasi,[Kernel];?
  181. pushdi
  182. movcx,11;8+3=0xb文件名和后缀长度
  183. repecmpsb
  184. popdi
  185. jefindfile_ok
  186. adddi,32;开始找下1个文件
  187. popcx
  188. loop.l_findfile
  189. movax,LoadKerFail;失败
  190. movbp,ax;es:bp=串地址
  191. movcx,LoadKerFaillength;cx=串长度
  192. callPrintMsg
  193. ret
  194. findfile_ok:
  195. popcx
  196. adddi,26;取文件占用的第一个簇号,即起始簇
  197. movax,[di]
  198. addax,31;簇转成扇区
  199. movbx,KERNEL;文件放在0x500!!!!!!!!!!!!!!!!!!!!!!!!!!!
  200. callLBACHS;调用转换
  201. movdl,0;因为是a:所以为0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  202. movah,0x02;BIOS读取扇区命令
  203. moval,0x03;一个扇区,这里不应该只读一个扇区,应该根据文件大小来决定,等待修改!!!!!
  204. int0x13;调用中断,内核放在0x1e00!;在磁盘的位置?
  205. movax,LoadKerSuess;成功
  206. movbp,ax;es:bp=串地址
  207. movcx,LoadKerlength;cx=串长度
  208. callPrintMsg
  209. ret
  210. ;=============================================
  211. ;清屏
  212. ;=============================================
  213. Clrscr:
  214. movax,0x0600;使用中断10h的功能6,实现卷屏,如果al=0则清屏
  215. movcx,0x0000;清屏
  216. movdx,0x174f;卷屏至23,79
  217. movbh,0;使用颜色0来填充
  218. int0x10;调用10h中断
  219. ret
  220. ;=============================================
  221. ;显示信息
  222. ;=============================================
  223. PrintMsg:
  224. movax,01301h;ah=13,al=01h
  225. movbx,000ch;页号为0(bh=0)黑底红字(bl=0Ch,高亮)
  226. movdl,0
  227. movdh,BYTE[NoLine]
  228. int10h;10h号中断
  229. adddh,1
  230. movBYTE[NoLine],dh
  231. ret
  232. BootMessage:db"WelcometoT'sOS!",0x0D,0x0A
  233. Msglengthequ$-BootMessage
  234. DB0x00
  235. Kernel:db'KERNELBIN';8+3=11位;将来这里改成内核的文件名!!!!!!!!!!!!!
  236. LoadKerSuess:db'LoadKernel.binSuccess!',0x0D,0x0A
  237. LoadKerlengthequ$-LoadKerSuess
  238. DB0x00
  239. LoadKerFail:db'LoadKernel.binFail!',0x0D,0x0A
  240. LoadKerFaillengthequ$-LoadKerFail
  241. DB0x00
  242. ProMessage:db"I'mintheProMode!",0x0D,0x0A
  243. ProMsglengthequ$-ProMessage
  244. DB0x00
  245. NoLineDB0x00
  246. times510-($-$$)db0;填充剩下的空间,使生成的二进制代码恰好为512字节
  247. dw0xaa55;结束标志
  248. ;把这段代码用NASM编译一下:
  249. ;nasmboot.asm–oboot.bin
  250. ;应该把内核在pro模式下加载就对了!

版权声明:本文为博主原创文章,未经博主允许不得转载。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics