練習1.1
1、先編譯鏈結生成kernel檔案
2、再編譯鏈結生成bootblock檔案
3、生成ucore.imgsign.c生成bootblock
1.2 檢視sign.c可以發現關鍵在於bootblock.out小於510bytes,且 buf[510] = 0x55; buf[511] = 0xaa;
練習2.1 從 cpu 加電後執行的第一條指令開始,單步跟蹤 bios 的執行。
單步跟蹤,方法如下:
1 修改 lab1/tools/gdbinit,內容為:
2 在 lab1目錄下,執行set architecture
i8086
target remote
:1234
make debug
3 在看到gdb的除錯介面(gdb)後,在gdb除錯介面下執行如下命令
si
即可單步跟蹤bios了。
4 在gdb介面下,可通過如下命令來看bios的**
練習2.2 在初始化位置0x7c00設定實位址斷點,測試斷點正常。x /2i $pc
//顯示當前eip處的彙編指令
在gdb中輸入一下命令
得到b *0x7c00
//在0x7c00處設定斷點。此位址是bootloader入口點位址,可看boot/bootasm.s的start位址處
c
//continue簡稱,表示繼續執行
x /2i $pc
//顯示當前eip處的彙編指令
breakpoint 2,
0x00007c00 in ?? ()
練習2.3 從0x7c00開始跟蹤**執行,將單步跟蹤反彙編得到的**與bootasm.s和 bootblock.asm進行比較。=> 0x7c00: cli
0x7c01: cld
將2.2中的步驟重複實現與兩個檔案進行對比發現是一致的
練習2.4 自己找乙個bootloader或核心中的**位置,設定斷點並進行測試。
自己按以上步驟測試一下就行了
練習3.1 分析bootloader進入保護模式的過程。
它先將各個暫存器置0
初始化gdt表:乙個簡單的gdt表和其描述符已經靜態儲存在引導區中,載入即可movw $prot_mode_dseg, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
movl $0x0, %ebp
movl $start, %esp
lgdt gdtdesc
進入保護模式:通過將cr0暫存器pe位置1便開啟了保護模式
通過長跳轉更新cs的基位址movl %cr0, %eax
orl $cr0_pe_on, %eax
movl %eax, %cr0
設定段暫存器,並建立堆疊ljmp
$prot_mode_cseg, $protcseg
.code32
protcseg:
轉到保護模式完成,進入boot主方法movw $prot_mode_dseg, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
movl $0x0, %ebp
movl $start, %esp
call bootmain
練習4 分析bootloader載入elf格式的os的過程。
首先看readsect函式,
readsect
從裝置的第secno扇區讀取資料到dst位置
readseg簡單包裝了readsect,可以從裝置讀取任意長度的內容。static
void
readsect(void
*dst, uint32_t secno)
在bootmain函式中,static
void
readseg(uintptr_t
va, uint32_t count, uint32_t offset)
}
練習5void
bootmain(void)
struct proghdr *ph, *eph;
// elf頭部有描述elf檔案應載入到記憶體什麼位置的描述表,
// 先將描述表的頭位址存在ph
ph = (struct proghdr *)((uintptr_t)elfhdr +
elfhdr->e_phoff);
eph = ph + elfhdr->e_phnum;
// 按照描述表將elf檔案中資料載入記憶體
for (; ph < eph; ph ++)
// elf檔案0x1000位置後面的0xd1ec位元被載入記憶體0x00100000
// elf檔案0xf000位置後面的0x1d20位元被載入記憶體0x0010e000
// 根據elf頭部儲存的入口資訊,找到核心的入口
((void (*)(void))(elfhdr->e_entry &
0xffffff))();
bad:
outw(0x8a00, 0x8a00);
outw(0x8a00, 0x8e00);
while (1);
}
實現函式呼叫堆疊跟蹤函式
ss:ebp指向的堆疊位置儲存著caller的ebp,以此為線索可以得到所有使用堆疊的函式ebp。
ss:ebp+4指向caller呼叫時的eip,ss:ebp+8等是(可能的)引數。
輸出中,堆疊最深一層為
ebp:0x00007bf8
eip:0x00007d68 \
args:0x00000000
0x00000000 0x00000000 0x00007c4f
: -- 0x00007d67 --
ucore作業系統lab1實驗準備知識
虛擬環境 virtualbox 操作環境 utunbu 10.04 編譯環境 gcc 4.6.x 作業系統是乙個軟體,也需要通過某種機制載入並執行它。在這裡我們將通過另外乙個更加簡單的軟體 bootloader來完成這些工作。為此,我們需要完成乙個能夠切換到x86的保護模式並顯示字元的bootloa...
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位址暫存...