练习一 Makefile

1.1 OS镜像文件ucore.img 是如何一步步生成的?

+ cc kern/init/init.c
+ cc kern/libs/readline.c
+ cc kern/libs/stdio.c
+ cc kern/debug/kdebug.c
+ cc kern/debug/kmonitor.c
+ cc kern/debug/panic.c
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
+ cc kern/driver/console.c
+ cc kern/driver/intr.c
+ cc kern/driver/picirq.c
+ cc kern/trap/trap.c
+ cc kern/trap/trapentry.S
+ cc kern/trap/vectors.S
+ cc kern/mm/pmm.c
+ cc libs/printfmt.c
+ cc libs/string.c
+ ld bin/kernel
+ cc boot/bootasm.S
+ cc boot/bootmain.c
+ cc tools/sign.c
tools/sign.c: In function 'main':
tools/sign.c:17:5: warning: unknown conversion type character 'l' in format [-Wformat=]
printf("'%s' size: %lld bytes\n", argv[1], (long long)st.st_size);
^
tools/sign.c:17:5: warning: too many arguments for format [-Wformat-extra-args]
tools/sign.c:19:9: warning: unknown conversion type character 'l' in format [-Wformat=]
fprintf(stderr, "%lld >> 510!!\n", (long long)st.st_size);
^
tools/sign.c:19:9: warning: too many arguments for format [-Wformat-extra-args]
+ ld bin/bootblock
'obj/bootblock.out' size: 480 bytes
build 512 bytes boot sector: 'bin/bootblock' success!

其中Makefile文件中include tools/function.mk  其中定义了一些Makefile中用到的函数

生成ucore.img  需要kernel和bootblock 如下:

# create ucore.img
UCOREIMG := $(call totarget,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 $(call create_target,ucore.img)

kernel编译链接:

# -------------------------------------------------------------------
# kernel # kernel中头文件目录
KINCLUDE += kern/debug/ \
kern/driver/ \
kern/trap/ \
kern/mm/ # kernel的源代码目录
KSRCDIR += kern/init \
kern/libs \
kern/debug \
kern/driver \
kern/trap \
kern/mm # 在编译选项中添加头文件包含目录
KCFLAGS += $(addprefix -I,$(KINCLUDE)) # 调用function.mk中的add_files_cc函数,将kernel的全部源文件编译,将源文件和编译生成的OBJ文件加入kernel包(packet)中
$(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS)) # 将KOBJS定义为编译生成的.o文件列表(大概??)
KOBJS = $(call read_packet,kernel libs) # 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 -o $@ $(KOBJS)
# 将OBJ文件全部反编译为汇编文件
@$(OBJDUMP) -S $@ > $(call asmfile,kernel)
# 输出OBJ文件对应的符号表
@$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel) # 将kernel包和OBJ文件添加到目标依赖
$(call create_target,kernel)

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)

sign:

# -------------------------------------------------------------------

# 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)

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)

dd的一些参数的含义:(dd命令说明
-if表示输入文件,如果不指定,那么会默认从stdin中读取输入
-of表示输出文件,如果不指定,那么会stdout
bs表示以字节为单位的块大小
count表示被赋值的块数
/dev/zero是一个字符设备,会不断返回0值字节\0
conv = notrunc 不截短输出文件
seek=blocks 从输出文件开头跳过blocks个块后再开始复制

生成kernel的.obj实际命令:

gcc -Ikern/init/ -fno-builtin -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
gcc -Ikern/libs/ -fno-builtin -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
gcc -Ikern/libs/ -fno-builtin -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
gcc -Ikern/debug/ -fno-builtin -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
gcc -Ikern/debug/ -fno-builtin -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
gcc -Ikern/debug/ -fno-builtin -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
gcc -Ikern/driver/ -fno-builtin -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
gcc -Ikern/driver/ -fno-builtin -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
gcc -Ikern/driver/ -fno-builtin -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
gcc -Ikern/driver/ -fno-builtin -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
gcc -Ikern/trap/ -fno-builtin -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
gcc -Ikern/trap/ -fno-builtin -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
gcc -Ikern/trap/ -fno-builtin -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
gcc -Ikern/mm/ -fno-builtin -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
gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -c libs/string.c -o obj/libs/string.o
gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -c libs/printfmt.c -o obj/libs/printfmt.o

参数及其意义:(gcc官方文档

    • -I:添加包含目录
    • -fno-builtin:只接受以“__builtin_”开头的名称的内建函数
    • -Wall:开启全部警告提示
    • -ggdb:生成GDB需要的调试信息
    • -m32:为32位环境生成代码,int、long和指针都是32位
    • -gstab:生成stab格式的调试信息,仅用于gdb
    • -nostdinc:不扫描标准系统头文件,只在-I指令指定的目录中扫描
    • -fno-stack-protector:生成用于检查栈溢出的额外代码,如果发生错误,则打印错误信息并退出
    • -c:编译源文件但不进行链接
    • -o:结果的输出文件

链接生成kernel二进制文件的命令为:

    • ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o obj/kern/libs/stdio.o obj/kern/libs/readline.o obj/kern/debug/panic.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/picirq.o obj/kern/driver/intr.o obj/kern/trap/trap.o obj/kern/trap/vectors.o obj/kern/trap/trapentry.o obj/kern/mm/pmm.o  obj/libs/string.o obj/libs/printfmt.o

      参数及其意义:(ld参数说明

      • -m elf_i386:使用elf_i386模拟器
      • -nostdlib:只查找命令行中明确给出的库目录,不查找链接器脚本中给出的(即使链接器脚本是在命令行中给出的)
      • -T tools/kernel.ld:将tools/kernel.ld作为链接器脚本
      • -o bin/kernel:输出到bin/kernel文件

      生成bootblock和sign工具所需全部OBJ文件的实际命令包括:

      gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootasm.S -o obj/boot/bootasm.o
      gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootmain.c -o obj/boot/bootmain.o
      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

      参数及其意义(重复的参数不再列出):

      • -Os:对输出文件大小进行优化,开启全部不增加代码大小的-O2优化
      • -g:以操作系统原生格式输出调试信息,gdb可以处理这一信息
      • -O2:进行大部分不以空间换时间的优化

      链接生成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: 488 bytes
      build 512 bytes boot sector: 'bin/bootblock' success!(这两行是sign的输出)

      参数及其意义:

        • -N:将文字和数据部分置为可读写,不将数据section置为与页对齐, 不链接共享库
        • -e start:将start符号置为程序起始点
        • -Ttext 0x7C00:链接时将".bss"、".data"或".text"置于绝对地址0x7C00

1.2 一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?

tool/sign.c

输入的主引导扇区记录小于等于510字节(446+64)

最后两个字节是0x55AA

练习2:

  使用Qemu和gdb调试lab1 实验目的:熟悉单步调试gdb方法 进一步了解os启动流程

练习3:

  bootloader进入保护模式的过程

  BIOS通过读取硬盘主引导扇区到内存,并跳转到对应内存中的位置执行bootloader,从实模式转换到保护模式。

bootloader启动过程主要工作:1切换到保护模式,启用分段机制

     2读磁盘中ELF执行文件格式的ucore到内存

     3显示字符串信息

     4把控制权交给ucore操作系统

1.开启A20地址线

2.初始化GDT表

3.进入保护模式

Ucore lab1实验报告的更多相关文章

  1. 《ucore lab1 exercise5》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 题目:实现函数调用堆栈跟踪函数 我们需要在lab1中完成kdebug.c中函数print_stackframe的实现,可以通过函数print_s ...

  2. 《ucore lab1》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1:理解通过make生成执行文件的过程 详见<ucore lab1 exercise1>实验报告 练习2:使用qemu执行并调试 ...

  3. 《ucore lab1 exercise3》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 题目:分析bootloader进入保护模式的过程 BIOS将通过读取硬盘主引导扇区到内存,并转跳到对应内存中的位置执行bootloader.请分 ...

  4. 《ucore lab1 exercise2》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 题目:使用qemu执行并调试lab1中的软件 为了熟悉使用qemu和gdb进行的调试工作,我们进行如下的小练习: 从CPU加电后执行的第一条指令 ...

  5. 《ucore lab1 exercise1》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 题目:理解通过make生成执行文件的过程 列出本实验各练习中对应的OS原理的知识点,并说明本实验中的实现部分如何对应和体现了原理中的基本概念和关 ...

  6. 《ucore lab1 exercise4》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 题目:分析bootloader加载ELF格式的OS的过程 通过阅读bootmain.c,了解bootloader如何加载ELF文件.通过分析源代 ...

  7. 《ucore lab1 exercise6》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 题目:完善中断初始化和处理 请完成编码工作和回答如下问题: 中断描述符表(也可简称为保护模式下的中断向量表)中一个表项占多少字节?其中哪几位代表 ...

  8. 《ucore lab5》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 加载应用程序并执行(需要编码) 题目 do_execv函数调用load_icode(位于kern/process/proc.c中) 来 ...

  9. 《ucore lab8》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 完成读文件操作的实现(需要编码) 题目 首先了解打开文件的处理流程,然后参考本实验后续的文件读写操作的过程分析,编写在sfs_inod ...

随机推荐

  1. 洛谷P1085 不高兴的津津

    题目描述 津津上初中了.妈妈认为津津应该更加用功学习,所以津津除了上学之外,还要参加妈妈为她报名的各科复习班.另外每周妈妈还会送她去学习朗诵.舞蹈和钢琴.但是津津如果一天上课超过八个小时就会不高兴,而 ...

  2. DVWA之Brute Force(暴力破解)

    目录 Low Medium High Impossible 暴力破解是指使用穷举法,举出所有的可能的结果,然后逐一验证是否正确! Low 源代码: <?php if( isset( $_GET[ ...

  3. POJ2688状态压缩(可以+DFS剪枝)

    题意:       给你一个n*m的格子,然后给你一个起点,让你遍历所有的垃圾,就是终点不唯一,问你最小路径是多少? 思路:       水题,方法比较多,最省事的就是直接就一个BFS状态压缩暴搜就行 ...

  4. Windows核心编程 第2 5章 未处理异常和C ++异常(上)

    未处理异常和C + +异常(上) 前一章讨论了当一个异常过滤器返回 E X C E P T I O N _ C O N T I N U E _ S E A R C H时会发生什么事情.返回EXCEPT ...

  5. 哈希爆破神器Hashcat的用法

    目录 HashCat HshCat的使用 使用Hashcat生成字典 使用Hashcat破解NTLMv2 HashCat HashCat系列软件在硬件上支持使用CPU.NVIDIA GPU.ATI G ...

  6. SpringBoot项目启动后自动打开浏览器

    编写一个类,注册为Spring的Bean,然后实现CommandLineRunner接口,重写run()方法即可 @Component public class OpenBrowser impleme ...

  7. Xshell6连Linux

    一.安装 文件 链接: 提取码:8rmr 二.连Linux 名称填自己喜欢的.续之前,我们保持一样的名字.主机填IP,根据之前Linux填的静态IP去连接. 然后双击,连接 我们用最高权限,填root ...

  8. 如何使用mongo shell

    Cd到MongoDb安装目录到bin目录下,执行mongo命令即可,其他命令参考手册:https://www.runoob.com/mongodb/mongodb-create-collection. ...

  9. 曾经我认为C语言就是个弟弟

    本文所有代码,均上传至github,如果你想直接看源代码,请到github下载,下载地址:https://github.com/vitalitylee/TextEditor "C语言只能写有 ...

  10. LinkedList作为栈和队列的使用

    最近在LeekCode用java写一些算法时,经常遇到要使用栈和队列结构,使用栈的话,Stack已经不被推荐使用了,所以栈和队列我们通常都是用LinkedList这种双链表结构实现.Linkedlis ...