MIT操作系统实验1-2

来源:互联网 发布:mac为什么不能剪切 编辑:程序博客网 时间:2024/05/03 16:28

2.1  Bootloader

Exercise 4.Set a breakpoint at address 0x7c00, which is where the boot sector will be loaded. Continue execution until that break point. Trace through the code inboot/boot.S, using the source code and the disassembly fileobj/boot/boot.asm to keep track of where you are. Also use theucommand in Bochs to disassemble sequences of instructions in the boot loader, and compare the original boot loader source code with both the GNU disassembly inobj/boot/boot.asmand the Bochs disassembly from theucommand.

Trace into cmain() in boot/main.c, and then intoreadsect(). 

在bootmain()中,循环调用完readsect()后执行的是如下语句:
// call the entry point from the ELF header// note: does not return!((void (*)(void)) (ELFHDR->e_entry & 0xFFFFFF))();
可以看出,在加载完代码后,会调用ELF头部信息中的入口函数:
此函数实际就是kernel中的主函数:
函数在执行call *%eax后会跳转到0xf010000c处,执行movw $0x1234, 0x472这条指令。
而这条指令正是entry.S中的第一条指令:
.globl_start_start:movw$0x1234,0x472# warm boot# Establish our own GDT in place of the boot loader's temporary GDT.lgdtRELOC(mygdtdesc)# load descriptor table# Immediately reload all segment registers (including CS!)# with segment selectors from the new GDT.movl$DATA_SEL, %eax# Data segment selectormovw%ax,%ds# -> DS: Data Segmentmovw%ax,%es# -> ES: Extra Segmentmovw%ax,%ss# -> SS: Stack Segmentljmp$CODE_SEL,$relocated# reload CS by jumpingrelocated:

 

Challenge!Make JOS boot under Bochs from a simulated CD-ROM. You will need to learn about themkisofsutility (available on Athena), and will have to modify the.bochsrcappropriately.

首先:生成iso镜像文件
oslab@oslab:~/lab1/obj/boot$ mkisofs -no-emul-boot -b boot -o boot.iso ./
I: -input-charset not specified, using utf-8 (detected in locale settings)
Using BOOT000.ISO;1 for  /boot.iso (boot.iso~)
Size of boot image is 4 sectors -> No emulation
Total translation table size: 2048
Total rockridge attributes bytes: 0
Total directory bytes: 542
Path table size(bytes): 10
Max brk space used 0
1348 extents written (2 MB) 
余下步骤:修改.bochsrc文件
Modify .bochsrc
Enable ata3:
ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9 
Set ata3:
ata3-slave: type=cdrom, path="./obj/boot/boot.iso", status=inserted 
BOOT:
boot: cdrom 
不要将ata0-master: type=disk, mode=flat, path="./obj/kern/bochs.img", cylinders=100, heads=10, spt=10注释掉,引导程序只是完成初始化的工作,系统镜像文件仍然放在硬盘之中。

 2.1  Loading the kernel

Exercise 6.Reset the machine (exit bochs and start it again). Examine the 8 words of memory at 0x00100000 at the point the BIOS enters the boot loader, and then again at the point the boot loader enters the kernel. Why are they different? What is there at the second breakpoint? (You do not really need to use Bochs to answer this question. Just think.)

不用调试也能想出来答案,由于0x00100000是内存加载的地址,在bootloader执行之前,这一片内存空间应该是没有值的,所以是0,在执行了bootloader之后,内核被加载到这一片区域。
在bochs中,加入断点,验证我们的想法。
bootloader加载前:

<bochs:1> x /8hx 0x100000
[bochs]:
0x00100000 <bogus+       0>: 0x0000  0x0000  0x0000  0x0000  0x0000  0x0000    0x0000  0x0000

 
 
 
 
在bootloader加载之后:

<bochs:4> x /8hx 0x100000
[bochs]:
0x00100000 <bogus+       0>: 0xb002  0x1bad  0x0003  0x0000  0x4ffb  0xe452    0xc766  0x7205

 

 

 

 

2.1  Link vs. Load Address

关于链接地址(LINK ADDRESS)和加载地址(LOAD ADDRESS)
Link Address: the memory address for which a binary is linked, hasn’t been loaded!
Load Address: the memory address for which a binary is actually loaded!

Exercise 7.Trace through the first few instructions of the boot loader again and identify the first instruction that would "break" or otherwise do the wrong thing if you were to get the boot loader's link address wrong. Then change the link address inboot/Makefragto something wrong, rungmake clean, recompile lab1 withgmake, and trace into the boot loader again to see what happens. Don't forget to change the link address back afterwards!

 

 

 

 

 

硬盘和软盘是按512字节分块(sector)的,而光盘是按2048字节分块的,在bootloader启动时,将会从启动盘拷贝512字节到0x7c00处,然后跳转到0x7c00处开始执行。
BIOS引导的时候只读第一个扇区,即前512个字节,BIOS判断这512个字节是否是引导程序的标准是:是否以55 aa 结束。
 在修改链接地址之前,我们查看obj/boot/boot.asm:  
.globl startstart:  .code16                     # Assemble for 16-bit mode  cli                         # Disable interrupts    7c00:fa                   cli      cld                         # String operations increment    7c01:fc                   cld    
可以清晰地看到,第一条执行的指令是cli, 其链接地址是0x7c00
打开boot/Makefrag,修改 0x7c00为0x7c10:
$(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7c10 -o $@.out $^ 
执行make clean, make。重新查看obj/boot/boot.asm:
.globl startstart:  .code16                     # Assemble for 16-bit mode  cli                         # Disable interrupts    7c10:fa                   cli      cld                         # String operations increment    7c11:fc                   cld     Part 2 The bootloader

可以看出,第一条指令的链接地址已经变成了0x7c10
在bochs中执行:
<bochs:1> lb 0x7c00
<bochs:2> c
(0) Breakpoint 1, 0x0x00007c00 in ?? ()
Next at t=873222
(0) [0x00007c00] 0000:7c00 (unk. ctxt): cli                       ; fa
可以看到在0x7c00处执行的任然是bootloader中的第一条语句:cli
然后我们在前面已经看到cli所对应的链接地址已经变成了0x7c10,所以继续单步执行,当执行到boot.asm中的ljmp    $PROT_MODE_CSEG, $protcseg时出错,系统panic。
Next at t=873242
(0)     [0x00007c2d] 0000:0x00007c2d (unk. ctxt): 
jmp far 0008:7c42         ; ea427c0800
<bochs:23> 
因为此时我们的链接地址与加载地址对不上了,正确的地址应该是0x7c32!
原创粉丝点击