qq:992591601 歡迎交流ios
2016.04.03 2016.05.31 2016.06.29數據結構
這一章是有些複雜的,我不太懂做者爲何要把這麼多內容都放進一天。函數
1讀入了十個柱面工具
2從啓動區執行操做系統oop
3進入32位ui
4導入C語言spa
makefile的內容:操作系統
TOOLPATH = ../z_tools/ INCPATH = ../z_tools/haribote/ MAKE = $(TOOLPATH)make.exe -r NASK = $(TOOLPATH)nask.exe NASM = $(TOOLPATH)nasm.exe CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet GAS2NASK = $(TOOLPATH)gas2nask.exe -a OBJ2BIM = $(TOOLPATH)obj2bim.exe BIM2HRB = $(TOOLPATH)bim2hrb.exe RULEFILE = $(TOOLPATH)haribote/haribote.rul EDIMG = $(TOOLPATH)edimg.exe IMGTOL = $(TOOLPATH)imgtol.com COPY = copy DEL = del default : $(MAKE) img ipl.bin : ipl.asm Makefile $(NASM) ipl.asm -o ipl.bin main.bin : main.nas Makefile $(NASK) main.nas main.bin main.lst c_main.gas : c_main.c Makefile $(CC1) -o c_main.gas c_main.c c_main.nas : c_main.gas Makefile $(GAS2NASK) c_main.gas c_main.nas c_main.obj : c_main.nas Makefile $(NASK) c_main.nas c_main.obj c_main.lst assemblyFunc.obj : assemblyFunc.nas Makefile $(NASK) assemblyFunc.nas assemblyFunc.obj assemblyFunc.lst c_main.bim : c_main.obj assemblyFunc.obj Makefile $(OBJ2BIM) @$(RULEFILE) out:c_main.bim stack:3136k map:c_main.map \ c_main.obj assemblyFunc.obj # 3MB+64KB=3136KB c_main.hrb : c_main.bim Makefile $(BIM2HRB) c_main.bim c_main.hrb 0 haribote.sys : main.bin c_main.hrb Makefile copy /B main.bin+c_main.hrb haribote.sys haribote.img : ipl.bin haribote.sys Makefile $(EDIMG) imgin:../z_tools/fdimg0at.tek \ wbinimg src:ipl.bin len:512 from:0 to:0 \ copy from:haribote.sys to:@: \ imgout:haribote.img img : $(MAKE) haribote.img run : $(MAKE) img $(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin $(MAKE) -C ../z_tools/qemu install : $(MAKE) img $(IMGTOL) w a: haribote.img clean : -$(DEL) *.bin -$(DEL) *.lst -$(DEL) *.gas -$(DEL) *.obj -$(DEL) c_main.nas -$(DEL) c_main.map -$(DEL) c_main.bim -$(DEL) c_main.hrb -$(DEL) haribote.sys src_only : $(MAKE) clean -$(DEL) haribote.img
注意end.exe,在次日,做者提到:本身開發的磁盤映像管理工具end.exe,先讀入一個空白的磁盤映像文件,而後在開頭寫入ipl.bin的內容,最後將結果輸出爲名爲helloos.img的磁盤映像文件。code
這樣一來,邏輯上就很簡單了,用makefile,調用end.exe,將ipl10.nas和操做系統代碼,製成一個img文件。ipl10.nas是啓動區。最後操做系統的啓動是,在啓動區啓動。blog
而後咱們用工具觀察製成的img,會發現:
做者得出的結論:
通常向一個空軟盤保存文件時
(1)文件名會寫在0x002600之後的地方;
(2)文件內容會寫在0x004200之後的地方。
因此,要執行磁盤映像上位於0x004200號地址的程序,如今的程序是從啓動區開始,把磁盤上的內容裝載到內存0x8000號地址,因此磁盤0x4200處的內容就應該位於內存0x8000+0x4200=0xc200號地址。
因此從啓動區,啓動操做系統就只須要jmp到0xc200地址便可。
這兩張圖能夠簡單解釋原理(第二張是我畫的):
ipl.asm:
; author: 無 名 ; date: 2016.05.31 06.01 06.02 06.03 ; description: bootsector CYLS equ 10 org 07c00h ;如下,FAT12格式引導程序專用代碼 JMP entry DB 0x90 DB "HELLOIPL" ; name DW 512 ; size of a sector(must be 512byte) DB 1 ; size of a cluster(must be a sector) DW 1 ; FAT begin from 1st sector DB 2 ; FAT num DW 224 ; size of root directory DW 2880 ; size of disk(2880 sectors) DB 0xf0 ; type of disk DW 9 ; length of FAT(must be 9 sectors) DW 18 ; how many sectors with a track DW 2 ; head num DD 0 ; 不使用分區 DD 2880 ; size of disk(2880 sectors) DB 0,0,0x29 DD 0xffffffff DB "HELLO-OS " DB "FAT12 " RESB 18 ; 先空出18字節 entry: mov ax,0 mov ss,ax mov sp,0x7c00 mov ds,ax ;read disk mov ax,0x0820 mov es,ax mov ch,0 ;柱面0 mov dh,0 ;磁頭0 mov cl,2 ;扇區2 readloop: mov si,0 ;記錄失敗次數 retry: mov ah,0x02 ;ah=0x02:讀入磁盤 mov al,1 ;a sector mov bx,0 mov dl,0x00 ;A驅動器 int 0x13 ;調用磁盤bios jnc next ;沒出錯跳轉next add si,1 cmp si,5 ;if si > 5 errorへ jae error mov ah,0x00 mov dl,0x00 int 0x13 ;重置驅動器 jmp retry next: mov ax,es add ax,0x0020 mov es,ax add cl,1 cmp cl,18 jbe readloop ; if cl <= 18 readloopへ mov cl,1 add dh,1 cmp dh,2 jb readloop ; if dh < 2 readloopへ mov dh,0 add ch,1 cmp ch,CYLS jb readloop ; if ch < CYLS readloopへ ;mov ax,cs ; print boot poem ;mov ds,ax ;mov es,ax ;call PrintStr ;jmp $ mov [0x0ff0],ch jmp 0xc200 fin: hlt jmp fin error: mov si,msg putloop: mov al,[si] add si,1 cmp al,0 ; if al == 0 finへ je fin mov ah,0x0e mov bx,15 int 0x10 jmp putloop PrintStr: mov ax,BootPoem ; print boot poem mov bp,ax
mov cx,170 mov ax,01301h mov bx,00009h mov dh,10 mov dl,0 int 10h ret msg: db 0x0a, 0x0a db "load error" db 0x0a db 0 BootPoem: db "Hold fast to dreams" db 0x0a db "For if dreams die" db 0x0a db "Life is a broken-winged bird " db 0x0a db "That can never fly" db 0x0a db "Hold fast to dreams" db 0x0a db "For when dreams go" db 0x0a db "Life is a barren field" db 0x0a db "Frozen only with snow" db 0x0a times 510-($-$$) db 0 ; 接下來510字節寫0 dw 0xaa55 ; 最後一個字0xaa55是引導程序結束標誌
main.nas
; sonn-os boot asm ; TAB=4 ; author: 無 名 ; date: 2016.06.03 2016.06.05 ; description: jmp to 32bit BOTPAK EQU 0x00280000 DSKCAC EQU 0x00100000 DSKCAC0 EQU 0x00008000 ; BOOT_INFO 數據結構 CYLS EQU 0x0ff0 ; 啓動區 LEDS EQU 0x0ff1 VMODE EQU 0x0ff2 ; 顏色數目的信息。顏色的位數 SCRNX EQU 0x0ff4 ; 分辨率的X SCRNY EQU 0x0ff6 ; 分辨率的Y VRAM EQU 0x0ff8 ; 圖像緩衝區的開始地址 ORG 0xc200 ; 這個程序要被裝載到內存什麼地方 ; 畫面模式定位 MOV AL,0x13 ; VGA顯卡,320*200*8位彩色 MOV AH,0x00 INT 0x10 MOV BYTE [VMODE],8 ; 記錄畫面模式 MOV WORD [SCRNX],320 MOV WORD [SCRNY],200 MOV DWORD [VRAM],0x000a0000 ; 用BIOS取得鍵盤上各類LED指示燈的狀態 MOV AH,0x02 INT 0x16 ; keyboard BIOS MOV [LEDS],AL ; PIC關閉一切中斷 ; 根據AT兼容機的規格、初始化PIC ; 必須在CLI以前進行,到CLI掛起 ; 隨後進行PIC初始化 MOV AL,0xff OUT 0x21,AL NOP ; 若是連續進行OUT命令,有些機種不能夠 OUT 0xa1,AL CLI ; 禁止CPU級別中斷 ; OPEN A20GATE CALL waitkbdout MOV AL,0xd1 OUT 0x64,AL CALL waitkbdout MOV AL,0xdf ; enable A20 OUT 0x60,AL CALL waitkbdout ; 保護模式 [INSTRSET "i486p"] ; 開始使用486命令 LGDT [GDTR0] ; 臨時GDT MOV EAX,CR0 AND EAX,0x7fffffff ; bit31設0,禁止分頁 OR EAX,0x00000001 ; bit0設1,爲了切換到保護模式 MOV CR0,EAX JMP pipelineflush pipelineflush: MOV AX,1*8 ; 可讀寫的段,32bit MOV DS,AX MOV ES,AX MOV FS,AX MOV GS,AX MOV SS,AX ; 轉移 MOV ESI,c_main MOV EDI,BOTPAK MOV ECX,512*1024/4 CALL memcpy MOV ESI,0x7c00 MOV EDI,DSKCAC MOV ECX,512/4 CALL memcpy MOV ESI,DSKCAC0+512 MOV EDI,DSKCAC+512 MOV ECX,0 MOV CL,BYTE [CYLS] IMUL ECX,512*18*2/4 SUB ECX,512/4 CALL memcpy ; main到此爲止接下來是c_main ; c_main啓動 MOV EBX,BOTPAK MOV ECX,[EBX+16] ADD ECX,3 ; ECX += 3; SHR ECX,2 ; ECX /= 4; JZ skip MOV ESI,[EBX+20] ADD ESI,EBX MOV EDI,[EBX+12] CALL memcpy skip: MOV ESP,[EBX+12] JMP DWORD 2*8:0x0000001b waitkbdout: IN AL,0x64 AND AL,0x02 JNZ waitkbdout RET memcpy: MOV EAX,[ESI] ADD ESI,4 MOV [EDI],EAX ADD EDI,4 SUB ECX,1 JNZ memcpy RET ALIGNB 16 GDT0: RESB 8 DW 0xffff,0x0000,0x9200,0x00cf DW 0xffff,0x0000,0x9a28,0x0047 DW 0 GDTR0: DW 8*3-1 DD GDT0 ALIGNB 16 c_main:
這裏前一部分是對32位模式的啓動,後一部分是對C語言的準備。
其實不是很好理解,等我理解了再回來補充吧。
。。EQU。。這樣的語句其實就至關於C語言中的#define語句。
mov dword[vram],0x000a0000;
vram,顯卡內存,也就是用於顯示畫面的內存,將之存儲0xa0000,也就是種對畫面的設置了。具體暫時不討論。
這段代碼應該還涉及16位進入32位,GDT尋址等等,這麼重要的東西,做者都沒有講。無語。
c_main.c:
void io_hlt(void); void HariMain(void) { fin: io_hlt(); goto fin; }
c_main.c調用的彙編函數在assemblyFunc.nas中,這須要一個編譯(將C語言編譯爲彙編文件c_main.nas)、連接(兩個.nas彙編文件)的過程
_io_hlt: ; void io_hlt(void); HLT RET