清華大學(xué)操作系統(tǒng)實驗lab1實驗報告_第1頁
清華大學(xué)操作系統(tǒng)實驗lab1實驗報告_第2頁
清華大學(xué)操作系統(tǒng)實驗lab1實驗報告_第3頁
清華大學(xué)操作系統(tǒng)實驗lab1實驗報告_第4頁
清華大學(xué)操作系統(tǒng)實驗lab1實驗報告_第5頁
已閱讀5頁,還剩10頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

練習(xí)1、理解通過make生成執(zhí)行文件的過程。[練習(xí)1.1]操作系統(tǒng)鏡像文件ucore.img是如何一步一步生成的?在projl執(zhí)行命令make2=可以得到make指令執(zhí)行的過程makeV=+ccboot/bootasm.Sgcc-Iboot/-fno-builtin-Wall-ggdb-m32-nostdinc-fno-stack-protector-Ilibs/-Os-nostdinc-cboot/bootasm.S-oobj/boot/bootasm.o+ccboot/bootmain.cgcc-Iboot/-fno-builtin-Wall-ggdb-m32-nostdinc-fno-stack-protector-Ilibs/-Os-nostdinc-cboot/bootmain.c-oobj/boot/bootmain.o+cctools/sign.cgcc-Itools/-g-Wall-02-ctools/sign.c-oobj/sign/tools/sign.ogcc-g-Wall-O2obj/sign/tools/sign.o-obin/sign+ldbin/bootblockld-melf_i386-N-estart-Ttext0x7C00obj/boot/bootasm.oobj/boot/bootmain.o-oobj/bootblock.o'obj/bootblock.out'size:440bytesbuild512bytesbootsector:'bin/bootblock'success!ddif=/dev/zeroof=bin/ucore.imgcount=10000記錄了10000+0的讀入記錄了10000+0的寫出5120000字節(jié)(5.1MB)已復(fù)制,0.0227439秒,225MB/秒ddif=bin/bootblockof=bin/ucore.imgconv=notrunc記錄了1+0的讀入記錄了1+0的寫出512字節(jié)(512B)已復(fù)制,0.000214966秒,2.4MB/秒從這幾條指令中可以看出需要生成ucore.img首先需要生成bootblock,而生成bootblock需要先生成bootmain.o和bootasm.o還有sign,這三個文件又分別由bootmain.c、bootasm.S、sigh.c來生成。ld-m elf_i386-N-estart-Ttext0x7C00obj/boot/bootasm.oobj/boot/bootmain.o-oobj/bootblock.o這句話用于生成bootblock,elf_i386表示生成elf頭,0x7C00為程序的入口。'obj/bootblock.out'size:440bytes這句話表示生成的bootblock的文件大小,因為大小不到512字節(jié),所以需要給blootblock填充,填充的功能在sign.c中有所體現(xiàn),最后兩字節(jié)設(shè)置為了0x55,0xAAbuf[510]=0x55;buf[511]=0xAA;FILE*ofp=fopen(argv[2],"wb+");size=fwrite(buf,1,512,ofp);[練習(xí)1.2]一個被系統(tǒng)認為是符合規(guī)范的硬盤主引導(dǎo)扇區(qū)的特征是什?么前面已經(jīng)提到過:引導(dǎo)扇區(qū)的大小為512字節(jié),最后兩個字節(jié)為標(biāo)志性結(jié)束字節(jié)0x55,OxAA,做完這樣的檢查才能認為是符合規(guī)范的磁盤主引導(dǎo)扇區(qū)。Sign.c文件中有作檢查:if(size!=512){fprintf(stderr,"write'%s'error,sizeis%d.\n",argv[2],size);return-1;}練習(xí)2:使用qemu執(zhí)行并調(diào)試labl中的軟件。[練習(xí)2.1]從CPU加電后執(zhí)行的第一條指令開始,單步跟蹤BIOS的執(zhí)行。[練習(xí)2?2]在初始化位置刃刖設(shè)置實地址斷點測試斷點正常。[練習(xí)2?3]在調(diào)用qemu時增加in_asm-Dq.log參數(shù),便可以將運行的匯編指令保存在Jog中。將執(zhí)行的匯編代碼與ootasm?S和bootblock.asm進行比較,看看二者是否一致。實驗是基于老lab1/proj1做的,練習(xí)開始時是打算用命令行一句一句執(zhí)行得到結(jié)果的,后來發(fā)現(xiàn)直接修改nake刑e和gdbinit可以大大提高調(diào)試效率。于是在makefile中增加以下代碼Iab1-mon:$(UCOREIMG)$(V)$(TERMINAL)-e"$(QEMU)-S-s-din_asm-D$(BINDIR)/q.Iog-monitorstdio-hda$<-serialnull"$(V)sleep2$(V)$(TERMINAL)-e"gdb-q-tui-xtools/gdbinit"-S-s是使得qemu在執(zhí)行第一條指令之前停下來,在調(diào)用emu時增加■din_asm-Dq.log參數(shù),便可以將運行的匯編指令保存在Jog中。然后sleep兩秒應(yīng)該是給qemu充分的時間準(zhǔn)備等待連接。接下來使用DB調(diào)試工具,-tui提供了代碼與命令行分屏查看的界面tools/gdbinit中存放的是gdb調(diào)試指令如下。fileobj/bootblock.otargetremote:1234setarchitecturei8086b*0x7c00continuex/10i$pc先是加載調(diào)試文件然后連接qemu,設(shè)置8086的實模式,設(shè)置斷點Ox7c00,也就是bootloader的第一條指令,然后運行到斷點。再顯示接下來的3條指令。運行結(jié)果圖如下

B+>Terminalstart:.crotlEi辰115cid1713尊B(yǎng)+>Terminalstart:.crotlEi辰115cid1713尊sexupthe19X(>?塔ax#KaxZDnovw%ds21mo'/w常ax#?ies22HOW%ax,%552324#EnableA2G:25JfForbackwaBootingfremHardDisk…、snpEtlbllAtywiththe P匸?phygtrenoteThread1in:startItne:15PC:OX7CO0renoteThread1in:startThetargetarchitectureisassumedtobe1S08CBreakpoint1atGx7c00:fiteboot/bootasm.S,lineIS,ell

eldBreakpoint1pEtmrt()atboot/bootasn.SrlS"0x7c00cstart>:ell

eldoxzcai<start+l>:---Type*;return>tocontinuetorq<;return》toquit--0x7c04^start+4>;novWax^dsax7c06<start+6>:novStes0k7c08<stsrt+8?:nov0X7CO3-£seta20.1^:tn$0x&4^al0k7c0c<seta26.l+2>:test$0xZ,94olax7coe<seta2B.l+4>:jneax7toatseta20.1>3k7c10r?」l、 <seta20.l+6>:nov$3xdl,%al很明顯,斷點位置的代碼和ootem文件中的代碼完全一致,說明斷點設(shè)置成功。打開Jog文件看,看到了很奇葩的結(jié)果。能夠看到Cd之類熟悉的指令,但是他們的地址以及出現(xiàn)的順序都不是想象的那樣(從0x0x00007c00k開始,第一條指令為陽丿。 IN;OxfffffffO:Ljnp $OxeeSb|4IM;Gk^&Of?BE6-kgtOx!&&0f?C68iIM!0X&&Ofee5b:cnpl $6x9,SC5:0x65a4:jne 6xfd;2.b9ie111213J.4之后聽大神解釋,在q.log中進入BIOS之后的跳轉(zhuǎn)地址與實際應(yīng)跳轉(zhuǎn)地址不相符,匯編代碼也與bootasm.S和bootblock.asm不相同。

可以通過makedebug之后在qemu的控制臺中輸入x/10i$pc看到BIOS執(zhí)行bootloader部分的代碼?!?j■~~1 MkjBfBy-H j]T?■■■■■■■■?4U* ■rCl00QEMU[Stopp&d]?ompat_rfionitorOconsole{EMU2.0.0ncm辻ctr[qemu)x/10i$pc)x0000?c00:cli)x0000?c01:cld-type'help"fopworeinformation)x00007cG2;xorzax,zax)x00007c04;mouzax,zds)x00007c06:mouzax,zes)x0O0O7cO6:mouzax,ZEE)x0O0O7cOa:in$0x64,zal)x0O0O7cOc:test,zal)x00007c0e:jneGx7c0aJxOOOOTclO:■nou$0xdl, 1進過對比,這些代碼與bootasm.S與bootblock.asm中的代碼完全一致。練習(xí)3分析bootloader進入保護模式的過程。在開啟120之前,BIOS^做了很多事關(guān)中斷、清除方向標(biāo)志,給各個數(shù)據(jù)段清零。cli #Disableinterruptscld #Stringoperationsincrement#Setuptheimportantdatasegmentregisters(DS,ES,SS).xorw%ax,%ax#Segmentnumberzeromovw%ax,%ds#->DataSegmentmovw%ax,%es#->ExtraSegmentmovw%ax,%ss

1、為何^^A20,以及如何開啟A20?seta20.1:inb$0x64,%altestb$0x2,%aljnzseta20.1#等待8042鍵盤控制器不忙movb$0xd1,%aloutb%al,$0x64#發(fā)送寫8042輸出端口的指令seta20.2:inb$0x64,%altestb$0x2,%aljnzseta20.2#等待8042鍵盤控制器不忙movb$0xdf,%aloutb%al,$0x60#打開A20當(dāng)A20地址線控制禁止時,則程序就像在8086中運行,1MB以上的地是不可訪問的。在保護模式下A20地址線控制是要打開的。為了使能所有地址位的尋址能力,必須向鍵盤控制器8042發(fā)送一個命令。鍵盤控制器8042將會將它的的某個輸出引腳的輸出置高電平,作為A20地址線控制的輸入。一旦設(shè)置成功之后,內(nèi)存將不會再被繞回(memorywrapping),這樣我們就可以尋址intel80286CPU支持的16M內(nèi)存空間,或者是尋址intel80386以上級別CPU支持的所有4G內(nèi)存空間了。2、如何初始化D7表?lgdtgdtdesc把gdt表的起始位置和界限裝入GDTR寄存器movl%cr0,%eaxorl$CR0_PE_ON,%eaxmovl%eax,%cr0#把保護模式位開啟復(fù)習(xí)一下crO寄存器,它的第0位為保護模式位PE:設(shè)置PE將讓處理器工作在保護模式下。復(fù)位PE將返回到實模式工作。此外,gdtdesc指出了全局描述符表在符號gdt處,如下上面四句話實現(xiàn)了打開保護模式位。3、如何使能進入保護模式?通過長跳轉(zhuǎn)指令gdt:SEG_NULLASMSEG_ASM(STA_X|STA_R,0x0,Oxffffffff)SEG_ASM(STA_W,0x0,Oxffffffff)#空段#代碼段(起始地址,大?。?數(shù)據(jù)段(起始地址,大?。﹍jmp$PROT_MODE_CSEG,$protcseg進入了保護模式。進入保護模式之后還有一個步驟:把所有的數(shù)據(jù)段寄存器指向上面的GDT描述符表中的數(shù)據(jù)段(0x10)。練習(xí)四、分析bootloader加載ELF格式的OS的過程。在proj2中,增加主要增加了對磁盤簡單的讀取函數(shù)readsect()readseg()),以及對ELF頭的解析(ELF頭結(jié)構(gòu)在ELF.h文件中)。staticvoidreadseg(uintptr_tva,uint32_tcount,uint32_toffset){uintptr_tend_va=va+count;//指針移到邊界va-=offset%SECTSIZE;//計算開始讀的第一個扇區(qū)號uint32_tsecno=(offset/SECTSIZE)+1;//逐個讀取扇區(qū)for(;va<end_va;va+=SECTSIZE,secno++){readsect((void*)va,secno);}}//實現(xiàn)了從kernel復(fù)制8個扇區(qū)(包含ELF頭,共4KB)到0x10000疑問:為什么要把ELF頭讀到0X10000?從哪讀?以下為一些硬件端口上實現(xiàn)讀取一個扇區(qū)到內(nèi)存0x10000。/*readsect-readasinglesectorat@secnointo@dst*/staticvoidreadsect(void*dst,uint32_tsecno){//waitfordisktobereadywaitdisk();outb(0x1F2,1); //count=1outb(0x1F3,secno&0xFF);outb(0x1F4,(secno>>8)&0xFF);outb(0x1F5,(secno>>16)&0xFF);outb(0x1F6,((secno>>24)&0xF)|0xE0);outb(0x1F7,0x20); //cmd0x20-readsectors//waitfordisktobereadywaitdisk();//readasectorinsl(0x1F0,dst,SECTSIZE/4);}Readsect()函數(shù)的工作大致是:1.讀I/O地址0x1f7,等待磁盤準(zhǔn)備好;2.寫I/O地址0x1f2~0x1f5,0x1f7,發(fā)出讀取第offseet個扇區(qū)處的磁盤數(shù)據(jù)的命令;讀I/O地址0x1f7,等待磁盤準(zhǔn)備好;連續(xù)讀I/O地址0x1f0,把磁盤扇區(qū)數(shù)據(jù)讀到指定內(nèi)存。練習(xí)五、實現(xiàn)函數(shù)調(diào)用堆棧跟蹤函數(shù)(需要編程)+|檢底方向 |高位地址TOC\o"1-5"\h\zI II I| #^13 ||券數(shù)2 |I奩數(shù)1 II返回地址 II上一層[出p] |U [ebp]|局部邏量 |低隹燉址可以獲知棧底是在高地址,棧頂在低地址,壓棧的次序為:參數(shù)(編程的時候默認有四個參數(shù))、返回地址、上一層EBP、局部變量。uint32_tebp=read_ebp(),eip=read_eip();inti,j;for(i=0;ebp!=0&&i<STACKFRAME_DEPTH;i++){cprintf"ebp:0x%08xeip:0x%08xargs:",ebp,eip);uint32_t*args=(uint32_t*)ebp+2;for(j=0;j<4;j++){cprintf"0x%08x",args[j]);}cprintf"\n");print_debuginfo(eip-1);eip=(uint32_t*)ebp)[1];ebp=(uint32_t*)ebp)[0];注:read_ebp()和readeip()都是通過內(nèi)聯(lián)匯編實現(xiàn)的。Eip-1是為了能找到上一條指令

結(jié)果圖:ITH7E0xO9007t>6eOx901O9a58exaoeeoaoe9X000001003QxMlOllldkern/debug/nonttDr.c:711runcndM370xO9l0lf14ebp:9)cae937bc8etp:okobiobqbcargs:□xeaaoooaa0X030000030xfa7502a8ITH7E0xO9007t>6eOx901O9a58exaoeeoaoe9X000001003QxMlOllldkern/debug/nonttDr.c:711runcndM370xO9l0lf14ebp:9)cae937bc8etp:okobiobqbcargs:□xeaaoooaa0X030000030xfa7502a8ebp:&K0flOO7b98eip:OxB0iaOac5args:0x00000000kern/debug/monitor-c;3B:nonitor+681oxooooeooo0x0000065cexaesaeaoeGx54e4dOBeexseeesaee□xa00iaa943backtraceebp:9K0O3O7ae8eip:OxOGlOOSCbargs:0x03990000QxOOOQGOOlkern/d!ebug/kdebug*c;307:print_stackfrane+21ebp:0K000O7afsetp:axoei90b49argsi0x00000000exaao07bickern/debug/nonitor*c:121:Tion_backtrace+19ebp:a?t&0OO7b68eip:0^00100^58args;0x00108569'0xOO007b98kern/init/tnit.c:25:kerninit-i-91ebp:DxOOOD7bf8eip:0KOG007d68args:0xc031fcfa0xcD8ed88e enMo":-- 0工Elm眥了ch?-- 練習(xí)六、完善中斷初始化和處理(需要編程)[練習(xí)6.1]中斷向量表中一個表項占多少字節(jié)?其中哪幾位代表中斷處理代碼的入口?80386INTERRUPTGATE中斷向量表一個表項占用8字節(jié),其中2-3字節(jié)是段選擇子,0-1字節(jié)和6-7字節(jié)拼成位移,兩者聯(lián)合便是中斷處理程序的入口地址。2.請編程完善kern/trap/trap.c中對中斷向量表進行初始化的函^Ht_initoidt_init(void){externuintptr」__vectors[];inti;for(i=0;i<sizeof(idt)/sizeof(structgatedesc);i++){SETGATE(idt[i],0,GD_KTEXT,__vectors[i],DPL_KERNEL);}//初始化每一條IDT項//設(shè)置內(nèi)核態(tài)到用戶態(tài)的轉(zhuǎn)換SETGATE(idt[T_SWITCH_TOK],0,GD_KTEXT,__vectors[T_SWITCH_TOK],DPL_USER);//載入IDTlidt(&idt_pd);}3.請編程完善trap.中的中斷處理函數(shù)rap在對時鐘中斷進行處理的部分填寫trapS數(shù)中處理時鐘中斷的部分,使操作系統(tǒng)每遇到0次時鐘中斷后,調(diào)用print_tickS程序,向屏幕上打印一行文字”00tic”caseIRQ_OFFSET+IRQ_TIMER:ticks++;if(ticks%TICK_NUM==0){print_ticks();}//當(dāng)有100次時鐘中斷輸出一次break;練習(xí)7、增加sysca功能,即增加一用戶態(tài)函數(shù)(可執(zhí)行

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論