日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【OS学习笔记】六 实模式:编写主引导扇区代码

發(fā)布時間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【OS学习笔记】六 实模式:编写主引导扇区代码 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

上一篇文章學(xué)習(xí)了:計算機(jī)的啟動過程(點(diǎn)擊鏈接查看上一篇文章)

這篇文章學(xué)習(xí)記錄為:編寫主引導(dǎo)扇區(qū)代碼。

參考:《X86匯編語言-從實模式到保護(hù)模式》-李忠。純學(xué)習(xí)筆記,更詳細(xì)內(nèi)容請閱讀正版書籍。如有侵權(quán)請聯(lián)系我刪除文章。

實際上,從這篇文章開始,我們才開始進(jìn)入到實模式的學(xué)習(xí)。之前的五篇文章,都是預(yù)備的學(xué)習(xí)知識。點(diǎn)擊下面鏈接復(fù)習(xí)相關(guān)的預(yù)備知識:

  • 處理器、內(nèi)存和指令
  • 匯編語言和匯編軟件
  • 計算機(jī)的啟動過程
  • 什么是虛擬機(jī)
  • VirtualBox的下載、安裝和配置
  • 1、回顧主引導(dǎo)扇區(qū)

    在前面的學(xué)習(xí)中,我們知道在計算機(jī)重新啟動后,如果硬盤是首選的啟動設(shè)備,那么處理器就會跳轉(zhuǎn)到硬盤的0面0道1扇區(qū)去執(zhí)行代碼。這里成為主引導(dǎo)扇區(qū)。

    主引導(dǎo)扇區(qū)的大小為512字節(jié)、ROM-BIOS將它加載到處理器的地址空間的邏輯地址0x0000:0x7c00處,也就是物理地址0x07c00處,然后判斷它是否有效。

    而判斷一個主引導(dǎo)扇區(qū)是否有效的方法是判斷它最后的兩個字節(jié)是否是0x55和0xAA。ROM-BIOS首先檢測這兩個位置是否正確,如果正確,則以一個段間轉(zhuǎn)移指令jmp 0x0000:0x7c00處執(zhí)行代碼。

    一般來說,主引導(dǎo)扇區(qū)的代碼,負(fù)責(zé)計算出操作系統(tǒng)所在的硬盤位置,然后將操作系統(tǒng)的自舉代碼加載到內(nèi)存,也用一個jmp指令跳轉(zhuǎn)到那里繼續(xù)執(zhí)行,直到操作系統(tǒng)完成啟動。

    我們本篇文章的主要內(nèi)容就是,編寫一段代碼,將它寫到主引導(dǎo)扇區(qū),讓處理器執(zhí)行。為了更加明顯的顯示我們的代碼是正確的,我們選擇在屏幕上顯示一行字符串。

    2、在屏幕上顯示文字

    在編寫代碼之前,我們首先來了解一下如何在屏幕上顯示文字。

    請注意,這里可不是使用printf或者cout或者System.out.println的地方。我們這里是在沒有操作系統(tǒng)的情況下,想要在顯示屏上顯示文字。

    想要顯示文字,就要把想要顯示的內(nèi)容寫到顯存即可。顯存是什么?也是一種存儲器,只不過專門存儲需要在顯示器上顯示的內(nèi)容的。其他詳細(xì)原理自己百度吧,或者看本文的參考書籍,有詳細(xì)的解釋。

    如下圖所示,是一個字符在屏幕上顯示的簡單的原理圖:

    處理器為了直接訪問顯存,將顯存映射到處理器的尋址空間中。如下圖:

    我們知道8086可以訪問1M的內(nèi)存空間。其中0x00000-0x9FFFF屬于常規(guī)內(nèi)存,由內(nèi)存條提供。0xF0000-0xFFFFF由主板上的ROM-BIOS提供。

    中間還剩余的320KB的空洞,即0xA0000-0xEFFFF,這段空間就由外設(shè)來提供,其中就包括顯卡的顯存部分。

    由于歷史原因,一直以來0xB8000-0xBFFFF這段物理地址空間,是留給顯卡的。

    3、分析主引導(dǎo)扇區(qū)代碼

    這段代碼是本文參考書籍的代碼,先把代碼貼上,不算長,如果看不懂,不要被嚇跑了。下面的分析,肯定可以讓你明白這個程序的意思。

    1 ;代碼清單5-1 2 ;文件名:c05_mbr.asm3 ;文件說明:硬盤主引導(dǎo)扇區(qū)代碼4 ;創(chuàng)建日期:2011-3-31 21:15 5 6 mov ax,0xb800 ;指向文本模式的顯示緩沖區(qū),顯存的段地址,7 mov es,ax ;一般用DS段寄存器,但是DS有其他用處,這里我們使用ES寄存器8 9 ;以下是顯示字符串"Label offset:"10 mov byte [es:0x00],'L'11 mov byte [es:0x01],0x0712 mov byte [es:0x02],'a'13 mov byte [es:0x03],0x0714 mov byte [es:0x04],'b'15 mov byte [es:0x05],0x0716 mov byte [es:0x06],'e'17 mov byte [es:0x07],0x0718 mov byte [es:0x08],'l'19 mov byte [es:0x09],0x0720 mov byte [es:0x0a],' '21 mov byte [es:0x0b],0x0722 mov byte [es:0x0c],"o"23 mov byte [es:0x0d],0x0724 mov byte [es:0x0e],'f'25 mov byte [es:0x0f],0x0726 mov byte [es:0x10],'f'27 mov byte [es:0x11],0x0728 mov byte [es:0x12],'s'29 mov byte [es:0x13],0x0730 mov byte [es:0x14],'e'31 mov byte [es:0x15],0x0732 mov byte [es:0x16],'t'33 mov byte [es:0x17],0x0734 mov byte [es:0x18],':'35 mov byte [es:0x19],0x0736 37 mov ax,number ;取得標(biāo)號number的偏移地址38 mov bx,1039 40 ;設(shè)置數(shù)據(jù)段的基地址,只是在同一個段,偏移地址是不一樣的41 mov cx,cs42 mov ds,cx43 44 ;求個位上的數(shù)字45 mov dx,046 div bx47 mov [0x7c00+number+0x00],dl ;保存?zhèn)€位上的數(shù)字48 49 ;求十位上的數(shù)字50 xor dx,dx51 div bx52 mov [0x7c00+number+0x01],dl ;保存十位上的數(shù)字53 54 ;求百位上的數(shù)字55 xor dx,dx56 div bx57 mov [0x7c00+number+0x02],dl ;保存百位上的數(shù)字58 59 ;求千位上的數(shù)字60 xor dx,dx61 div bx62 mov [0x7c00+number+0x03],dl ;保存千位上的數(shù)字63 64 ;求萬位上的數(shù)字 65 xor dx,dx66 div bx67 mov [0x7c00+number+0x04],dl ;保存萬位上的數(shù)字68 69 ;以下用十進(jìn)制顯示標(biāo)號的偏移地址70 mov al,[0x7c00+number+0x04]71 add al,0x3072 mov [es:0x1a],al ;將al寄存器中的ASCII數(shù)字傳送到顯示緩沖區(qū)73 mov byte [es:0x1b],0x04 ;下一字節(jié)存放顯示屬性,0x04代表:黑底紅字,無閃爍,無加亮74 75 mov al,[0x7c00+number+0x03]76 add al,0x3077 mov [es:0x1c],al78 mov byte [es:0x1d],0x0479 80 mov al,[0x7c00+number+0x02]81 add al,0x3082 mov [es:0x1e],al83 mov byte [es:0x1f],0x0484 85 mov al,[0x7c00+number+0x01]86 add al,0x3087 mov [es:0x20],al88 mov byte [es:0x21],0x0489 90 mov al,[0x7c00+number+0x00]91 add al,0x3092 mov [es:0x22],al93 mov byte [es:0x23],0x0494 95 mov byte [es:0x24],'D'96 mov byte [es:0x25],0x0797 98 infi: jmp near infi ;無限循環(huán),防止處理器再接著取下面的數(shù)據(jù),數(shù)據(jù)當(dāng)成指令取執(zhí)行會導(dǎo)致錯誤或運(yùn)行不正常99 100 number db 0,0,0,0,0 101 102 times 203 db 0 103 db 0x55,0xaa
  • 首先我們是要在屏幕上顯示字符串,所以需要將需要顯示的字符串的字符傳送到顯存中
  • 6行7行代碼:由第2節(jié)的內(nèi)容知顯存位于處理器尋址空間的0xB8000處。所以我們需要設(shè)置顯存的段地址為:0xb800 ,這里我們使用ES寄存器來表示顯存段地址(當(dāng)然也可以使用DS,但是DS還有其他用處,所以我們就使用ES寄存器)。
  • 10行-35行:顯示字符串"Label offset:"
  • 那么為什么每將一個字符傳送到顯存后,后面要繼續(xù)傳動一個0x07呢?實際上是這樣的:

    顯存中,每一個字符的ASCII碼后面跟的是該字符的顯示屬性。包括字符的顏色和背景色。如下圖:

    在8086下,80x25文本模式下的顏色表如下:

    由以上可知,我們顯示的字符屬性是0x07,黑底白字,無閃爍,無加亮。也就是黑底白字。

    10行-35行依次將字符寫入到緩存中,后面依次寫入字符的屬性。這很好理解!!!

  • 37行:取得標(biāo)號number的匯編地址。本代碼不光想在屏幕上顯示字符串Label offset:,還想將number的匯編地址顯示出來。number是一個標(biāo)號,標(biāo)號是它所在的地方的匯編地址。什么是匯編地址?
  • 實際上一個程序經(jīng)過編譯后,編譯器會給每一條代碼一個匯編地址,這個匯編地址實際上是從0開始。

    在分段機(jī)制中,偏移地址也是從0開始。實際上,這個匯編地址就是與偏移地址是對應(yīng)的。如下圖:

    理解了什么是匯編地址與偏移地址的關(guān)系后(不理解的看原書第五章),我們就來將number處的匯編地址在屏幕上顯示出來。

    number就代表那個地址的值。我這里已經(jīng)提前知道這個地址是:0x012E也就是十進(jìn)制302。

    由之前的學(xué)習(xí)內(nèi)容知道直接將302傳送到顯存的話,是不可能在屏幕上顯示302的。我們只能將302進(jìn)行拆分,將每一個數(shù)位都拆解出來,一個一個傳送給顯存。如何拆解?每次除以10…太簡單了就不寫了。

  • 38行:將bx寄存器賦值為10 ,作為下面除以10 的時候的除數(shù)。
  • 100行:這里為什么突然到100行了?不急,慢慢來,你分析程序也是跳來跳去的分析吧。
  • 我們既然想將number的匯編地址分解為一個個數(shù)位,就得找一個地方,將分解后的數(shù)字先咱是存起來。你可以想到用寄存器先存起來,但是寄存器,畢竟就那么8個通用的寄存器,而且本段代碼也用了好幾個了,所以這里無法使用寄存器來暫時存我們的數(shù)據(jù)。

    一個辦法就是在內(nèi)存找到一個地方,來存儲。這里,我們的主引導(dǎo)扇區(qū)是512字節(jié),我們寫的代碼很少不到300字節(jié),所以我們選擇在主引導(dǎo)扇區(qū)的最后先開辟一個空間用于存儲number的分解后的數(shù)字。

    那么第100行,就定義了五字節(jié)的數(shù)據(jù),賦值為0。當(dāng)然你也可以賦值為其他值,反正后面是呀被覆蓋的。

  • 41-42行:我們將DS寄存器指向代碼段,就是讓數(shù)據(jù)段寄存器DS與代碼段寄存器CS保持一致。因為我們這里將數(shù)據(jù)與代碼都放到一個段里面了,所以數(shù)據(jù)段與代碼段是一個段(正常不能不放到一個段,我們初學(xué),先這么寫,后面會分段) 其實用CS來訪問數(shù)據(jù)也可以,但是我們還是習(xí)慣用DS來訪問數(shù)據(jù),所以這里就有這么兩句賦值代碼。

  • 44-67行:求numberi的各個數(shù)位的數(shù)字,然后存到我們預(yù)先開辟好的空間中。

  • 70-93行:先將各個數(shù)位轉(zhuǎn)化成十進(jìn)制顯示,然后送入到顯存,在每一個字符后面寫入顯示屬性0x04,代表黑底紅字。

  • 95-96行:顯示字符D 以代表我們前面顯示的number地址是10進(jìn)制顯示的。黑底白字。

  • 98行:無限循環(huán),防止處理器再接著取下面的數(shù)據(jù),數(shù)據(jù)當(dāng)成指令取與執(zhí)行會導(dǎo)致錯誤或運(yùn)行不正常

  • 102行:由于主引導(dǎo)扇區(qū)是512字節(jié)的,我們寫的程序并沒有達(dá)到512字節(jié)。所以我們應(yīng)該將主引導(dǎo)扇區(qū)未滿的地方填滿。我們這里采取了一些特殊手段得知有203字節(jié)未填滿,搜易我們了連續(xù)聲明203個字節(jié)用于存儲0. 至于使用了什么特殊手段,不必要知道,因為后面的學(xué)習(xí)中會學(xué)習(xí)使用正常的的手段來得知這個未填滿的字節(jié)有多少。

  • 103行:一個有效的主引導(dǎo)扇區(qū),它的最后必須是0x55和0xaa。

  • 4、編譯主引導(dǎo)扇區(qū)代碼并加載運(yùn)行

    在上一篇文章,我們已經(jīng)安裝了VirtualBox 虛擬機(jī)軟件,并在里面創(chuàng)建了一臺名為LEARNASM的虛擬計算機(jī)。除此之外,還為它創(chuàng)建了一塊虛擬硬盤。

    然后我們參考書上4.2.4節(jié)的內(nèi)容,將我們匯編代碼編譯好的二進(jìn)制bin文件寫到虛擬硬盤的主引導(dǎo)扇區(qū)中。啟動虛擬機(jī),就會運(yùn)行我們寫的代碼,運(yùn)行結(jié)果如下:

    今天的程序運(yùn)行的很順利。

    5、總結(jié)

    了解匯編的運(yùn)行機(jī)制,對以后深入學(xué)習(xí)高級語言,很有幫助:比如JVM。

    筆記記得不是很全,像匯編的語法以及如何將代碼寫到虛擬硬盤的主引導(dǎo)扇區(qū)這些都沒有寫。如果又不懂的可以加我聯(lián)系方式一起交流。

    學(xué)習(xí)探討加個人:
    qq:1126137994
    微信:liu1126137994

    總結(jié)

    以上是生活随笔為你收集整理的【OS学习笔记】六 实模式:编写主引导扇区代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。