1. 程式人生 > >自己寫操作系統---bootsector篇

自己寫操作系統---bootsector篇

ase 圖書 自制操作系統 ber 中斷 不錯 end vds ads

其實博主本來想在寒假自己寫一個OSkernal的,高高興興的影印了本《一個操作系統的實現》。

然後又去圖書館借來《30天自制操作系統》和《X86/X64體系探索編程》,結果還是被自己的懶惰給打敗了。。。

原本我感覺自制力還不錯的,好歹春節前也看了很多東西,但是過了一個春節就懶散了。。

當然也有一部分原因是因為《30天》寫的實在是太亂了。。缺少一個理論的上的指導和概括,看的雲裏霧裏。

再就是匯編。。。博主原來只學過8086和AT&T匯編啊。。。這下又來個nasm匯編。。這學期還開了個ARM匯編。。Orz。。。

不過nasm匯編真的是很好用,它還有類似c++默認構造的宏指令,很強大啊!

當然了,如果我不是一個喜歡深究的人,也可以用《30天》提供的工具也能很快的寫出來。但我畢竟還是有點追求的。。

廢話了這麽多,開始進入主題吧。。

首先,bootsector是個什麽東西呢?其實就是個引導的作用,引導到bootloader或者是操作系統上。

註意,bootsector不是雙系統的那種引導,而是在它之前的程序。

那麽bootsector程序是如何發揮作用的呢?這得從計算機的開機流程講起。

還記得學校上的操作系統教材上面說,計算機開機加電直接就去讀取硬盤上的操作系統。(但其實漏掉了好些東西啊!!國產教材誤人子弟啊!!!!)

其實一開機,並不是直接讀硬盤,而是從主板的BIOS啟動。

(BIOS不知道可以自己百度,它還把一些自帶的中斷加載到了內存中)

上電後,BIOS的ROM中程序通過硬件加載到內存。

根據BIOS的ROM中的程序,來檢測相關硬件是否安裝正確。然後才是尋找操作系統。

完整流程如下:

bios->bootsector->bootloader->kernel(後面兩個以後再說)

這樣就有問題了,BIOS怎麽知道操作系統放在哪呢?

這需要了解通用計算機所遵循的規範了,bios只從硬盤的第一個扇區讀取並加載程序。

扇區又是什麽呢?這裏我簡單的帶著你聯想一下.

由於原來32位地址總線只能尋址4G的大小。那麽硬盤不斷發展,64位總線還沒出現,但是硬盤大小超過4g。

所以多出來的部分就沒有用了!但是工程師很聰明,所以就讓每個地址存儲的內容更多吧!(自己回顧組成原理)

所以,硬盤就出現了所謂的扇區!一般一個扇區的大小為512b。4G*512b=2t的樣子。

這樣來算,現在的發展已經夠用了,以後換到64位系統就不用擔心地址不夠了。

回到正題。由於BIOS只能自動讀一個扇區,512b的大小。

這麽點大小肯定裝不下操作系統~所以只好用bootsector來轉讓計算機使用的權力了。

於是我們就清楚了bootsector的作用----讀入硬盤上的其他程序,並將cpu交給它。

下面是我寫的bootsector。由於沒有文件系統也不想用fat12,所以讀取loader的位置是我自己隨便定的。

如果fat12那一段不註釋的話,U盤就可以被識別了,但是U盤中的內容都是亂的~~~

linux下可以用dd命令直接寫到你的U盤中去。

dd if=$(OBOOT) of=$(DEVICE) bs=512 count=1 conv=notrunc
OBOOT表示生成文件,直接用nasm匯編生成.bin文件即可。

DEVICE就是你U盤在linux下的路徑了。

然後就可以通過U盤啟動,來執行你的bootsector了~

  1. %include "boot.inc"
  2. %ifdef DEBUG
  3. org 0100h ;07c00h 0100
  4. %else
  5. org 07c00h
  6. %endif
  7. jmp short LABEL_START
  8. nop
  9. ;head of FAT12
  10. ; BS_OEMName DB ‘meiboyu ‘ ; OEM String, 必須 8 個字節
  11. ; BPB_BytsPerSec DW 512 ; 每扇區字節數
  12. ; BPB_SecPerClus DB 1 ; 每簇多少扇區
  13. ; BPB_RsvdSecCnt DW 1 ; Boot 記錄占用多少扇區
  14. ; BPB_NumFATs DB 2 ; 共有多少 FAT 表
  15. ; BPB_RootEntCnt DW 224 ; 根目錄文件數最大值
  16. ; BPB_TotSec16 DW 2880 ; 邏輯扇區總數
  17. ; BPB_Media DB 0xF0 ; 媒體描述符
  18. ; BPB_FATSz16 DW 9 ; 每FAT扇區數
  19. ; BPB_SecPerTrk DW 18 ; 每磁道扇區數
  20. ; BPB_NumHeads DW 2 ; 磁頭數(面數)
  21. ; BPB_HiddSec DD 0 ; 隱藏扇區數
  22. ; BPB_TotSec32 DD 0 ; wTotalSectorCount為0時這個值記錄扇區數
  23. ; BS_DrvNum DB 0 ; 中斷 13 的驅動器號
  24. ; BS_Reserved1 DB 0 ; 未使用
  25. ; BS_BootSig DB 29h ; 擴展引導標記 (29h)
  26. ; BS_VolID DD 0 ; 卷序列號
  27. ; BS_VolLab DB ‘MOS by mby ‘; 卷標, 必須 11 個字節
  28. ; BS_FileSysType DB ‘FAT12 ‘ ; 文件系統類型, 必須 8個字節
  29. times 18 db 0
  30. LABEL_START:
  31. mov ax, cs
  32. mov ds, ax
  33. mov es, ax ;make all pointer point null place
  34. mov dx,0
  35. mov ax,BootMessage
  36. mov cx,BMlength
  37. mov dh,0
  38. call showStr ;show string function
  39. call Loader ;Loader getting loading
  40. jmp fin ;while(1)
  41. Loader:
  42. mov ax,4200h
  43. mov dl,0x80
  44. mov cx,0
  45. mov ds,cx
  46. mov si,DAP
  47. int 0x13
  48. jc LoaderError
  49. mov ax,0 ;clean es register
  50. mov es,ax
  51. mov dx,0
  52. mov ax,LSuccess
  53. mov cx,LSlength
  54. mov dh,1
  55. call showStr
  56. jmp BaseOffLoader:SetOffLoader ;jump to Loader !
  57. LoaderError:
  58. mov ax,0
  59. mov es,ax
  60. mov ax,LError
  61. mov cx,LElength
  62. mov dh,1
  63. call showStr
  64. fin:
  65. hlt
  66. jmp fin
  67. showStr:
  68. mov bp,ax
  69. mov ax,01301h
  70. mov bx,000Fh
  71. mov dl,0
  72. int 10h
  73. ret
  74. LSuccess: db "Loader OK!"
  75. LSlength equ $-LSuccess
  76. LError: db "Booting Loader get wrong!"
  77. LElength equ $-LError
  78. BootMessage: db "Boot Sector Start!"
  79. BMlength equ $-BootMessage
  80. DAP:
  81. db 16 ;packet size
  82. db 0 ;must 0
  83. dw 100 ;number of block need to read
  84. dw 0 ;the offset
  85. dw 8000h ;the segment address
  86. dw 1h ;start block
  87. dw 0
  88. dw 0
  89. dw 0
  90. times 510-($-$$) db 0
  91. dw 0xaa55

程序短,所以懶得用宏了。。這樣對於新手看著也方便。

具體匯編的內容很簡單,我就不講了,這裏說一下我寫這個遇到的個坑。。。

使用BIOS的int 13h+al=02h的時候,在真機上是無法加載loader的!!軟盤跟U盤還是有區別的!

我看《一個操作系統 的實現》和《30天》的時候,就是這裏。。他們都使用的是軟盤,但是用U盤就有問題!!

於是發現要用擴展BIOS中斷,詳細的可以去google擴展BIOS中斷。(我記得我是在wiki上看到的,但是現在找不到了)

當然看我的代碼也可以~

bootsector就介紹到這裏了。過幾天我再來寫loader的部分~

恩。。現在正在寫,並且寫圖形化界面的時候又遇到坑了。。

PS:

裝過win+linux雙系統的知道,得先裝windows再裝linux。

我估計就是windows直接重寫bootsetor,然後直接引導到他的loader了,而linux的引導程序grub會識別原來的系統。

自己寫操作系統---bootsector篇