操作系統實踐之加載程序

  Loader程序主要作用是加載Kernel.bin到內存中,這一步與引導程序加載Loader.bin進入內存是類似的,Kernel.bin是在Linux下編譯的,是ELF格式的。因此,Kernel.bin加載內存後,需要將其中的代碼段拷貝到

相應的位置,這個位置由Kernel.bin編譯時指令的入口地址決定,這些是由InitKernel完成的。Loader還做了一些事情,就是設置GDT,進入保護模式,啓動分頁機制,在這些事情完成後將控制權交給Kernel,Kernel程序在執行時已經處於保護模式下了。Loader的部分源代碼如下:

org  0100h            
BaseOfStack equ    0100h    
jmp short LABEL_START
nop
%include "fat12hdr.inc"
%include "pm.inc"
%include "load.inc"
LABEL_GDT: Descriptor 0, 0, 0
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW|DA_DPL3; //顯存地址空間
LABEL_DESC_FLAT_C: Descriptor 0, 0fffffh, DA_C+DA_32+DA_LIMIT_4K
LABEL_DESC_FLAT_RW: Descriptor 0, 0fffffh, DA_DRW+DA_32+DA_LIMIT_4K

GdtLen equ $ - LABEL_GDT;GDT長度
GdtPtr dw GdtLen - 1
       dd BaseOfLoaderPhyAddr + LABEL_GDT ;//GDT物理地址

;GDT選擇子 
SelectorVideo equ  LABEL_DESC_VIDEO - LABEL_GDT+SA_RPL3;顯存選擇子
SelectorFlatC equ LABEL_DESC_FLAT_C - LABEL_GDT;
SelectorFlatRW equ LABEL_DESC_FLAT_RW - LABEL_GDT;
;Loader入口
LABEL_START:
mov axcs
mov dsax
mov esax
mov ssax
mov sp, BaseOfStack


; 省略將軟盤中的Kernel.bin加載到內存中的代碼
;LABEL_FILE_LOADED:
  mov dh, 1
  call DispStrRealMode
  ;加載gdtr
  lgdt [GdtPtr]
  cli;關中斷
  in al, 92h
  or al,00000010b
  out 92h, al
  mov eaxcr0
  or eax, 1
  mov cr0eax
  ;進入保護模式
  jmp dword SelectorFlatC: (BaseOfLoaderPhyAddr+LABEL_PM_START)

[SECTION .s32]
ALIGN 32
[BITS 32]
LABEL_PM_START:
  mov ax, SelectorVideo
  mov gsax
  mov ax, SelectorFlatRW
  mov dsax
  mov esax
  mov fsax
  mov ssax
  mov esp, TopOfStack
  
  push szMemChkTitle
  call DispStr
  add  esp, 4
  call DispMemInfo ;打印內存信息
  call SetupPaging ;啓動分頁機制
   
  mov ah, 0Fh
  mov al, 'P'
  mov [gs:((80*0 + 39)*2)], ax
  
  call InitKernel;重新放置內核代碼
  jmp SelectorFlatC: KernelEntryPointPhyAddr

%include    "lib.inc"

;打印內存信息,現在處於保護模式下
DispMemInfo:
  push esi
  push edi
  push ecx
  mov esi, MemChkBuf
  mov ecx, [dwMCRNumber]
.loop:
  mov edx, 5;每個地址範圍描述符結構分5個部分,每個部分是32位
  mov edi, ARDStruct
.1:
  push dword [esi]
  call DispInt
  pop eax
  stosd ;將eax中的內容存到es: edi中,同時edi+4
  add esi, 4; //地址範圍的下一個部分
  dec edx
  cmp edx, 0
  jne .1
  call DispReturn; 回車
  cmp dword [dwType], 1
  jne .2
  mov eax, [dwBaseAddrLow]
  add eax, [dwLengthLow]
  cmp eax, [dwMemSize]
  jb .2
  mov [dwMemSize], eax ;可用的最大內存範圍
.2:
  loop .loop 
  call DispReturn
  push szRAMSize
  call DispStr
  add esp, 4
  push dword [dwMemSize]
  call DispInt
  add esp, 4
  pop ecx
  pop edi
  pop esi
  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章