ucore作業系統lab1實驗準備知識

2021-07-02 22:18:37 字數 4523 閱讀 6222

虛擬環境:virtualbox

操作環境:utunbu 10.04

編譯環境:gcc-4.6.x

作業系統是乙個軟體,也需要通過某種機制載入並執行它。在這裡我們將通過另外乙個更加簡單的軟體-bootloader來完成這些工作。為此,我們需要完成乙個能夠切換到x86的保護模式並顯示字元的bootloader,為啟動作業系統ucore做準備。lab1提供了乙個非常小的bootloader和ucore os,整個bootloader執行**小於512個位元組,這樣才能放到硬碟的主引導扇區中。

知識目標:

bootloader軟體

ucore os軟體

準備知識:

1、x86啟動順序

首先,當系統加電的時候一些基本的暫存器會被置成固定的初值,簡單列舉如下:

base:0xffff0000

eip:0xfff0

cs:0xf000

eax:0x0000

然而,我們知道x86的啟動位址為base+eip的值,即為0xfffffff0。它指向乙個bios的eprom區域,通常所含的內容是乙個長跳轉指令,它會跳到1m左右的地方去執行,在那裡bios將進行相應的檢查並將bootloader載入到記憶體0x7c00的位置。

需要注意,由於在實模式下我們需要20位的位址,而cs是16位的暫存器,所以實模式下,我們將cs暫存器的內容左移4位+eip的位址,構成了實模式下的20位定址空間(1m)。具體實模式與保護模式說明如下:

實模式:這是個人計算機早期的8086處理器採用的一種簡單執行模式,當時微軟的ms-dos作業系統主要就是執行在8086的實模式下。80386加電啟動後處於實模式執行狀態,在這種狀態下軟體可訪問的物理記憶體空間不能超過1mb,且無法發揮intel 80386以上級別的32位cpu的4gb記憶體管理能力。實模式將整個物理記憶體看成分段的區域,程式**和資料位於不同區域,作業系統和使用者程式並沒有區別對待,而且每乙個指標都是指向實際的實體地址。這樣使用者程式的乙個指標如果指向了作業系統區域或其他使用者程式區域,並修改了內容,那麼其後果就很可能是災難性的。

保護模式:保護模式的乙個主要目標是確保應用程式無法對作業系統進行破壞。實際上,80386就是通過在實模式下初始化控制暫存器(如gdtr,ldtr,idtr與tr等管理暫存器)以及頁表,然後再通過設定cr0暫存器使其中的保護模式使能位置位,從而進入到80386的保護模式。當80386工作在保護模式下的時候,其所有的32根位址線都可供定址,物理定址空間高達4gb。在保護模式下,支援記憶體分頁機制,提供了對虛擬記憶體的良好支援。保護模式下80386支援多工,還支援優先順序機制,不同的程式可以執行在不同的特權級上。特權級一共分0~3四個級別,作業系統執行在最高的特權級0上,應用程式則執行在比較低的級別上;配合良好的檢查機制後,既可以在任務間實現資料的安全共享也可以很好地隔離各個任務。

接下來我們具體來看看bootloader都做了些什麼,顯然,它就是讀取mbr的所在的第乙個扇區(512kb)的一段引導程式,它雖然十分短小卻實現了以下三大功能:

①由實模式向保護模式的切換。並將段機制使能。

具體來說就是將cr0暫存器的最高位置1,即-|0x8000000,使具有4g定址能力和相應的段機制。

關於段機制的內容,在實現時再具體說明。

②讀取ucore kernel到記憶體。

elfhdr(elf格式頭)→找到**段(prohdr)

③跳到ucore os入口點位址。

2、c函式呼叫的實現

push al(暫存器壓棧。不是所有的)

引數壓棧。。。

call foo(將返回位址壓棧)

pop引數

pop al(暫存器內容彈出)

foo:

push %ebp    儲存ebp資訊

movl %esp,%ebp 將ebp的內容置為esp

popl %ebp   恢復ebp的值

ret    返回主調位址執行

3、gcc內聯彙編

使用gcc內聯彙編的例子如下:

#define read_cr0() ()
它代表什麼含義呢?這需要從其基本格式講起。gcc內聯彙編的基本格式是:

asm [volatile] ( assembler template

: output operands

[ : input operands

[ : clobbers ] ])

:"=r" (__dummy)
「=r」表示相應的目標運算元(指令部分的%0)可以使用任何乙個通用暫存器,並且變數__dummy 存放在這個暫存器中,但如果是:

:「=m」(__dummy)
「=m」就表示相應的目標運算元是存放在記憶體單元__dummy中。表示約束條件的字母很多,下表給出幾個主要的約束字母及其含義:

字母含義

m, v, o

記憶體單元

r任何通用暫存器

q暫存器eax, ebx, ecx,edx之一

i, h

直接運算元

e, f

浮點數g

任意a, b, c, d

暫存器eax/ax/al, ebx/bx/bl, ecx/cx/cl或edx/dx/dl

s, d

暫存器esi或edi

i常數(0~31)

輸入部分(input operand list):輸入部分與輸出部分相似,但沒有「=」。如果輸入部分乙個運算元所要求使用的暫存器,與前面輸出部分某個約束所要求的是同乙個暫存器,那就把對應運算元的編號(如「1」,「2」等)放在約束條件中。在後面的例子中,可看到這種情況。修改部分(clobber list,也稱 亂碼列表):這部分常常以「memory」為約束條件,以表示操作完成後記憶體中的內容已有改變,如果原來某個暫存器的內容來自記憶體,那麼現在記憶體中這個單元的內容已經改變。亂碼列表通知編譯器,有些暫存器或記憶體因內聯彙編塊造成亂碼,可隱式地破壞了條件暫存器的某些位(字段)。 注意,指令部分為必選項,而輸入部分、輸出部分及修改部分為可選項,當輸入部分存在,而輸出部分不存在時,分號「:「要保留,當「memory」存在時,三個分號都要保留,例如

#define __cli() __asm__ __volatile__("cli": : :"memory")
下面是乙個例子:

int count=1;

int value=1;

int buf[10];

void main()

得到的主要彙編**為:

movl count,%ecx

movl value,%eax

movl buf,%edi

cldrep

stosl

cld,rep,stos這幾條語句的功能是向buf中寫上count個value值。冒號後的語句指明輸入,輸出和被改變的暫存器。通過冒號以後的語句,編譯器就知道你的指令需要和改變哪些暫存器,從而可以優化暫存器的分配。其中符號"c"(count)指示要把count的值放入ecx暫存器。類似的還有:

a eax

b ebx

c ecx

d edx

s esi

d edi

i 常數值,(0 - 31)

q,r 動態分配的暫存器

g eax,ebx,ecx,edx或記憶體變數

a 把eax和edx合成乙個64位的暫存器(use long longs)

也可以讓gcc自己選擇合適的暫存器。如下面的例子:

asm("leal (%1,%1,4),%0"

: "=r" (x)

: "0" (x)

);

這段**到的主要彙編**為:

movl x,%eax

leal (%eax,%eax,4),%eax

movl %eax,x

幾點說明:

4、x86中斷處理過程

①找到中斷描述符表(idt)的位址idtr

②通過相應index找到中斷門(陷阱門)

③到gdt(段描述符表)中去獲取特權級和入口位址資訊

④進入isr(中斷服務例程)尋找中斷的型別對應程式

根據不同的呼叫所建立的棧是不同:

核心態中斷:只用一套棧,只壓入eflags、cs、eip、error code等資訊

使用者態的呼叫:需要乙個使用者棧,和乙個核心棧,核心棧除了儲存上述資訊外還需要ss、esp儲存使用者棧的棧頂和基址.

中斷結束會呼叫iret

最後說明以下三條語句的區別:

iret:(在核心中的中斷)彈出eflags,cs,eip

(從使用者態呼叫)彈出eip,cs,eflags,esp,ss

ret:只彈eip

retf:彈出cs,eip

基於ucore的作業系統實驗lab1

練習1.1 1 先編譯鏈結生成kernel檔案 2 再編譯鏈結生成bootblock檔案 3 生成ucore.imgsign.c生成bootblock 1.2 檢視sign.c可以發現關鍵在於bootblock.out小於510bytes,且 buf 510 0x55 buf 511 0xaa 練習...

ucore作業系統 lab1 練習二 實驗報告

為了熟悉使用qemu和gdb進行的除錯工作,我們進行如下的小練習 從cpu加電後執行的第一條指令開始,單步跟蹤bios的執行。在初始化位置0x7c00設定實位址斷點,測試斷點正常。從0x7c00開始跟蹤 執行,將單步跟蹤反彙編得到的 與bootasm.s和bootblock.asm進行比較。自己找乙...

ucore作業系統 lab1 練習四 實驗報告

1.bootloader如何讀取硬碟扇區的?2.bootloader是如何載入elf格式的os?讀乙個扇區的大致流程 1.等待磁碟準備好 2.發出讀取扇區的命令 3.等待磁碟準備好 4.把磁碟扇區資料讀到指定記憶體 實際操作中,需要知道怎樣與硬碟互動。所有的io操作是通過cpu訪問硬碟的io位址暫存...