bootsect啟動代碼分析

      網友投稿 1236 2022-05-28

      Linux0.11內核啟動過程

      I、Linux0.11內核啟動過程概述:

      當PC的電源打開后,80x86結構的CPU將進入實模式,并從地址0XFFFF0開始自動執行。

      PC機的BIOS將執行某些系統的檢測,并在物理地址0處開始初始化中斷向量。

      啟動設備(軟驅或硬盤)的第一個扇區(磁盤引導扇區,512字節)讀入到內存的絕對地址0x7C00處,并跳轉到這個地方運行。

      Linux0.11啟動代碼目錄boot下文件介紹:

      在boot目錄下主要有bootsect.s,head.s,setup.s三個匯編文件,三個匯編文件完成了啟動引導的流程,過程圖如下圖所示:

      1、bootsect.s程序:

      bootsec.s是磁盤引導塊程序,駐留在磁盤的第一個扇區中(引導扇區,0磁道,0磁頭,第一個扇區)。

      2、setup.s程序

      setup.s是一個操作系統加載程序,它的主要作用是利用ROM BIOS中斷讀取機器系統數據,并將這些數據保存到0x90000開始的位置。

      3、head.s程序

      從這里開始,內核完全都是在保護模式下運行了。

      II、 boot/bootsect.s啟動內核時在內存中的位置和移動情況:

      8086體系結構的計算機在上電后將由BIOS進行系統的自檢。

      之后BIOS會將bootsect.s文件讀入內存的0x7C00(31k)處。

      然后跳轉到此執行引導扇區的代碼。

      這段代碼執行時會將自己移動的內存的0x90000(576k)到0xA0000處一共64K,并把存儲設備中的setup.s文件讀入到內存的0x90200(576.5k)處,system模塊讀入到內存的0x10000(64k)處。啟動引導時內核在內存中的位置和移動后的位置情況如下圖所示:

      III 、bootsect.s程序分析

      目錄:

      bootsect.s文件讀入內存

      setup讀入內存及讀取磁盤驅動器參數

      打印信息代碼分析

      SYSTEM模塊讀入內存

      確定使用哪個根文件系統設備

      跳轉執行setup

      1、bootsect.s文件讀入內存

      1.1、代碼分析:

      entry start ! 告知連接程序,程序從start 標號開始執行。 start: ! 47--56 行作用是將自身(bootsect)從目前段位置0x07c0(31k) mov ax,#BOOTSEG ! 將ds 段寄存器置為0x7C0; mov ds,ax mov ax,#INITSEG ! 將es 段寄存器置為0x9000; mov es,ax mov cx,#256 ! 移動計數值=256 字; sub si,si ! 源地址 ds:si = 0x07C0:0x0000 sub di,di ! 目的地址 es:di = 0x9000:0x0000 rep ! 重復執行,直到cx = 0 movw ! 移動1 個字; jmpi go,INITSEG ! 間接跳轉。這里INITSEG 指出跳轉到的段地址。

      1

      2

      3

      4

      5

      6

      bootsect啟動代碼分析

      7

      8

      9

      10

      11

      12

      1.2、bootsect.s文件讀入內存示圖

      1.3、ds,es和ss端處設置

      go: mov ax,cs ! 將ds、es 和ss 都置成移動后代碼所在的段處(0x9000)。 mov ds,ax !由于程序中有堆棧操作(push,pop,call),因此必須設置堆棧。 mov es,ax

      1

      2

      3

      1.4、移動堆棧指針程序分析

      ! put stack at 0x9ff00. ! 將堆棧指針sp 指向0x9ff00(即0x9000:0xff00)處

      ! 由于代碼段移動過了,所以要重新設置堆棧段的位置。

      ! sp 只要指向遠大于512 偏移(即地址0x90200)處

      ! 都可以。因為從0x90200 地址開始處還要放置setup 程序,

      ! 而此時setup 程序大約為4 個扇區,因此sp 要指向大

      ! 于(0x200 + 0x200 * 4 + 堆棧大小)處。

      mov ss,ax mov sp,#0xFF00 ! arbitrary value >>512

      1

      2

      2、setup讀入內存及讀取磁盤驅動器參數

      2.1、磁盤平面圖:

      2.2、啟動文件在磁盤中位置示意圖:

      2.3、setup讀入內存示意圖:

      2.4、setup讀入內存代碼分析

      ! 用途是利用BIOS 中斷INT 0x13 將setup 模塊從磁盤第2 個扇區

      ! 開始讀到0x90200 開始處,共讀4 個扇區。如果讀出錯,則復位驅動器,并

      ! 重試,沒有退路。INT 0x13 的使用方法如下:

      ! 讀扇區:

      ! ah = 0x02 讀磁盤扇區到內存;al = 需要讀出的扇區數量;

      ! ch = 磁道(柱面)號的低8 位; cl = 開始扇區(0-5 位),磁道號高2 位(6-7);

      ! dh = 磁頭號; dl = 驅動器號(如果是硬盤則要置位7);

      ! es:bx ??指向數據緩沖區; 如果出錯則CF 標志置位。

      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 , 讀4個扇區 int 0x13 ! read it jnc ok_load_setup ! ok - continue mov dx,#0x0000 mov ax,#0x0000 ! reset the diskette int 0x13 j load_setup

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      2.5、setup讀入參數代碼分析

      ! Get disk drive parameters, specifically nr of sectors/track

      ! 取磁盤驅動器的參數,特別是每道的扇區數量。

      ! 取磁盤驅動器參數INT 0x13 調用格式和返回信息如下:

      ! ah = 0x08 dl = 驅動器號(如果是硬盤則要置位7 為1)。

      ! 返回信息:

      ! 如果出錯則CF 置位,并且ah = 狀態碼。

      ! ah = 0, al = 0, bl = 驅動器類型(AT/PS2)

      ! ch = 最大磁道號的低8 位,cl = 每磁道最大扇區數(位0-5),最大磁道號高2 位(位6-7)

      ! dh = 最大磁頭數, dl = 驅動器數量,

      ! es:di -?? 軟驅磁盤參數表。

      ok_load_setup: mov dl,#0x00 mov ax,#0x0800 ! AH=8 is get drive parameters int 0x13 mov ch,#0x00 seg cs ! 表示下一條語句的操作數在cs 段寄存器所指的段中。 mov sectors,cx ! 保存每磁道扇區數。 mov ax,#INITSEG mov es,ax ! 因為上面取磁盤參數中斷改掉了es 的值,這里重新改回。

      1

      2

      3

      4

      5

      6

      7

      8

      9

      3、打印信息代碼分析:

      ! Print some inane message

      ! 在顯示一些信息(‘Loading system …’回車換行,共24 個字符)。

      ! BIOS中斷0x10功能號 ah = 0x03,讀光標

      !BIOS中斷0x10功能號 ah=0x13,顯示字符

      mov ah,#0x03 ! read cursor pos xor bh,bh ! 讀光標位置。 int 0x10 mov cx,#24 ! 共24 個字符。 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#msg1 ! 指向要顯示的字符串。 mov ax,#0x1301 ! write string, move cursor int 0x10 ! 寫字符串并移動光標。

      1

      2

      3

      4

      5

      6

      7

      8

      9

      msg1:

      .byte 13,10 ! 回車、換行的ASCII 碼。 .ascii "Loading system ..." .byte 13,10,13,10 ! 共24 個ASCII 碼字符。 .org 508 ! 表示下面語句從地址508(0x1FC)開始,所以root_dev ! 在啟動扇區的第508 開始的2 個字節中。 root_dev: .word ROOT_DEV ! 這里存放根文件系統所在的設備號(init/main.c 中會用)。 boot_flag: .word 0xAA55 ! 硬盤有效標識。

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      4、SYSTEM模塊讀入內存

      4.1示圖

      4.2 代碼分析

      ! ok, we’ve written the message, now

      ! we want to load the system (at 0x10000) ! 現在開始將system 模塊加載到0x10000(64k)處。

      SYSSIZE = 0x3000 ! 指編譯連接后system 模塊的大小。參見列表1.2 中第92 的說明。 ! setup 程序從這里開始; SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). ! system 模塊加載到0x10000(64 kB)處; ENDSEG = SYSSEG + SYSSIZE ! where to stop loading !-------------------------------------------------- mov ax,#SYSSEG mov es,ax ! segment of 0x010000 ! es = 存放system 的段地址。 call read_it ! 讀磁盤上system 模塊,es 為輸入參數。 call kill_motor ! 關閉驅動器馬達,這樣就可以知道驅動器的狀態了。

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      4.3、read_it

      //待分析

      4.4、關閉軟驅的馬達

      ! 這個子程序用于關閉軟驅的馬達,這樣我們進入內核后它處于已知狀態,以后也就無須擔心它了。

      kill_motor: push dx mov dx,#0x3f2 ! 軟驅控制卡的驅動端口,只寫。 mov al,#0 ! A 驅動器,關閉FDC,禁止DMA 和中斷請求,關閉馬達。 outb ! 將al 中的內容輸出到dx 指定的端口去。 pop dx ret

      1

      2

      3

      4

      5

      6

      7

      5、確定使用哪個根文件系統設備

      5.1、設備號介紹

      ! ROOT_DEV: 0x000 same type of floppy as boot.

      ! 根文件系統設備使用與引導時同樣的軟驅設備;

      ! 0x301 first partition on first drive etc

      ! 根文件系統設備在第一個硬盤的第一個分區上,等等;

      ROOT_DEV = 0x306 ! 指定根文件系統設備是第2 個硬盤的第1 個分區。這是Linux 老式的硬盤命名

      ! 方式,具體值的含義如下:

      ! 設備號=主設備號*256 + 次設備號(也即dev_no = (major<<8) + minor )

      ! (主設備號:1-內存,2-磁盤,3-硬盤,4-ttyx,5-tty,6-并行口,7-非命名管道)

      ! 0x300 /dev/hd0 代表整個第1 個硬盤;

      ! 0x301 /dev/hd1 第1 個盤的第1 個分區;

      ! …

      ! 0x304 /dev/hd4 第1 個盤的第4 個分區;

      ! 0x305 /dev/hd5 代表整個第2 個硬盤盤;

      ! 0x306 /dev/hd6 第2 個盤的第1 個分區;

      ! …

      ! 0x309 /dev/hd9 第2 個盤的第4 個分區;

      ! 從linux 內核0.95 版后已經使用與現在相同的命名方法了。

      5.2、內存地址偏移代碼:

      .org 508 ! 表示下面語句從地址508(0x1FC)開始,所以root_dev ! 在啟動扇區的第508 開始的2 個字節中。 root_dev: .word ROOT_DEV ! 這里存放根文件系統所在的設備號(init/main.c 中會用)。 boot_flag: .word 0xAA55 ! 硬盤有效標識。

      1

      2

      3

      4

      5

      6

      5.3、內存地址偏移如圖所示:

      5.4 代碼分析

      ! After that we check which root-device to use. If the device is

      ! defined (!= 0), nothing is done and the given device is used.

      ! Otherwise, either /dev/PS0 (,28) or /dev/at0 (2,8), depending

      ! on the number of sectors that the BIOS reports currently.

      ! 此后,我們檢查要使用哪個根文件系統設備(簡稱根設備)。如果已經指定了設備(!=0)

      ! 就直接使用給定的設備。否則就需要根據BIOS 報告的每磁道扇區數來

      ! 確定到底使用/dev/PS0 (2,28) 還是 /dev/at0 (2,8)。

      ! 上面一行中兩個設備文件的含義:

      ! 在Linux 中軟驅的主設備號是2(參見第43 行的注釋),次設備號 = type*4 + nr,其中

      ! nr 為0-3 分別對應軟驅A、B、C 或D;type 是軟驅的類型(2??1.2M 或7??1.44M 等)。

      ! 因為7*4 + 0 = 28,所以 /dev/PS0 (2,28)指的是1.44M A 驅動器,其設備號是0x021c

      ! 同理 /dev/at0 (2,8)指的是1.2M A 驅動器,其設備號是0x0208。

      seg cs mov ax,root_dev ! 將根設備號 cmp ax,#0 jne root_defined seg cs mov bx,sectors ! 取上面第88 行保存的每磁道扇區數。如果sectors=15

      1

      2

      3

      4

      5

      6

      ! 則說明是1.2Mb 的驅動器;如果sectors=18,則說明是

      ! 1.44Mb 軟驅。因為是可引導的驅動器,所以肯定是A 驅。

      mov ax,#0x0208 ! /dev/ps0 - 1.2Mb cmp bx,#15 ! 判斷每磁道扇區數是否=15 je root_defined ! 如果等于,則ax 中就是引導驅動器的設備號。 mov ax,#0x021c ! /dev/PS0 - 1.44Mb cmp bx,#18 je root_defined undef_root: ! 如果都不一樣,則死循環(死機)。 jmp undef_root root_defined: seg cs mov root_dev,ax ! 將檢查過的設備號保存起來。

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      6、跳轉執行setup

      ! after that (everyting loaded), we jump to

      ! the setup-routine loaded directly after

      ! the bootblock:

      ! 到此,所有程序都加載完畢,我們就跳轉到被

      ! 加載在bootsect 后面的setup 程序去。

      jmpi 0,SETUPSEG ! 跳轉到0x9020:0000(setup.s 程序的開始處)。

      1

      Elasticsearch Linux

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:彈性文件服務解密 -- 數據可靠性設計,N+M數據存儲
      下一篇:云資源池運維規劃:業務重要性等級和資源池等級劃分
      相關文章
      久久亚洲国产成人影院| 亚洲国产另类久久久精品黑人| 亚洲欧洲美洲无码精品VA | 久久精品国产亚洲AV未满十八| 久久综合亚洲色一区二区三区| 亚洲成AV人片在线观看ww| 亚洲精品无码99在线观看| 亚洲国产精品日韩av不卡在线| 亚洲国产精品乱码在线观看97 | 久久亚洲精品成人av无码网站| 国产精品亚洲片在线| 亚洲成av人在片观看| 亚洲人成网亚洲欧洲无码| 久久精品亚洲AV久久久无码 | 亚洲va在线va天堂va手机| 久久精品国产亚洲av麻豆色欲| 亚洲精品国产成人片| 亚洲AV无码一区二区二三区入口 | 久久亚洲AV无码精品色午夜麻| 亚洲AV无码码潮喷在线观看| 亚洲国产成人久久综合碰碰动漫3d| 亚洲国产精品第一区二区| 久久精品国产亚洲AV麻豆网站| 亚洲国产精品线观看不卡| 亚洲情A成黄在线观看动漫软件| 四虎必出精品亚洲高清| 亚洲AV无码成人精品区狼人影院 | 一区二区三区亚洲视频| 亚洲乱码国产一区网址| 久久久久亚洲AV成人网人人网站| 亚洲午夜福利717| 亚洲AV日韩AV永久无码绿巨人| 久久综合亚洲鲁鲁五月天| 亚洲人成影院午夜网站| 亚洲人成人网站18禁| 一本色道久久88综合亚洲精品高清| 国产成人99久久亚洲综合精品| 国产亚洲精久久久久久无码| 久久久久亚洲av无码专区喷水| 亚洲一卡二卡三卡| 亚洲AV无码XXX麻豆艾秋|