ucore 实验 lab1

练习一:
执行 make "V="的结果。

zhh043@moocos-VirtualBox-> make "V="
+ cc kern/init/init.c
gcc -Ikern/init/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/init/init.c -o obj/kern/init/init.o
kern/init/init.c:95:1: warning: ‘lab1_switch_test’ defined but not used [-Wunused-function]
 lab1_switch_test(void) {
 ^
+ cc kern/libs/readline.c
gcc -Ikern/libs/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/readline.c -o obj/kern/libs/readline.o
+ cc kern/libs/stdio.c
gcc -Ikern/libs/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/stdio.c -o obj/kern/libs/stdio.o
+ cc kern/debug/kdebug.c
gcc -Ikern/debug/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kdebug.c -o obj/kern/debug/kdebug.o
kern/debug/kdebug.c:251:1: warning: ‘read_eip’ defined but not used [-Wunused-function]
 read_eip(void) {
 ^
+ cc kern/debug/kmonitor.c
gcc -Ikern/debug/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kmonitor.c -o obj/kern/debug/kmonitor.o
+ cc kern/debug/panic.c
gcc -Ikern/debug/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/panic.c -o obj/kern/debug/panic.o
kern/debug/panic.c: In function ‘__panic’:
kern/debug/panic.c:27:5: warning: implicit declaration of function ‘print_stackframe’ [-Wimplicit-function-declaration]
     print_stackframe();
     ^
+ cc kern/driver/clock.c
gcc -Ikern/driver/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/clock.c -o obj/kern/driver/clock.o
+ cc kern/driver/console.c
gcc -Ikern/driver/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/console.c -o obj/kern/driver/console.o
+ cc kern/driver/intr.c
gcc -Ikern/driver/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/intr.c -o obj/kern/driver/intr.o
+ cc kern/driver/picirq.c
gcc -Ikern/driver/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/picirq.c -o obj/kern/driver/picirq.o
+ cc kern/trap/trap.c
gcc -Ikern/trap/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trap.c -o obj/kern/trap/trap.o
kern/trap/trap.c:14:13: warning: ‘print_ticks’ defined but not used [-Wunused-function]
 static void print_ticks() {
             ^
kern/trap/trap.c:30:26: warning: ‘idt_pd’ defined but not used [-Wunused-variable]
 static struct pseudodesc idt_pd = {
                          ^
+ cc kern/trap/trapentry.S
gcc -Ikern/trap/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trapentry.S -o obj/kern/trap/trapentry.o
+ cc kern/trap/vectors.S
gcc -Ikern/trap/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/vectors.S -o obj/kern/trap/vectors.o
+ cc kern/mm/pmm.c
gcc -Ikern/mm/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/mm/pmm.c -o obj/kern/mm/pmm.o
+ cc libs/printfmt.c
gcc -Ilibs/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/printfmt.c -o obj/libs/printfmt.o
+ cc libs/string.c
gcc -Ilibs/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/string.c -o obj/libs/string.o
+ ld bin/kernel
ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o obj/kern/libs/readline.o obj/kern/libs/stdio.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/debug/panic.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/intr.o obj/kern/driver/picirq.o obj/kern/trap/trap.o obj/kern/trap/trapentry.o obj/kern/trap/vectors.o obj/kern/mm/pmm.o  obj/libs/printfmt.o obj/libs/string.o
+ cc boot/bootasm.S
gcc -Iboot/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootasm.S -o obj/boot/bootasm.o
+ cc boot/bootmain.c
gcc -Iboot/ -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootmain.c -o obj/boot/bootmain.o
+ cc tools/sign.c
gcc -Itools/ -g -Wall -O2 -c tools/sign.c -o obj/sign/tools/sign.o
gcc -g -Wall -O2 obj/sign/tools/sign.o -o bin/sign
+ ld bin/bootblock
ld -m    elf_i386 -nostdlib -N -e start -Ttext 0x7C00 obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o
'obj/bootblock.out' size: 472 bytes
build 512 bytes boot sector: 'bin/bootblock' success!
dd if=/dev/zero of=bin/ucore.img count=10000
10000+0 records in
10000+0 records out
5120000 bytes (5.1 MB) copied, 0.0290902 s, 176 MB/s
dd if=bin/bootblock of=bin/ucore.img conv=notrunc
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000174016 s, 2.9 MB/s
dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc
146+1 records in
146+1 records out
74871 bytes (75 kB) copied, 0.000366798 s, 204 MB/s
[~/Desktop/ucore_os_lab-master/labcodes/lab1]

可以看到,它先是将一些C的源码通过gcc编译成.o文件,然后用ld将.o转换成可执行文件。
主要是需要 bootloader 和 kernel 两个程序。
这其实就展示了ucore是如何一步步生成的。

然后查看了tools目录下的sign.c在这里插入图片描述看到其中有:
buf[510]=0x55;
buf[511]=0xAA;
这两个就是符合规范的硬盘主引导扇区的特征
分别是:
1.输入的主引导扇区的记录必须是510字节以内(446+64)。
2.输出的主引导扇区的最后两个字节是55AA。

练习2:
按照实验书,看到Makefile里的lab1-mon指令:

    201 lab1-mon: $(UCOREIMG)
    202         $(V)$(TERMINAL) -e "$(QEMU) -S -s -d in_asm -D $(BINDIR)/q.log -monitor stdio -hda $< -serial null"
    203         $(V)sleep 2
    204         $(V)$(TERMINAL) -e "gdb -q -x tools/lab1init"

其实这些就是一些初始化的执行指令。
然后主要是lab1init:

      1 file bin/kernel             #加载bin/kernel
      2 target remote :1234         #与qemu连接
      3 set architecture i8086      #bios进入8086实模式
      4 b *0x7c00                   #在0x7c00设置断点
      5 continue                    #系统继续运行
      6 x /2i $pc                   #显示pc

执行 make lab1-mon:
在这里插入图片描述可以看到在0x7c00处断开了。
然后continue让它继续运行:在这里插入图片描述看到可以继续运行了。

练习三:
看一下bootasm.S的源码:

      1 #include <asm.h>
      2 
      3 # Start the CPU: switch to 32-bit protected mode, jump into C.
      4 # The BIOS loads this code from the first sector of the hard disk into
      5 # memory at physical address 0x7c00 and starts executing in real mode
      6 # with %cs=0 %ip=7c00.
      7 
      8 .set PROT_MODE_CSEG,        0x8                     # kernel code segment selector
      9 .set PROT_MODE_DSEG,        0x10                    # kernel data segment selector
     10 .set CR0_PE_ON,             0x1                     # protected mode enable flag
     11 
     12 # start address should be 0:7c00, in real mode, the beginning address of the running bootloader
     13 .globl start
     14 start:
     15 .code16                                             # Assemble for 16-bit mode
     16     cli                                             # Disable interrupts
     17     cld                                             # String operations increment
     18 
     19     # Set up the important data segment registers (DS, ES, SS).
     20     xorw %ax, %ax                                   # Segment number zero
     21     movw %ax, %ds                                   # -> Data Segment
     22     movw %ax, %es                                   # -> Extra Segment
     23     movw %ax, %ss                                   # -> Stack Segment
     24 
     25     # Enable A20:
     26     #  For backwards compatibility with the earliest PCs, physical
     27     #  address line 20 is tied low, so that addresses higher than
     28     #  1MB wrap around to zero by default. This code undoes this.
     29 seta20.1:
     30     inb $0x64, %al                                  # Wait for not busy(8042 input buffer empty).
     31     testb $0x2, %al
          32     jnz seta20.1
     33 
     34     movb $0xd1, %al                                 # 0xd1 -> port 0x64
     35     outb %al, $0x64                                 # 0xd1 means: write data to 8042's P2 port
     36 
     37 seta20.2:
     38     inb $0x64, %al                                  # Wait for not busy(8042 input buffer empty).
     39     testb $0x2, %al
     40     jnz seta20.2
     41 
     42     movb $0xdf, %al                                 # 0xdf -> port 0x60
     43     outb %al, $0x60                                 # 0xdf = 11011111, means set P2's A20 bit(the 1 bit) to     43  1
     44 
     45     # Switch from real to protected mode, using a bootstrap GDT
     46     # and segment translation that makes virtual addresses
     47     # identical to physical addresses, so that the
     48     # effective memory map does not change during the switch.
     49     lgdt gdtdesc
     50     movl %cr0, %eax
     51     orl $CR0_PE_ON, %eax
     52     movl %eax, %cr0
     53 
     54     # Jump to next instruction, but in 32-bit code segment.
     55     # Switches processor into 32-bit mode.
     56     ljmp $PROT_MODE_CSEG, $protcseg
     57 
     58 .code32                                             # Assemble for  32-bit mode
     59 protcseg:
     60     # Set up the protected-mode data segment registers
     61     movw $PROT_MODE_DSEG, %ax                       # Our data segment selector
     62     movw %ax, %ds                                   # -> DS: Data Segment
     63     movw %ax, %es                                   # -> ES: Extra Segment
     64     movw %ax, %fs                                   # -> FS
     65     movw %ax, %gs                                   # -> GS
     66     movw %ax, %ss                                   # -> SS: Stack Segment
     67 
     68     # Set up the stack pointer and call into C. The stack region is from 0--start(0x7c00)
     69     movl $0x0, %ebp
     70     movl $start, %esp
     71     call bootmain
     72 
     73     # If bootmain returns (it shouldn't), loop.
     74 spin:
     75     jmp spin
     76 
     77 # Bootstrap GDT
     78 .p2align 2                                          # force 4 byte alignment
     79 gdt:
     80     SEG_NULLASM                                     # null seg
     81     SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)           # code seg for bootloader and kernel
     82     SEG_ASM(STA_W, 0x0, 0xffffffff)                 # data seg for bootloader and kernel
     83 
     84 gdtdesc:
     85     .word 0x17                                      # sizeof(gdt) - 1
     86     .long gdt                                       # address gdt

其实BootLoader主要做了以下几件事:

  1. 关闭中断
  2. A20 使能
  3. 全局描述符表初始化
  4. 保护模式启动
  5. 设置段寄存器(长跳转更新CS,根据设置好的段选择子更新其他段寄存器)
  6. 设置堆栈,esp 0x700 ebp 0
  7. 进入bootmain后读取内核映像到内存,检查是否合法,并启动操作系统,控制权交给它

练习四:

查看kernel文件:

moocos-> file kernel
kernel: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped

就是它完成了上个实验中的一些基础功能。

BootLoader读取硬盘扇区其实是通过一个函数来完成的:
在这里插入图片描述就是图中的readseg
它用的是一种IO的地址寻址,将外设的数据读到内存,也就是读取硬盘扇区。
在readseg的下方,有一个对于ELF格式的判断
它是通过读取了ELF的HEADER,然后通过判断特殊成员变量 e magic 是否为一个特定的值来判断是否为合法格式的ELF文件。

练习五:
执行make qemu 结果如下:
在这里插入图片描述
练习六:
中断向量表一个表项占用8字节,2、3字节是段选择子,0、1字节和6、7字节拼成位移, 两者联合便是中断处理程序的入口地址。

idt_init:

idt_init(void) {
    extern uintptr_t __vectors[];
    for (int i = 0; i < 256; ++i) {
        SETGATE(idt[i], 0, GD_KTEXT, __vectors[i], DPL_KERNEL);
    }
    SETGATE(idt[T_SWITCH_TOK], 0, GD_KTEXT, __vectors[T_SWITCH_TOK], DPL_USER);
    lidt(&idt_pd);
}
        ticks++;
        if (ticks== TICK_NUM) {
            ticks= 0;
            print_ticks();
        }
        break;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值