版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
word格式-可編輯-感謝下載支持通make生成執(zhí)行文件的過程操作系統(tǒng)鏡像文件ucore.img是如何一步一步生成的在編譯時(shí)使用makeV=,相當(dāng)于設(shè)置一個(gè)標(biāo)記,使得把make編譯執(zhí)行的過程全部展示出來。首先,調(diào)用了GCC,把一些C的源代碼編譯成.O的目標(biāo)文件。然后,調(diào)用了ld,把這些目標(biāo)文件準(zhǔn)換成一個(gè)可執(zhí)行程序,比如下面示例,轉(zhuǎn)換成為了bootloader的一個(gè)執(zhí)行程序bootblock.out。最后,調(diào)用了dd,把bootloader、bootblock和kernel放到虛擬的硬盤uCore.img里面。硬盤的主引導(dǎo)扇區(qū)的特征是什么在sign.c中,先申請(qǐng)了一個(gè)512字節(jié)的空間buf,然后將buf初始化為全0,再將主引導(dǎo)程序?qū)懭脒@個(gè)空間,最后,在buf的最后兩個(gè)字節(jié)寫入55AA。所以硬盤的主引導(dǎo)扇區(qū)的特征是主引導(dǎo)扇區(qū)的512個(gè)字節(jié)的最后兩個(gè)字節(jié)是55AA。使用qemu執(zhí)行并調(diào)試lab1中的軟件從啟動(dòng)開始,單步跟蹤BIOS的執(zhí)行實(shí)驗(yàn)遠(yuǎn)程調(diào)用的方法,啟動(dòng)qemu,并讓它進(jìn)入-S狀態(tài)。開啟另外一個(gè)終端,執(zhí)行g(shù)db命令,綁定端口1234。在QEMU窗口中使用x/10i$pc查看最近10條指令的反匯編內(nèi)容。在gdb中使用si命令執(zhí)行單步,顯示位置??梢钥吹揭粏?dòng),就處于0xfffffff0的位置,第一條指令是個(gè)長跳轉(zhuǎn)指令。在初始化位置0x7c00設(shè)置實(shí)地址斷點(diǎn),測(cè)試斷點(diǎn)正常輸入b*0x7c00設(shè)置斷點(diǎn),輸入c執(zhí)行到斷點(diǎn)。輸入x/10i$pc查看最近10條指令的反匯編內(nèi)容,可以看到qemu執(zhí)行到斷點(diǎn)0x7c00。斷點(diǎn)工作正常。再次輸入c執(zhí)行,qemu繼續(xù)工作。得到結(jié)論,斷點(diǎn)工作正常。從0x7c00開始跟蹤代碼運(yùn)行,將單步跟蹤反匯編得到的代碼與bootasm.S和bootblock.asm進(jìn)行比較經(jīng)過比較發(fā)現(xiàn):gdb得到的反匯編代碼與bootasm.S和bootblock.asm中的代碼基本相一致。找一個(gè)bootloader或內(nèi)核中的代碼位置,設(shè)置斷點(diǎn)并進(jìn)行測(cè)試輸入b*0x7c10設(shè)置斷點(diǎn),輸入c執(zhí)行到斷點(diǎn)。輸入x/10i$pc查看最近10條指令的反匯編內(nèi)容。輸入stepi,單步執(zhí)行一條機(jī)器指令。再一次輸入x/10i$pc查看最近10條指令的反匯編內(nèi)容。最后,輸入c,qemu繼續(xù)工作。分析bootloader進(jìn)入保護(hù)模式的過程從%cs=0$,pc=0x7c00進(jìn)入bootloader。.globlstartstart: 準(zhǔn)備:將中斷標(biāo)志位清0,不允許中斷,設(shè)置增址,將段寄存器置0。 .code16cli cld xorw%ax,%axmovw%ax,%dsmovw%ax,%esmovw%ax,%ss開啟A20:通過將鍵盤控制器上的A20線置于高電位,使全部32條地址線可用,進(jìn)而可以訪問4G的內(nèi)存空間。 seta20.1: #等待8042鍵盤控制器不忙inb$0x64,%altestb$0x2,%aljnzseta20.1movb$0xd1,%al#發(fā)送寫8042輸出端口的指令outb%al,$0x64seta20.2: #等待8042鍵盤控制器不忙inb$0x64,%altestb$0x2,%aljnzseta20.2movb$0xdf,%al#打開A20outb%al,$0x60 加載GDTR、初始化GDT表:GDT表和其描述符已經(jīng)靜態(tài)儲(chǔ)存在引導(dǎo)區(qū)中,載入即可。 lgdtgdtdesc進(jìn)入保護(hù)模式:通過將cr0寄存器PE位置1便開啟了保護(hù)模式。 movl%cr0,%eax orl$CR0_PE_ON,%eax movl%eax,%cr0通過長跳轉(zhuǎn)更新cs的基地址。 ljmp$PROT_MODE_CSEG,$protcseg.code32protcseg:設(shè)置段寄存器,并建立堆棧。 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完成進(jìn)入保護(hù)模式,進(jìn)入bootmain。 callbootmain分析bootloader加載ELF格式的OS的過程bootloader讀取硬盤扇區(qū)readsect函數(shù)可以從設(shè)備的第secno扇區(qū)讀取數(shù)據(jù)到dst位置。設(shè)置讀取扇區(qū)的數(shù)目為、扇區(qū)號(hào),讀取扇區(qū)。 outb(0x1F2,1); outb(0x1F3,secno&0xFF); outb(0x1F4,(secno>>8)&0xFF); outb(0x1F5,(secno>>16)&0xFF); outb(0x1F6,((secno>>24)&0xF)|0xE0); outb(0x1F7,0x20);讀取一個(gè)扇區(qū)。 insl(0x1F0,dst,SECTSIZE/4);readseg函數(shù)包裝了readsect,使得可以從設(shè)備讀取任意長度的內(nèi)容。 bootloader加載ELF格式的OS讀取ELF的頭部。readseg((uintptr_t)ELFHDR,SECTSIZE*8,0);判斷是否是合法的ELF文件。if(ELFHDR->e_magic!=ELF_MAGIC){ gotobad;}根據(jù)ELFheader和proghdr程序頭,讀出代碼段和數(shù)據(jù)段,并且加載到相應(yīng)地方。ph=(structproghdr*)((uintptr_t)ELFHDR+ELFHDR->e_phoff); eph=ph+ELFHDR->e_phnum; for(;ph<eph;ph++){ readseg(ph->p_va&0xFFFFFF,ph->p_memsz,ph->p_offset);根據(jù)ELF頭部儲(chǔ)存的入口信息,找到內(nèi)核的入口。 ((void(*)(void))(ELFHDR->e_entry&0xFFFFFF))();實(shí)現(xiàn)函數(shù)調(diào)用堆棧跟蹤函數(shù)因?yàn)閟s:ebp指向的堆棧位置儲(chǔ)存著跳轉(zhuǎn)之前的ebp,所有,以此為線索可以得到所有使用堆棧的函數(shù)ebp。ss:ebp+4指向的是調(diào)用時(shí)的eip,ss:ebp+8等是參數(shù)。又因?yàn)閎ootloader設(shè)置的堆棧從0x7c00開始,使用"callbootmain"轉(zhuǎn)入bootmain函數(shù),所以,堆棧最深一層值為ebp:0x00007bf8eip:0x00007d68。代碼分析:得到當(dāng)前ebp,eip。uint32_tebp=read_ebp(),eip=read_eip();輸出ebp,eip。cprintf("ebp:0x%08xeip:0x%08xargs:",ebp,eip);設(shè)置指針,輸出四個(gè)參數(shù)。uint32_t*args=(uint32_t*)ebp+2;for(j=0;j<4;j++){cprintf("0x%08x",args[j]);}調(diào)用print_debuginfo函數(shù)完成查找對(duì)應(yīng)函數(shù)名并打印至屏幕。print_debuginfo(eip-1);獲取上一層eip,ebp。eip=((uint32_t*)ebp)[1];ebp=((uint32_t*)ebp)[0];完善中斷初始化和處理中斷向量表中一個(gè)表項(xiàng)占多少字節(jié)?其中哪幾位代表中斷處理代碼的入口?中斷向量表一個(gè)表項(xiàng)占用8字節(jié),其中2-3字節(jié)是段選擇子,0-1字節(jié)和6-7字節(jié)拼成位移,兩者聯(lián)合便是中斷處理程序的入口地址。完善對(duì)中斷向量表進(jìn)行初始化的函數(shù)idt_init獲得IDT表的入口地址。externuintptr_t__vectors[];在中斷門描述符表建立中斷門描述符,其中存儲(chǔ)了中斷處理例程 的代碼段GD_KTEXT和偏移量__vectors[i],特權(quán)級(jí)為 DPL_KERNEL。通過查詢idt[i]就可定位到中斷服務(wù)例程的起始地 址。for(i=0;i<sizeof(idt)/sizeof(structgatedesc);i++){ SETGATE(idt[i],0,GD_KTEXT,__vectors[i],DPL_KERNEL);}通過指令lidt把中斷門描述符表的起始地址裝入IDTR寄存器中。lidt(&idt_pd);完善對(duì)時(shí)鐘中斷進(jìn)行處理的部分當(dāng)ticks每加100次后(大約1秒),輸出“100ticks”。ticks++;if(ticks%TICK_NUM==0){ print_ticks();}擴(kuò)展練習(xí)從內(nèi)核空間切換到用戶空間調(diào)用lab1_switch_to_user函數(shù)進(jìn)行從內(nèi)核空間到用戶空間的切換,lab1_switch_to_user函數(shù)內(nèi)容如下:asmvolatile(從中斷返回時(shí),會(huì)多pop兩位,并用這兩位的值更新ss、sp,所以要先把棧壓兩位。 "sub$0x8,%%esp\n"調(diào)用T_SWITCH_TOU號(hào)中斷。 "int%0\n"修復(fù)esp。 "movl%%ebp,%%esp" ::"i"(T_SWITCH_TOU));調(diào)用T_SWITCH_TOU號(hào)中斷代碼如下:if(tf->tf_cs!=USER_CS){設(shè)置switchk2u。switchk2u=*tf;將cs,ds,es,ss設(shè)置為用戶態(tài)。switchk2u.tf_cs=USER_CS;switchk2u.tf_ds=switchk2u.tf_es=switchk2u.tf_ss=USER_DS;設(shè)置esp值。switchk2u.tf_esp=(uint32_t)tf+sizeof(structtrapframe)-8;設(shè)置eflags值。switchk2u.tf_eflags|=FL_IOPL_MASK;設(shè)置新棧頂指向switchk2u,當(dāng)返回出棧,則出棧switchk2u中的 值。*((uint32_t*)tf-1)=(uint32_t)&switchk2u;}從用戶空間切換到內(nèi)核空間調(diào)用lab1_switch_to_kernel函數(shù)進(jìn)行從內(nèi)核空間到用戶空間的切換,lab1_switch_to_kernel函數(shù)內(nèi)容如下:asmvolatile(調(diào)用T_SWITCH_TOK號(hào)中斷。 "int%0\n"從中斷返回時(shí),esp仍在TSS指示的堆棧中。所以要在從中斷返 回后修復(fù)esp。 "movl%%ebp,%%esp" ::"i"(T_SWITCH_TOK));調(diào)用T_SWITCH_TOK號(hào)中斷代碼如下:if(tf->tf_cs!=KERNEL_CS){將cs,ds,es設(shè)置為內(nèi)核態(tài)。 tf->tf_cs=KERNEL_CS; tf->tf_ds=tf->tf_es=KERNEL_DS;設(shè)置eflags值。 tf->tf_eflags&=~FL_IOPL_MASK;設(shè)置switchu2k值。switchu2k=(structtrapframe*)(tf->tf_esp-(sizeof(structtrapframe)-8));用tf值覆蓋switchu2k值。memmove(switchu2k,tf,sizeof(structtrapframe)-8);設(shè)置新棧頂指向switchk2u,當(dāng)返回出棧,則出棧switchk2u中的值。*((uint32_t*)tf-1)=(uint32_t)switchu2k;}問題配置環(huán)境我首先主要遇到的問題是安裝一個(gè)代碼閱讀的工具,因?yàn)榇a量比較大而且函數(shù)間相互調(diào)用很多。最后安裝了understand,首先下載軟件壓縮包,然后解壓到安裝目錄,再添加路徑,最后輸入證書號(hào)。還有一個(gè)是在運(yùn)行makeqemu時(shí)報(bào)錯(cuò),解決辦法是:建立符號(hào)鏈接文件”ln-s/usr/local/bin/qenu-system-i386/usr/local/bin/qemu”。在練習(xí)2時(shí),設(shè)置斷點(diǎn)在0x7c20時(shí),沒有在斷點(diǎn)處停止后來才了解到設(shè)置斷點(diǎn)時(shí),斷點(diǎn)處的信息會(huì)被修改,有時(shí)由于設(shè)置斷點(diǎn)剛好設(shè)置在一條指令中間,這樣信息修改后,原指令一部分未被覆蓋,與斷點(diǎn)的機(jī)器碼可能恰好組成其他的指令,所以沒有停止。所以,設(shè)置斷點(diǎn)時(shí)應(yīng)該注意要設(shè)置在一條指令完成之后,而不要設(shè)置在一條指令中間。在練習(xí)4,無法理解readseg((uintptr_t)ELFHDR,SECTSIZE*8,0)在詢問后知道,這句代碼并不是獲取bootloader,而是獲取讀取ELF文件的頭部,所以大小不是512字節(jié),應(yīng)該是512*8字節(jié),也就是一頁4k。在練習(xí)5,無法理解堆棧最深一層值為ebp:0x00007bf8查閱后知道,在編譯器會(huì)在每個(gè)函數(shù)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 租借游艇問題課程設(shè)計(jì)
- 算法綜合設(shè)計(jì)課程設(shè)計(jì)
- 補(bǔ)貨管理的優(yōu)化與實(shí)施方案計(jì)劃
- 健身器材銷售業(yè)績總結(jié)
- 2024年煙花爆竹安全的應(yīng)急預(yù)案
- 銀行工作總結(jié)創(chuàng)新發(fā)展成果彰顯
- 醫(yī)藥包材采購心得總結(jié)
- 娛樂活動(dòng)行業(yè)顧問工作總結(jié)提升娛樂活動(dòng)吸引力
- 服務(wù)業(yè)會(huì)計(jì)工作內(nèi)容分析
- 2024年設(shè)備的管理制度范本
- 山東省濟(jì)南市2023-2024學(xué)年高一上學(xué)期期末考試生物試題(解析版)
- 2025年工程春節(jié)停工期間安全措施
- 2024版人才引進(jìn)住房租賃補(bǔ)貼協(xié)議3篇
- 川藏鐵路勘察報(bào)告范文
- 新零售智慧零售門店解決方案
- 小學(xué)一年級(jí)數(shù)學(xué)20以內(nèi)的口算題(可直接打印A4)
- 上海黃浦區(qū)2025屆物理高一第一學(xué)期期末質(zhì)量跟蹤監(jiān)視模擬試題含解析
- 肺結(jié)核課件教學(xué)課件
- 新生兒心臟病護(hù)理查房
- 規(guī)劃設(shè)計(jì)行業(yè)數(shù)字化轉(zhuǎn)型趨勢(shì)
- 2024年廣告代理合同的廣告投放范圍與分成比例
評(píng)論
0/150
提交評(píng)論