Ucore Lab1(上)

Ucore Lab1(上)

前情提要:

Vx6太难了, 👴🏻跑路了

日, 怎么Ubuntu里敲出来的中文这么怪

ppt来源于清华大学的操作系统网课

练习1:

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

在这里插入图片描述

先看一下makefile(选择编译器和编译器选项), 经过对比, 发现使用的是LLVM makefile系统, cc实际上为gcc编译 / ld链接选项有如下:

-g可调试 
-Wall会列举编译文件中的一些常见错误 
-O2为优化程度 
-march(架构?不会翻译)为i686 
-fno-builtin若自己的函数与库函数重名也可以通过编译
-fno-PIC不使用位置无关代码(因为开启pic会为got设定32k的限制, 所以可能会导致编译失败
-ggdb倾向gdb的可调试
-m32生成32位程序
-gstabs以stabs格式声称调试信息但是不包括gdb调试信息(.s文件中的信息)
-nostdinc不要在标准系统目录中寻找头文件
-fno-stack-protector关闭canary
-E仅作预处理、不编译、汇编或链接
-x c选定语言为c语言

vim看了一下Makefile, 主要目的还是生成kernel, bootblock, ucore.img, sign工具

链接kernel情况如下(编译文件太多就不截图了):

+ ld bin/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

其在makefile中的代码如下:

kernel = $(call totarget,kernel) #将/bin前缀添加到kernel中

$(kernel): tools/kernel.ld #kernel的依赖项为tools/kernel.ld

$(kernel): $(KOBJS) #kernel的依赖项为$(KOBJS), 在非"V="不打印@后的内容
    @echo + ld $@
    $(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS) #变量自己看咯,-T为选定指定ld文件作为完全替换 
    @$(OBJDUMP) -S $@ > $(call asmfile,kernel)
    @$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)

$(call create_target,kernel) #生成kernel

编译bootblock的依赖项情况如下:

+ 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

链接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
'obj/bootblock.out' size: 484 bytes
build 512 bytes boot sector: 'bin/bootblock' success!

其在makefile中代码如下:

bootfiles = $(call listf_cc,boot)
$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))   
#上面一句的意思是, 先用listf_cc函数列举出所用boot文件夹中的c语言文件到变量bootfiles中
#再用foreach函数循环, 将bootfiles中的文件枚举到临时变量f中, 然后依次对f中的文件以CFLAGS的选项
#再加上-Os, -nostdinc(不用标准库)以gcc进行编译

bootblock = $(call totarget,bootblock) #先增加/bin前缀到bootblock中

$(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign) 
#上面的意思是获得/obj前缀到生成的.oqi依赖项中, 并且将sign(后面会讲)添加/bin前缀
    @echo + ld $@
    $(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock) 
		#-N把text和data节设置为可读写.同时,取消数据节的页对齐,同时,取消对共享库的连接. -e start将符号start设置为程序起始位置. 
		#-Ttext 0x7C00将该地址设置为.bss或.text或.data
    @$(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) #生成bootblock

最终生成了一个512字节大小的boot扇区

编译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
#太短, 懒得备注了属于是

其在makefile中如下

# create 'sign' tools
$(call add_files_host,tools/sign.c,sign,sign)                                     
$(call create_target_host,sign,sign) 
#用tools/sign.c创建一个sign/sign

此举用于生成一个符合规范的硬盘主引导扇区

生成ucore.img情况如下:

dd if=/dev/zero of=bin/ucore.img count=10000
10000+0 records in
10000+0 records out
5120000 bytes (5.1 MB, 4.9 MiB) copied, 0.0225575 s, 227 MB/s
dd if=bin/bootblock of=bin/ucore.img conv=notrunc
1+0 records in
1+0 records out
512 bytes copied, 0.000109965 s, 4.7 MB/s
dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc
146+1 records in
146+1 records out
74828 bytes (75 kB, 73 KiB) copied, 0.000395085 s, 189 MB/s

其在makefile中如下:

UCOREIMG    := $(call totarget,ucore.img) #定义变量, 且将ucore.img添加/bin前缀

$(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
#创建一个10000块将/dev/zero拷贝进去
#将$(bootblock)拷贝到同一个位置(不截短输出文件 )
#将$(kernel)拷贝到同一位置(从输出文件开头跳过1个块后再开始拷贝)

$(call create_target,ucore.img) #生成ucore.img

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

通过分析sign.c文件我们可以得到答案如下:

  1. block.out的大小小于510字节
  2. 扇区大小为512字节
  3. 扇区结尾为0x55AA

练习二:

大概就是总结总结自己gdb的使用吧:

  1. pwndbg中的类会报错
  2. gdb原来的操作界面实在太丑了
  3. peda可用, 但显示源码不方便
  4. 同时修改lab1文件夹tools/gdbinit也无法使得make debug出来的gdb变为peda, 所以就只能使用qemu-system-i386来开启后在用gdb给连上去了
  5. 在启动后的第一条指令被卡住过, 我的界面如下:

在这里插入图片描述

可用看到执行的命令为add…但是分析一下明显不对, 因为eax为0, 若add ptr [eax]则肯定报错, 但是程序没有报错, 同时eip发生了改变, 所以看了一眼官方文档:

在这里插入图片描述

然后开动了一下猪脑才发现此时的cs设置为了0xf000, 所以真正的执行地址为0xffff0, 指令为上面的ljmp, 呜呜呜, 我好笨(这个玩意是16位! 所以要改变自己平时32位和64位的想法啦~), 之后开始执行bootblock.o是从0x07c00开始的, 因为之前在ld的时候, 有参数 -Ttext 0x7c00, 详情可man ld查看

  1. gdb的汇编显示语法在配置文件中要把set写在peda的配置下面, 因为peda默认是intel

其实还是有关于分析的内容的:

  1. 0x7c00基本上才算是真正的启动内核初始化地址(bootloader)

  2. 待解决(1)

  3. 设置重要的段地址DS, ES, SS为0

  4. 开启A20接口, 向后兼容的一种, 使得物理地址线20被绑定到低电平, 因此高于1MB的地址线会被置为0

  5. 从0x64端口读取信号, 一开始我读入的elfags, 如果读入是0x1c则说明0x64端口不忙碌(注: test执行的是and操作, 我记错了…), 不忙碌通常是这个结果PF+ZF+2(2是之前产生的, 其不是标志)

    在这里插入图片描述

  6. 将0xd1传给0x64端口, 代表将从P2端口写数据

  7. 再次等待0x64端口不忙碌, 发送0xdf给0x60端口

    在这里插入图片描述

    即打开A20地址线

在这里插入图片描述
这里是打开cr0的pe位置
至此经过7, 8两步, 实际上实模式切换到保护模式的准备工作就完成了, 后面一个跳转就跑到保护模式了

  1. 保护模式在执行bootmain之前在ucore中就只是设置设置寄存器, 设置设置栈啥的

学堂在线第三讲:

3.1:

  1. cpu加电以后会先执行BIOS, 其作用为:

    1. 将加载程序(0000: 0x7c00)加载到引导扇区
    2. 跳转到加载程序

    之后加载程序的作用为:

    1. 将操作系统的代码和数据加载到内存中
    2. 跳转到操作系统开头

    所以说BIOS和加载程序感觉就像两个跳转一样, 而其还有一个作用为识别操作系统格式

  2. 实模式: 执行BIOS和加载程序的程序, 此时是固定为20位地址线, 寻址方式为 基址*0x10000+偏移, 最大寻址空间为1MB, 此时所有段可读可写可执行, 而且在某些实模式中会有一些只能在实模式中使用的中断(如intel)

在这里插入图片描述

3.2:

  1. BIOS的其它一些作用: 自检类似显卡等关键部件的工作状态, 然后继续部件初始化, 进行系统检测(包括一些U盘中即插即用的系统), 更新CMOS中的拓展系统配置数据ESCD
  2. 还讲到多分区的东东, 由于ucore好像不涉及这玩意, 所以看图就行了:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    最后一幅图是我根据《鸟哥的Linux私房菜》总结出来的…

待解决的问题:

什么是string operations increment

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值