linux0.11的bootsect.s和setup.s

 一、計算機的啓動linux

   一、首先計算機的工做原理能夠簡單的概述爲取指,執行;再取指,再執行;以此類推的過程,cpu就是一個不停取指執行不會休息的機器。
   二、那麼x86結構的計算機上電後是怎麼工做的呢?其實上電後(未加載操做系統代碼以前)會先執行內存中一段爲BIOS固化的區域,這段區域是每次開機都必須執行的,正常狀況下不被咱們所控,主要做用是對一些硬件環境作出檢測,是否有硬件損壞。這段期間cpu處在實模式下工做。在BIOS代碼執行完畢後,cpu會去磁盤的0磁道0扇區讀取512字節到內存地址的0x7c00處,而後設置cs:ip = 0x7c00,開始取指,執行。。。這512個字節就是今天的重點,操做系統的引導代碼bootsect.s就放在其中。
   三、bootsect.s就是一個操做系統的引導代碼,一個操做系統的起步就從這裏開始。所以bootsect.s重要性無可厚非。
二、 bootsect.s
  bootsect.s的做用:
  一、bootsect.s在執行時,首先將自身代碼內存位置0x7c00開始的512個字節 挪到0x90000開始的內存地址處,而後載入setup.s代碼塊(又一個重點)到0x90200位置開始的 4*512字節(這是setup.s)的大小。
    mov ax,#BOOTSEG        !BOOTSEG=0x7c0
    mov ds,ax
    mov ax,#SETUPSEG       !SETUPSEG=0x9000
    mov es,ax
    mov cx,#256
    sub si,si
    sub di,di
    rep
    movs              ! ds:si -->  es:di 
    jmpi load_setup,SETUPSEG     !jmpi是段間跳轉,具體跳轉的地址爲9000:load_setup 
     load_setup:   git

    load_setup:
    mov dx,#0x0000                  
    mov cx,#0x0002    !cl表示從第二個扇區開始讀
    mov bx,#0x0200      !bx表示段內偏移地址 ,讀到0x90200
    mov ax,#0x0200+SETUPLEN
    int 0x13                           !0x13號中斷開始讀磁盤oop

    jnc ok_load_setup          !讀取成功後跳轉
    mov dx,#0x0000
    mov ax,#0x0000
    int 0x13
    jmp load_setup
  ok_load_setup:
    jmpi 0,SETUP   !SETUP=0x9020  最後執行段間跳轉指令,cs:ip-->9020:0spa

  二、載入setup程序後bootsect繼續執行,先向屏幕打印提示system is loading... 在此的提示就和window開機的窗口是一個原理。最後bootsect在將system模塊讀入後,完成使命,將執行權交到setup模塊。操作系統

    mov ah,#0x03    !功能號ah=0x03
    xor bh,bh    !頁號,應該是屏幕位置的頁號
    int 0x10      !讀取光標所在的位置 返回參數保存在dx寄存器中
    mov cx,#36     !設置字符串長度 
    mov bx,#0x0007       !bl = 0x07 表示字符屬性爲normal
    mov bp,#msg1     !設置字符串偏移
    mov ax,#0x07c0  !7c00是bootsect模塊所在首地址
    mov es,ax      !設置字符串基地址  es:bp 表示要顯示字符串的內存地址
    mov ax,#0x1301      !ah = 0x13 表示顯示字符功能號,al = 0x01 表示光標的屬性在bl保存。
    int 0x10      !開啓中斷,開始從內存中讀字符到屏幕中orm

三、setup.sblog

  setup.s的功能:setup的主要功能是首先得到光標,內存,顯卡,磁盤等參數存放在0x90000爲起始地址的空間中,在這個模塊以前放的bootsect.s,如今bootsect.s已經執行完成,這段空間也能夠從新可利用了。而後將system模塊從起始地址0x10000的全部代碼,挪到0x0000(內存的起始地址處,以後system就一直存在於此處)。而後setup會初始化gdt表,idt表等等,最後用一個很酷的指令開啓32位尋址方式,進入保護模式(在bootsect和setup執行的過程當中cpu一直處於實模式,16位地址模式,最多能尋址1M的空間)。保護模式能夠尋址4G的內存空間。ip

    mov ax,#0x0001內存

     mov cr1,ax    !等價於lmsw ax      將cr0寄存器最後一位置1,便進入了保護模式
ci

     jmpi 0,8

    

 

                            這兩幅圖來自linux0.11內核徹底註釋v3.0版

 

四、具體實驗(用代碼實踐實踐)

      

      截圖所示是,操做系統的第二個實驗,改寫bootsect.s 和setup.s重新編譯後,實現開機引導啓動,獲取硬件參數,顯示到屏幕上。

 

實驗具體代碼:

SETUPLEN=2
SETUPSEG=0x9000
SETUP=0x9020
BOOTSEG=0x7c0
entry _start
_start:
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#36
mov bx,#0x0007
mov bp,#msg1
mov ax,#0x07c0
mov es,ax
mov ax,#0x1301
int 0x10

mov ax,#BOOTSEG
mov ds,ax
mov ax,#SETUPSEG
mov es,ax
mov cx,#256
sub si,si
sub di,di
rep
movs
jmpi load_setup,SETUPSEG

load_setup:
mov dx,#0x0000
mov cx,#0x0002
mov bx,#0x0200
mov ax,#0x0200+SETUPLEN
int 0x13
jnc ok_load_setup
mov dx,#0x0000
mov ax,#0x0000
int 0x13
jmp load_setup
ok_load_setup:
jmpi 0,SETUP
msg1:
.byte 13,10
.ascii "Hello OS world, my name is til"
.byte 13,10,13,10
.org 510
boot_flag:
.word 0xAA55
-------------------------------------------------以上是2019.11.9實驗二6.8bootsect.s正確代碼

INITSEG = 0x9000
entry _start
_start:
! Print "NOW we are in SETUP"
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#25
mov bx,#0x0007
mov bp,#msg2
mov ax,cs
mov es,ax
mov ax,#0x1301
int 0x10

mov ax,cs
mov es,ax
! init ss:sp
mov ax,#INITSEG
mov ss,ax
mov sp,#0xFF00

! Get Params
mov ax,#INITSEG
mov ds,ax
mov ah,#0x03
xor bh,bh
int 0x10
mov [0],dx
mov ah,#0x88
int 0x15
mov [2],ax
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0004
mov cx,#0x10
rep
movsb
! Be Ready to Print
mov ax,cs
mov es,ax
mov ax,#INITSEG
mov ds,ax

! Cursor Position
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#18
mov bx,#0x0007
mov bp,#msg_cursor
mov ax,#0x1301
int 0x10
mov dx,[0]
call print_hex
! Memory Size
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#14
mov bx,#0x0007
mov bp,#msg_memory
mov ax,#0x1301
int 0x10
mov dx,[2]
call print_hex
! Add KB
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#2
mov bx,#0x0007
mov bp,#msg_kb
mov ax,#0x1301
int 0x10
! Cyles
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#7
mov bx,#0x0007
mov bp,#msg_cyles
mov ax,#0x1301
int 0x10
mov dx,[4]
call print_hex
! Heads
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#8
mov bx,#0x0007
mov bp,#msg_heads
mov ax,#0x1301
int 0x10
mov dx,[6]
call print_hex
! Secotrs
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#10
mov bx,#0x0007
mov bp,#msg_sectors
mov ax,#0x1301
int 0x10
mov dx,[12]
call print_hex
inf_loop:
jmp inf_loop

print_hex:
mov cx,#4

print_digit:
rol dx,#4        !循環左移命令,最高位的4bit放在最低位的4bit上,由於4bit是一個16進制字符
mov ax,#0xe0f      !0x10號中斷,功能號ah=0x0e表示顯示al所對應ascii碼的字符到屏幕上。這裏的低16位是掩碼
           !特別注意,區別上面功能號爲0x13是顯示es:bp內存地址的字符到屏幕上
and al,dl        !將dl的低4位經過and操做放到al的低4位
add al,#0x30      !al = al + 0x30 由於0x30~0x39爲數字
cmp al,#0x3a         !判斷al中存放是否爲數字
jl outp          !若是爲數字跳轉
add al,#0x07      !不然+7表示爲一個字母 由於字母a~f的ascii碼爲 0x41~0x46
outp:
int 0x10        !將al中的內容以ascii碼形式輸出到屏幕上
loop print_digit      !循環四次,把dx的每四位都拿出來輸出一次
ret !四次結束後返回。

print_nl:

mov ax,#0xe0d ! CR int 0x10 mov al,#0xa ! LF int 0x10 retmsg2: .byte 13,10 .ascii "NOW we are in SETUP" .byte 13,10,13,10msg_cursor: .byte 13,10 .ascii "Cursor position:"msg_memory: .byte 13,10 .ascii "Memory Size:"msg_cyles: .byte 13,10 .ascii "Cyls:"msg_heads: .byte 13,10 .ascii "Heads:"msg_sectors: .byte 13,10 .ascii "Sectors:"msg_kb: .ascii "KB".org 510boot_flag: .word 0xAA55----------------------------------------------以上是2019.11.9實驗二6.8 setup.s正確代碼

相關文章
相關標籤/搜索