ucore lab1及challenge

练习1

一、ucore.img是如何一步一步生成的?

1. 生成ucore.img需要kernelbootblock

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

生成ucore需要kernelbootblock文件
创建一个10000块将/dev/zero拷贝进去
$(bootblock)拷贝到同一个位置(不截短输出文件 )
$(kernel)拷贝到同一位置(从输出文件开头跳过1个块后再开始拷贝 )


2. 生成 kernel

# create kernel target
kernel = $(call totarget,kernel)

$(kernel): tools/kernel.ld

$(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)

$(call totraget,kernel)指令中,将bin/前缀加到kernel中
生成bin/kernel

链接所有的目标文件生成elf-i386的内核文件
通过make V=命令得到了

+ 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

由此可以看到生成kernel的过程中,需要用GCC将目标文件从.c转换成如下的.o文件


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

3.生成bootblock

# create bootblock
bootfiles = $(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)

bootflies表示boot下所有文件,包括

asm.h
bootasm.S
bootmain.c

先把bootfiles中的bootasm.S,bootmain.c编译成bootasm.obootmain.o
再由bootasm.obootmain.osign生成bootblock

生成bootasm.obootmain.o的代码

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

通过make V=可以看到生成bootasm.obootmain.o的过程

+ cc boot/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

+ cc boot/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

生成sign的代码
(sign.c是一个C语言小程序,是辅助工具,用于生成一个符合规范的硬盘主引导扇区。)

# create 'sign' tools
$(call add_files_host,tools/sign.c,sign,sign)
$(call create_target_host,sign,sign)

通过make V=看到生成sign的过程

+ 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

生成bootblock的过程

+ 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

查询相关资料:

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

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

生成bootblock和sign工具所需全部OBJ文件的相关命令参数:
-Os:对输出文件大小进行优化,开启全部不增加代码大小的-O2优化
-g:以操作系统原生格式输出调试信息,gdb可以处理这一信息
-O2:进行大部分不以空间换时间的优化

链接生成bootblock二进制文件的相关命令参数为:
-N:将文字和数据部分置为可读写,不将数据section置为与页对齐, 不链接共享库
-e start:将start符号置为程序起始点
-Ttext 0x7C00:链接时将".bss"、".data"或".text"置于绝对地址0x7C00处

生成ucore.img的命令相关参数:
if:输入
of:输出
count=10000:只拷贝输入的10000块
conv=notrunc:不截短输出文件
seek=1:从输出文件开头跳过1个块后再开始复制

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

可以通过研究sign.c获取主引导扇区的规范

char buf[512];
    memset(buf, 0, sizeof(buf));
    FILE *ifp = fopen(argv[1], "rb");
    int size = fread(buf, 1, st.st_size, ifp);
    if (size != st.st_size) {
   
        fprintf(stderr, "read '%s' error, size is %d.\n", argv[1], size);
        return -1;
    }
    fclose(ifp);
    buf[510] = 0x55;
    buf[511] = 0xAA;
    FILE *ofp = fopen(argv[2], "wb+");
    size = fwrite(buf, 1, 512, ofp);
    if (size != 512) {
   
        fprintf(stderr, "write '%s' error, size is %d.\n", argv[2], size);
        return -1;
    }

由上可知,
符合规范的硬盘主引导扇区的特征是

  • 扇区大小为512字节
  • 最后两个字节为0xAA

练习2

1. 从CPU加电后执行的第一条指令开始,单步跟踪BIOS的执行。

tools/gdbinit中添加set architecture i386一行,
然后进入lab1/根目录下,输入make deb

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值