從這一節開始,分析代碼,我會分析的比較細,適合像我這種水平比較低的同學看。
代碼大家可以從http://download.csdn.net/tag/linux0.11%E5%86%85%E6%A0%B8下載
.equ SETUPLEN, 4# nr of setup-sectors.equ BOOTSEG, 0x07c0# original address of boot-sector.equ INITSEG, 0x9000# we move boot here - out of the way.equ SETUPSEG, 0x9020# setup starts here.equ SYSSEG, 0x1000# system loaded at 0x10000 (65536)..equ ENDSEG, SYSSEG + SYSSIZE# where to stop loading
設定了從磁碟片讀取 SETUPPLEN=4 個扇區,BOOTSEG是bios複製的第一個扇區的起始位置,INITSEG是複製到
記憶體的第一個扇區代碼自己複製自己後的起始位置,SETUPSEG是第二到第五扇區(即setup.s)代碼複製到記憶體
的起始位置,SYSSEG是核心(後面的240個扇區)載入的位置,ENDSEG核心的末尾位置。
.equ ROOT_DEV, 0x301ljmp $BOOTSEG, $_start_start:mov$BOOTSEG, %axmov%ax, %dsmov$INITSEG, %axmov%ax, %esmov$256, %cxsub%si, %sisub%di, %direpmovsw
這部分代碼實現了 “挪代碼”也就是 被bios拷貝進記憶體的代碼,被這些代碼自己放到新的位置上。
解釋兩個指令:
(1)ljmp $BOOTSEG, $_start
實現將cs置為BOOTSEG的段基址,ip置為_start的位移地址,實現跳轉
(2)rep
movsw
搬移字串指令,rep(repeat),movsw(moving string word),實現將把 DS:SI 所指地址的一個字搬移到
ES:DI 所指的地址上,搬移後原來的內容不變,但是原來 ES:DI 所指的內容會被覆蓋而且在搬移之後 SI 和 DI
會自動地址向下一個要搬移的地址。
ljmp$INITSEG, $gogo:mov%cs, %ax
這兩句實現了從原先的程式碼片段執行到複製完成後的程式碼片段執行的轉變。
load_setup:mov$0x0000, %dx# drive 0, head 0mov$0x0002, %cx# sector 2, track 0mov$0x0200, %bx# address = 512, in INITSEG.equ AX, 0x0200+SETUPLENmov $AX, %ax# service 2, nr of sectorsint$0x13# read itjncok_load_setup# ok - continuemov$0x0000, %dxmov$0x0000, %ax# reset the disketteint$0x13jmpload_setup
解釋一下,0x13中斷。
ah: 功能號 0x02--讀磁碟資料到記憶體
al: 需要讀出的扇區的數量
ch: 磁軌(柱面)號的低8位
cl: 開始扇區(0-5bit),磁軌號的高兩位(6-7bit)
dh: 磁頭號, dl: 磁碟機代號(if it's hard-disk, set the 7th bit)
es:bx: 目的地址。指向資料緩衝區;如果出錯則CF標誌置位。
這樣上面的代碼就實現了從磁碟片將四個扇區的代碼拷貝到制定記憶體的功能。