ucore lab1实验报告

这篇实验报告详细介绍了ucore lab1的实验过程,包括实验目的和内容。主要内容涉及计算机原理,如CPU的编址与寻址、中断机制、外设管理;Bootloader的编译运行及调试;ucore OS的启动与调试,特别是通过make生成ucore.img的步骤,包括bootblock和kernel的生成。此外,报告还深入解析了如何使用GDB进行调试,以及从实模式进入保护模式的关键步骤,如初始化GDT、开启A20地址线等。
摘要由CSDN通过智能技术生成

ucore lab1实验报告

一.实验目的

了解:

1.计算机原理:

  • CPU的编址与寻址: 基于分段机制的内存管理
  • CPU的中断机制
  • 外设:串口/并口/CGA,时钟,硬盘

2.Bootloader软件:

  • 编译运行bootloader的过程
  • 调试bootloader的方法
  • PC启动bootloader的过程
  • ELF执行文件的格式和加载
  • 外设访问:读硬盘,在CGA上显示字符串

3.ucore OS软件:

  • 编译运行ucore OS的过程
  • ucore OS的启动过程
  • 调试ucore OS的方法
  • 函数调用关系:在汇编级了解函数调用栈的结构和处理过程
  • 中断管理:与软件相关的中断处理
  • 外设管理:时钟

二.实验内容

练习1:理解通过make生成执行文件的过程

(1)操作系统镜像文件ucore.img是如何一步一步生成的? (需要比较详细地解释Makefile中每一条相关命令和命令参数的含义, 以及说明命令导致的结果)

1.首先执行命令*make v=*查看Makefile命令,但是会报错

make: *** No targets specified and no makefile found. Stop.图:

在这里插入图片描述

解决方案如下:要在Makefile同目录下输入命令,利用cd切换到同目录下即可,结果如图:
在这里插入图片描述

2.然后打开makefile文件,找到生成ucore.img部分代码,如图:
在这里插入图片描述
分析如下:

create ucore.img
#在ucore.img前面加上bin/
UCOREIMG    := $(call totarget,ucore.img)

$(UCOREIMG): $(kernel) $(bootblock)
        # 创建一个大小为10000字节的空白文件
    $(V)dd if=/dev/zero of=$@ count=10000
    # 向上述文件中拷贝bin/bootblock
    $(V)dd if=$(bootblock) of=$@ conv=notrunc
    # 向上述文件中继续(第二个块)拷贝bin/kernel
    $(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc

#将ucore.img包添加到ucore.img目标
$(call create_target,ucore.img)

由上图代码中显然知道为了生成ucore.img,首先创建一个大小为10000字节的块儿,并且需要生成bootblock、kernel,把bootblock中的内容写到第一个块, 从第二个块开始写kernel中的内容。

3.生成bootblock的相关代码如图:
在这里插入图片描述
分析如下:

 create bootblock
 bootfiles为boot/文件夹下的全部文件列表
bootfiles = $(call listf_cc,boot)
 编译boot/文件夹下的全部文件
$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))

#(在bootblock前面加上bin/目录名)
bootblock = $(call totarget,bootblock)

#bootblock目标的依赖项为源文件对应的OBJ文件和bin/sign
$(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)
        # 输出"+ ld bin/bootblock"到控制台
        @echo + ld $@
        # 将OBJ文件链接为bin/bootblock
    $(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock)
    # 将bin/bootblock文件反编译
    @$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)
    # 将bin/bootblock转换成bin/bootblock.out二进制文件
    @$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)
    # 用链接出的bin/sign工具将bin/bootblock.out再转换回bin/bootblock二进制文件
    @$(call totarget,sign) $(call outfile,bootblock) $(bootblock)

#将bootblock包添加到bootblock目标
$(call create_target,bootblock)

所以为了生成bootblock,首先需要生成bootasm.o、bootmain.o、sign

生成bootasm.o,bootmain.o的相关makefile代码为

bootfiles = $(call listf_cc,boot) 
 $(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))

生成bootasm.o需要bootasm.S命令为

gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs
-nostdinc -fno-stack-protector -Ilibs/ -Os -nostdinc
-c boot/bootasm.S -o obj/boot/bootasm.o

其中关键的参数为

-ggdb  生成可供gdb使用的调试信息。这样才能用qemu+gdb来调试bootloader or ucore。

-m32  生成适用于32位环境的代码。我们用的模拟硬件是32bit的80386,所以ucore也要是32位的软件。

-gstabs  生成stabs格式的调试信息。这样要ucore的monitor可以显示出便于开发者阅读的函数调用栈信息

-nostdinc  不使用标准库。标准库是给应用程序用的,我们是编译ucore内核,OS内核是提供服务的,所以所有的服务要自给自足。

-fno-stack-protector  不生成用于检测缓冲区溢出的代码。这是for 应用程序的,我们是编译内核,ucore内核好像还用不到此功能。

-Os  为减小代码大小而进行优化。根据硬件spec,主引导扇区只有512字节,我们写的简单bootloader的最终大小不能大于510字节。

生成bootmain.o需要bootmain.c命令为

gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc
-fno-stack-protector -Ilibs/ -Os -nostdinc
-c boot/bootmain.c -o obj/boot/bootmain.o

其中关键参数有

-fno-builtin  除非用__builtin_前缀, 否则不进行builtin函数的优化

生成sign工具的makefile代码为

在这里插入图片描述
分析如下:

# create 'sign' tools
# 将tools/sign.c编译到OBJ文件,将源文件和中间文件添加到sign包
$(call add_files_host,tools/sign.c,sign,sign)
# 将sign包添加到sign目标
$(call create_target_host,sign,sign)

实际命令为

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

接着就是生成bootblock.o,命令为

ld -m elf_i386 -nostdlib -N -e start -Ttext 0x7C00
obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o

其中关键的参数为

-nostdlib  不使用标准库
-N  设置代码段和数据段均可读写
-e <entry>  指定入口
-Ttext  制定代码段开始位置

然后拷贝二进制代码bootblock.o到bootblock.out,命令为:

objcopy -S -O binary obj/bootblock.o obj/bootblock.out

其中关键的参数为

-S  移除所有符号和重定位信息
-O <bfdname>  指定输出格式

然后使用sign工具处理bootblock.out,生成bootblock,命令为:

bin/sign obj/bootblock.out bin/bootblock

4.接着来看看生成kernel的相关代码,如图:

在这里插入图片描述
分析如下:

# create kernel target
# (在kernel前面加上bin/目录名)
kernel = $(call totarget,kernel)

# kernel目标依赖于tools/kernel.ld文件
$(kernel): tools/kernel.ld

# kernel目标依赖于编译生成的OBJ文件
$(kernel): $(KOBJS)
        # 输出"+ ld bin/kernel"到控制台
    @echo + ld $@
    # 即命令"ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o ... obj/libs/printfmt.o"
    $(V)$(LD) $(LDFLAGS) -T tools/kernel.ld 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值