Linux0.11內核--引導程序分析


1.簡介

本文主要介紹三個文件bootsect.s、setup.s、head.s,主要是做了些從軟盤加載內核和設置32位保護模式的操作。

2.程序分析

當PC電源打開后,BIOS自檢后將bootsect讀入內存絕對地址0x7c00處,因為bootsect.s的結尾是:

	.word 0xAA55

然后跳轉到0x7c00處並把執行權交給此處的代碼,從start:處開始執行。

BOOTSEG  = 0x07c0	
INITSEG  = 0x9000

start:
	mov	ax,#BOOTSEG
	mov	ds,ax
	mov	ax,#INITSEG
	mov	es,ax
	mov	cx,#256
	sub	si,si
	sub	di,di
	rep
	movw
	jmpi	go,INITSEG

BOOTSEG是當前程序的起始內存地址的段地址,INITSEG表示是bootsect將要移動要的內存地址的段地址,這段代碼的意思是重復執行movw指令256次,每次從BOOTSEG(0x7c0段地址)+si的地址處移動一個字(2個字節)的數據到INITSEG(0x9000段地址)+di地址處,挨個移動256次,所以總共就是256字(512字節),bootsect.s編譯出來也就是512字節的大小。所以這段代碼執行完之后就是把自己拷貝到0x90000地址處,然后jmpi跳轉到0x9000的偏移地址為go的地方執行。

所以接下來程序執行到go:處,但是整個程序的起始段地址變成了0x9000,go處的代碼設置了下堆棧,接着是load_setup:

SETUPLEN = 4	

load_setup:
	mov	dx,#0x0000		! drive 0, head 0
	mov	cx,#0x0002		! sector 2, track 0
	mov	bx,#0x0200		! address = 512, in INITSEG
	mov	ax,#0x0200+SETUPLEN	! service 2, nr of sectors
	int	0x13			! read it
	jnc	ok_load_setup		! ok - continue
	mov	dx,#0x0000
	mov	ax,#0x0000		! reset the diskette
	int	0x13
	j	load_setup

利用BIOS中斷int 0x13將setup從磁盤第2個扇區開始讀到0x90200開始處,共SETUPLEN(setup 程序的扇區數)讀4個扇區。成功后跳轉到ok_load_setup。

SETUPSEG = 0x9020

ok_load_setup:
...
	mov	ax,#SYSSEG
	mov	es,ax		! segment of 0x010000
	call	read_it
	call	kill_motor

...
	jmpi	0,SETUPSEG

省略的代碼都是一些讀硬盤和驅動器的數據。這里比較關鍵的是call read_it,調用read_it:

SYSSIZE = 0x3000
SYSSEG   = 0x1000
ENDSEG   = SYSSEG + SYSSIZE

read_it:
	mov ax,es
	test ax,#0x0fff
die:	jne die			! es must be at 64kB boundary
	xor bx,bx		! bx is starting address within segment
rp_read:
	mov ax,es
	cmp ax,#ENDSEG		! have we loaded all yet?
	jb ok1_read
	ret
ok1_read:
	...

SYSSIZE是編譯后system模塊的大小,SYSSEG是system模塊將加載到的內存段地址處,所以ENDSEG的值就是system模塊停止加載的段地址。那么read_it的作用就是先判斷一下es是不是到了system模塊停止加載的段地址處,如果沒有則跳轉去讀取system模塊到這個地址。加載完成后就ret返回。然后關閉馬達后讀一些驅動器的信息,最后jmpi 0,SETUPSEG跳轉到0x9020:0000也就是setup.s程序的開始處。

bootsect.s就此結束,到現在為止內核各個模塊在內存中的位置如下圖的第3步:

接下來進入setup.s。

未完待續


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM