Ucore实验lab1

练习一:理解通过make生成执行文件的过程。
在Makefile中生成ucore.img的代码是:
$(UCOREIMG): $(kernel) $(bootblock) $(V)dd if=/dev/zero of=$@ count=10000 $(V)dd if=$(bootblock) of=$@ conv=notrunc $(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc
在执行Makefile时对应的输出为:
dd if=/dev/zero of=bin/ucore.img count=1000010000+0 records in10000+0 records out5120000 bytes (5.1 MB) copied, 0.0540315 s, 94.8 MB/sdd if=bin/bootblock of=bin/ucore.img conv=notrunc1+0 records in1+0 records out512 bytes (512 B) copied, 0.000110706 s, 4.6 MB/sdd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc138+1 records in138+1 records out70775 bytes (71 kB) copied, 0.000472623 s, 150 MB/s
从Makefile中可以看出要生成ucore.img首先要拥有kernel和bootblock两个可执行文件所以继续在Makefile中找到kernel的相关代码段
kernel = $(call totarget,kernel) $(kernel): tools/kernel.ldw$(kernel): $(KOBJS) @echo + ld $@ $(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS) @$(OBJDUMP) -S $@ > $(call asmfile,kernel) @$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel) $(call create_target,kernel)
查看文件中的文件得出,生成kernel需要以下文件:
kernel.ld init.o readline.o stdio.o kdebug.o kmonitor.o panic.o clock.o console.o intr.o picirq.o trap.o trapentry.o vectors.o pmm.o printfmt.o string.o
在Makefile中bootblock的相关代码:# create bootblockbootfiles = $(call listf_cc,boot)$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc)) bootblock = $(call totarget,bootblock) $(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign) @echo + ld $@ $(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock) @$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock) @$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock) @$(call totarget,sign) $(call outfile,bootblock) $(bootblock) $(call create_target,bootblock)
生成ucore.img过程中产生的信息:
dd if=/dev/zero of=bin/ucore.img count=1000010000+0 records in10000+0 records out5120000 bytes (5.1 MB) copied, 0.0540315 s, 94.8 MB/sdd if=bin/bootblock of=bin/ucore.img conv=notrunc1+0 records in1+0 records out512 bytes (512 B) copied, 0.000110706 s, 4.6 MB/sdd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc138+1 records in138+1 records out70775 bytes (71 kB) copied, 0.000472623 s, 150 MB/s练习二使用qemu执行并调试lab1中的软件。
1从CPU加电后执行的第一条指令开始,单步跟踪BIOS的执行。
修改
lab1/tools/gdbinitset architecture i8086target remote :1234
执行
make debug
来查看BIOS的代码,得到结果。
2在初始化位置0x7c00设置实地址断点,测试断点正常。
在gdbinit 中添加指令:set architecture i8086b *0x7c00cx/5i $pcset architecture i386
然后运行Make debug可以得到断点正常。
3从0x7c00开始跟踪代码运行,将单步跟踪反汇编得到的代码与bootasm.S和 bootblock.asm进行比较。
​ 在0x7c00处break,然后使用si和 x/i $pc 指令一行一行的跟踪,将得到的反汇编代码为:0x00007c01 in ?? ()(gdb) x/i $pc=> 0x7c01: cld (gdb) si0x00007c02 in ?? ()(gdb) x/i $pc=> 0x7c02: xor %eax,%eax(gdb) si0x00007c04 in ?? ()(gdb) x/i $pc=> 0x7c04: mov %eax,%ds(gdb) bootblock.asm 中的代码为:.
code16 # Assemble for 16-bit mode cli # Disable interrupts 7c00: fa cli cld # String operations increment 7c01: fc cld # Set up the important data segment registers (DS, ES, SS). xorw %ax, %ax # Segment number zero 7c02: 31 c0 xor %eax,%eax movw %ax, %ds # -> Data Segment 7c04: 8e d8 mov %eax,%ds movw %ax, %es # -> Extra Segment 7c06: 8e c0 mov %eax,%es movw %ax, %ss # -> Stack Segment 7c08: 8e d0 mov %eax,%ss
bootasm.s中的代码为:
.globl startstart:.code16 # Assemble for 16-bit mode cli # Disable interrupts cld # String operations increment # Set up the important data segment registers (DS, ES, SS). xorw %ax, %ax # Segment number zero movw %ax, %ds # -> Data Segment movw %ax, %es # -> Extra Segment movw %ax, %ss # -> Stack Segment
根据比较,这几部分一样
4自己找一个bootloader或内核中的代码位置,设置断点并进行测试
在init.c中会对gdt进行初始化,在初始化过程中,调用了gdt_init()这个函数,我选择此处进行测试。已经成功在gdt_init处停止,然后使用x/i $pc指令查询正在执行的汇编代码,与原文件中的c代码对照,测试结束。 **练习三分析bootloader进入保护模式的过程。
**从bootasm.s查看代码,并分析过程首先禁止中断,并且修改控制方向标志寄存器DF=0,使得内存地址从低到高增加,然后对实模式下的段寄存器进行初始化

   xorw %ax, %ax    movw %ax, %ds    movw %ax, %es    movw %ax, %ss

xorw %ax, %ax 将ax寄存器置为0,然后,对ds(数据段寄存器),es(额外寄存器),ss(栈寄存器)

   seta20.1:   inb $0x64, %al        testb $0x2, %al   jnz seta20.1  movb $0xd1, %al        # 0xd1 -> port 0x64 outb %al, $0x64  seta20.2:   inb $0x64, %al                                  testb $0x2, %aljnz seta20.2  movb $0xdf, %al     # 0xdf -> port 0x60  outb %al, $0x60

接下来初始化GDT表,GDT表已经在数据区声明
# Bootstrap GDT .p2align 2 # force 4 byte alignmentgdt: SEG_NULLASM # null seg SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg for bootloader and kernel SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg for bootloader and kernel gdtdesc: .word 0x17 # sizeof(gdt) - 1 .long gdt # address gdt
然后将cr0置为1开启保护模式,设置保护模式下的段寄存器
movw $PROT_MODE_DSEG, %ax # Our data segment selector movw %ax, %ds # -> DS: Data Segment movw %ax, %es # -> ES: Extra Segment movw %ax, %fs # -> FS movw %ax, %gs # -> GS movw %ax, %ss # -> SS: Stack Segment PROT_MODE_DSEG为0x10
建立堆栈,并且调用bootmain.c
movl $0x0, %ebp
movl $start, %esp
call bootmain
栈的地址是从0到0x7c00
练习四分析bootloader加载ELF格式的OS的过程
bootloader首先读取ELF头表
// read the 1st page off disk
readseg((uintptr_t)ELFHDR, SECTSIZE * 8, 0);
ELFHDR是前面定义的一个临时空间,而uintptr_t是在defs.h中定义的:
#define ELFHDR ((struct elfhdr *)0x10000) // scratch space
所以一层层推导下来,uintptr_t就是unsigned int。
这里是为了把ELF的头表读进去,传入readseg的三个参数分别表示,起始位置,大小,和偏移。大小是SECTSIZE8,SETCSIZE的大小是512:
#define SECTSIZE 512
这里读入了512
8个位,然而实际并不需要这么大,亲测只要一个SECTSIZE也就是512就足够,所以猜测可能是为了以后的扩展,所以在这里定义了这么大。当头表读入完成后,就通过e_magic检测是否是合法的ELF文件:
// is this a valid ELF? if (ELFHDR->e_magic != ELF_MAGIC) { goto bad; }
如不是就会跳入到bad执行指令,如果是就继续往下执行。根据ELF头表中的描述,将ELF文件加载到内存中的相应位置保存到ph中; ph = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR->e_phoff);
将结束位置加载到eph中,然后就将ELF文件中的数据通过循环加载到内存中,加载完成后根据ELF头表中存储的入口信息,找到内核的入口:

((void (*)(void))(ELFHDR->e_entry & 0xFFFFFF))();
5实现函数调用堆栈跟踪函数
代码:
uint32_t ebp = read_ebp(); uint32_t eip = read_eip(); int i,j; for(i = 0; ebp!=0 && i < STACKFRAME_DEPTH; i++) { cprintf("ebp:0x%08x eip:0x%08x ",ebp, eip); cprintf("args"); 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); }
练习六完善中断初始化和处理
1中断描述符表(也可简称为保护模式下的中断向量表)中一个表项占多少字节?其中哪几位代表中断处理代码的入口?
中断描述符表中一个表项占8个字节,其中015和4863分别为offset的低16位和高16位,16~31位是段选择子,通过段选择子得到段基址,再加上段内偏移量就可以得到中断处理代码的入口。
2请编程完善kern/trap/trap.c中对中断向量表进行初始化的函数idt_init。在idt_init函数中,依次对所有中断入口进行初始化。使用mmu.h中的SETGATE宏,填充idt数组内容。每个中断的入口由tools/vectors.c生成,使用trap.c中声明的vectors数组即可。
代码如下:

 extern uintptr_t __vectors[];    int i = 0;    for(i = 0; i<sizeof(idt) / sizeof(struct gatedesc);i++) {    SETGATE(idt[i], 0,KERNEL_CS, __vectors[i], DPL_KERNEL);    }     SETGATE(idt[T_SYSCALL], 0, KERNEL_CS, __vectors[T_SYSCALL], DPL_USER);    lidt(&idt_pd);

3请编程完善trap.c中的中断处理函数trap,在对时钟中断进行处理的部分填写trap函数中处理时钟中断的部分,使操作系统每遇到100次时钟中断后,调用print_ticks子程序,向屏幕上打印一行文字”100 ticks”。
代码如下
ticks++; if(ticks%TICK_NUM == 0) print_ticks(); break;此处代码的意思就是在,每次时钟中断后ticks就加一,每次达到TICK_NUM就会调用print_ticks()语句,向屏幕上输出一句话。

操作系统课程ucore实验 lab1相关推荐

  1. 操作系统ucore实验——lab1

    ** ## 操作系统ucore实验--lab1 ** 紧急更新实验用的源代码在lab0中的有误改为: 链接:https://pan.baidu.com/s/1RLCG57xDSydH8oQD-JwgP ...

  2. 西工大计算机操作系统实验报告,西工大计算机操作系统课程设计实验报告bh05xh5...

    <西工大计算机操作系统课程设计实验报告bh05xh5>由会员分享,可在线阅读,更多相关<西工大计算机操作系统课程设计实验报告bh05xh5(7页珍藏版)>请在人人文库网上搜索. ...

  3. HDU操作系统课程设计实验三

    HDU操作系统课程设计实验三 一.设计目的 二.内容要求 三.实验内容 信号量的使用 1.实现一个模拟的shell,基本功能加find.grep命令 2.实现一个管道通信程序,基本功能加有名管道通信 ...

  4. 操作系统课程设计---实验六 银行家算法的模拟与实现

    实验六 银行家算法的模拟与实现 完整课程设计源码及其报告查看:陈陈的操作系统课程设计 1.实验目的 (1) 进一步理解进程的并发执行. (2) 加强对进程死锁的理解,理解安全状态与不安全状态的概念. ...

  5. 操作系统课程设计---实验十 简单shell命令行解释器的设计与实现

    实验十 简单shell命令行解释器的设计与实现 完整课程设计源码及其报告查看:陈陈的操作系统课程设计 1.实验目的 本实验主要目的在于进一步学会如何在 Linux 系统下使用进程相关的系统调用,了解 ...

  6. 操作系统课程设计---实验七 磁盘调度算法的模拟与实现

    实验七 磁盘调度算法的模拟与实现 完整课程设计源码及其报告查看:陈陈的操作系统课程设计 1.实验目的 (1) 了解磁盘结构以及磁盘上数据的组织方式. (2) 掌握磁盘访问时间的计算方式. (3) 掌握 ...

  7. Operating System lab1(操作系统课程设计实验1)

    操作步骤 把如下文件放到一个目录下 再依次执行以下命令 make mkdir web ./webserver 8088 ./web display.c /** Copyright (c) 1989, ...

  8. 西电Pintos操作系统课程设计 实验二

    实验二:Alarm-Clock 一.实验目的 重新实现timer_sleep()函数,避免"忙等待"的发生.通过阅读Pintos部分源码,初步了解Pintos操作系统内核的关键函数 ...

  9. 计算机操作系统课设总结,计算机操作系统课程设计

    <计算机操作系统课程设计>由会员分享,可在线阅读,更多相关<计算机操作系统课程设计(36页珍藏版)>请在人人文库网上搜索. 1.操作系统课程设计实验报告姓 名: 李文孝 班 级 ...

最新文章

  1. Supporting Python 3(支持python3)——常见的迁移问题
  2. JProfiler学习笔记
  3. 百练OJ:2943:小白鼠排队
  4. makefile文件中的依赖关系理解
  5. reddit_如何将多个子Reddit与多个Reddit合并
  6. windows调用python_windows 快捷调用Python语言
  7. 让你的单细胞数据动起来!|iCellR(一)
  8. 【Level 08】U08 Positive Attitude L6 Join our virtual community
  9. 时下超火的在线教育移动应用UI套件设计素材
  10. 应届生从头脑风暴到游戏策划案的个人思路(一)
  11. 图片溢出div,超出div解决办法
  12. 【产品】什么是虚位密码及其用途
  13. ubuntu 16.04 + GTX1050安装nvidia驱动
  14. 站在巨人肩膀上优雅地分蛋糕
  15. 不完整拼音模糊匹配算法
  16. 创业思维的误区 (余世维)
  17. 英雄联盟 LCUAPI
  18. vue-cli3访问public文件夹静态资源的报错解决
  19. 爱是瞬间的美,情是永恒的痛
  20. 三种方法教你让模糊照片秒变高清图

热门文章

  1. 电脑文件被误删别急,这样设置操作可恢复数据
  2. 京东APP地址加密的浅分析
  3. 5.(人脸签到)疫情下的在线办公签到系统-进阶篇
  4. 几何代数(Geometric Algebra)
  5. i9500android操作系统跑流量,三星I9500刷机包 百度云ROM54公测版 因为专注 所以精进...
  6. 统计数据会说谎_社交媒体统计数据何时说谎以及如何处理
  7. STC89C51——中断系统
  8. 商业计划书范文3000_商业计划书范文
  9. 2019年5月新出Dart Flutter入门实战视频教程网盘下载地址
  10. android应用角标