lab1 实验报告

思考题

Thinking 1.1

image-20220327113157554

参数含义:

objdump -D test     反汇编test中的所有section
objdump -S test     将代码段反汇编的同时,将反汇编代码和源代码交替显示,编译时需要给出-g,即需要调试信息。

我的link script:

SECTIONS
{ 
    . = 0x10000;
    .text : { *(.text) }
    . = 0x8000000;
    .data : { *(.data) }
    .bss : { *(.bss) }
}

我的think1.c

int main() {
    int a = 1;
    int b = 2;
    int c = a + 2;
    return 0;
}

使用以下命令进行操作:

cppath=/OSLAB/compiler/usr/bin/mips_4KC-  	#不想打那么多次路径,用变量记录路径
${cppath}gcc -E think1.c > E-think1   		#预处理
${cppath}gcc -c think1.c					#编译think1.c
${cppath}ld think1.o -T my.lds -o think1 	#链接并重命名可执行文件
${cppath}objdump -DS think1.o >o.txt  		#反汇编.o文件
${cppath}objdump -DS think1 >out.txt  		#反汇编.out可执行文件

以下为预处理和反汇编得到的结果:

E-think1: (源文件预处理后的结果)

# 1 "think1.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "think1.c"
int main() {
 int a = 1;
 int b = 2;
 int c = a + 2;
 return 0;
}

o.txt:

think1.o:     file format elf32-tradbigmips

Disassembly of section .text:

00000000 <main>:
   0:   27bdffe0    addiu   sp,sp,-32
   4:   afbe0018    sw  s8,24(sp)
   8:   03a0f021    move    s8,sp
   c:   24020001    li  v0,1
  10:   afc20010    sw  v0,16(s8)
  14:   24020002    li  v0,2
  18:   afc2000c    sw  v0,12(s8)
  1c:   8fc20010    lw  v0,16(s8)
  20:   24420002    addiu   v0,v0,2
  24:   afc20008    sw  v0,8(s8)
  28:   00001021    move    v0,zero
  2c:   03c0e821    move    sp,s8
  30:   8fbe0018    lw  s8,24(sp)
  34:   27bd0020    addiu   sp,sp,32
  38:   03e00008    jr  ra
  3c:   00000000    nop
Disassembly of section .reginfo:

00000000 <.reginfo>:
   0:   e0000004    sc  zero,4(zero)
    ...
Disassembly of section .pdr:

00000000 <.pdr>:
   0:   00000000    nop
   4:   40000000    mfc0    zero,c0_index
   8:   fffffff8    sdc3    $31,-8(ra)
    ...
  14:   00000020    add zero,zero,zero
  18:   0000001e    0x1e
  1c:   0000001f    0x1f
Disassembly of section .comment:

00000000 <.comment>:
   0:   00474343    0x474343
   4:   3a202847    xori    zero,s1,0x2847
   8:   4e552920    c3  0x552920
   c:   342e302e    ori t6,at,0x302e
  10:   30202844    andi    zero,at,0x2844
  14:   454e5820    0x454e5820
  18:   454c444b    0x454c444b
  1c:   20342e31    addi    s4,at,11825
  20:   20342e30    addi    s4,at,11824
  24:   2e302900    sltiu   s0,s1,10496

out.txt:

think1:     file format elf32-tradbigmips

Disassembly of section .text:

00010000 <main>:
   10000:       27bdffe0        addiu   sp,sp,-32
   10004:       afbe0018        sw      s8,24(sp)
   10008:       03a0f021        move    s8,sp
   1000c:       24020001        li      v0,1
   10010:       afc20010        sw      v0,16(s8)
   10014:       24020002        li      v0,2
   10018:       afc2000c        sw      v0,12(s8)
   1001c:       8fc20010        lw      v0,16(s8)
   10020:       24420002        addiu   v0,v0,2
   10024:       afc20008        sw      v0,8(s8)
   10028:       00001021        move    v0,zero
   1002c:       03c0e821        move    sp,s8
   10030:       8fbe0018        lw      s8,24(sp)
   10034:       27bd0020        addiu   sp,sp,32
   10038:       03e00008        jr      ra
   1003c:       00000000        nop
Disassembly of section .reginfo:

00010040 <.reginfo>:
   10040:       e0000004        sc      zero,4(zero)
        ...
Disassembly of section .pdr:

00000000 <.pdr>:
   0:   00010000        sll     zero,at,0x0
   4:   40000000        mfc0    zero,c0_index
   8:   fffffff8        sdc3    $31,-8(ra)
        ...
  14:   00000020        add     zero,zero,zero
  18:   0000001e        0x1e
  1c:   0000001f        0x1f
Disassembly of section .comment:

00000000 <.comment>:
   0:   00474343        0x474343
   4:   3a202847        xori    zero,s1,0x2847
   8:   4e552920        c3      0x552920
   c:   342e302e        ori     t6,at,0x302e
  10:   30202844        andi    zero,at,0x2844
  14:   454e5820        0x454e5820
  18:   454c444b        0x454c444b
  1c:   20342e31        addi    s4,at,11825
  20:   20342e30        addi    s4,at,11824
  24:   2e302900        sltiu   s0,s1,10496

以下为我用DiffMerge比较的o.txt和out.txt

image-20220327113943900

可见main()的地址在0x10000,与link script的设置一致。

Thinking 1.2

image-20220327102131108

此为我用系统自带的readelf -h来解析内核文件vmlinux 和测试文件testELF的结果。

image-20220326214345647

此图中上部为vmlinux内核文件,下部为测试testELF文件。
可见vmlinux为大端存储文件,mips机器。 testELF为小端文件,Intel机器。

由此可知我们的readelf程序只可以解析小端存储的文件。此外,还只能对32位文件进行分析。

Thinking 1.3

image-20220327114529559

​ 操作系统的启动分为两个部分,加电后取指寄存器复位到固定值(就是启动入口地址,这个地址是固定的,是硬件逻辑决定的),然后进入Stage1。
​ 在Stage1,执行硬件初始化和Stage2的准备工作并跳转到Stage2。
​ 在Stage2,才会进行内核和根文件系统的载入工作,得益于Stage1的处理,实现了硬件初始化和软件初始化的初步分离,此时完全可以根据内存布局图来加载内核。

​ 回看整个过程,启动入口地址是bootloader的位置,内核的载入在Stage2,此时已经可以使用RAM了,可以按照内存布局来加载内核。

​ 实验操作系统使用GXemul仿真器,支持直接加载ELF格式的内核。其已经提供Stage1的功能,可以按照内存布局来加载内核。

Thinking 1.4

image-20220327114750286

为了避免发生页面冲突现象。需要:

  1. 不同程序段占用空间尽量独立,没有重合
  2. 避免一个页面被多个程序段占用

因此,若当前程序占用的末页面为vi,那么后续程序应从vi+1页面开始。

Thinking 1.5

image-20220327151808994

通过查看顶层的Makefile文件,可以知道源码地址,通过反汇编内核,可以知道各函数在内存中的位置。以下为反汇编的结果:

image-20220327151938491

内核的入口在:学号/boot/start.S,存储地址为0x80010000。
main函数在学号/init/main.c,存储地址为0x80010040。

内核会从_start方法处开始,在该方法的结尾处有jal main,借此可以跳转到main函数中。

通过反汇编,可以看出每个函数会有一个确定的地址。在跨文件调用函数时,首先会将需要保存的数据入栈保护,再用jal跳转到相应函数的地址。

Thinking 1.6

image-20220327094221404

联系在学号/include/asm/cp0regdef中宏定义文件,可以将文件中的各个寄存器名与CP0中的寄存器对应
image-20220327095903801

 mtc0 zero,CP0_STATUS  	#将CP0中SR($12)寄存器清零
 mfc0 t0, CP0_CONFIG  	#取出CP0中$16的值 
 and t0,~0x7 			#后三位清零
 ori t0,0x2 			#将1号位置1
 mtc0 t0, CP0_CONFIG	#将处理后的值放回到CP0中$16,具体操作为将Config寄存器0号位和2号位置0,将1号位置1

实验难点展示

lab1难点

体会与感想

对课下部分的一些想法

​ 个人认为本次实验的课下部分难度并不是非常大,虽然需要大量阅读代码,但是因为有着指导书的详细教导,大任务被分割成了一个个小任务,总体而言还算知道要如何要做什么,难度不大。

​ 但是我认为思考题的难度太大,且缺少一些必要的教程和提醒。必须承认,通过思考题,我对于整个实验内容有了更加清晰和全面的了解。但是整个过程实在是太痛苦了,且浪费了大量宝贵的时间!!!因为思考题几乎没有提示,一旦卡住,大量的时间直接就浪费了。

​ 例如思考题1.1,各位助教大大能不能在指导书中提醒一下我们直接使用课程组的gcc是无法实现链接的?需要使用ld来完成链接。且能不能提一嘴让各位同学在完成了exercise 1.3之后再来尝试做本题。 在做本题时,我知道我需要使用课程组提供的工具进行反汇编,但是对于使用这些工具时会遇上的一些细节问题,我一无所知,就因为一个链接的问题,我被卡了至少两个小时没有进展,最后是找助教才解决的问题。

​ 总而言之,指导书为我们提供了一个很好的入门操作系统的机会,通俗的讲解和脉络清晰的指导书让我们学起来的体验非常好。 就是希望助教大大们可以在具体操作细节方面多写一些提示,让我们可以在一些小地方减少时间的消耗,将更宝贵的时间拿来阅读代码、理解整个系统。

感想

​ lab1是非常耗时也让我收获颇丰的一次学习经历。 个人至少在课下花费了超过12个小时。走了不少弯路。

​ 我学习lab1起码有三遍,第一遍是跟着指导书走一遍,完成了课下的exercise,理解了boot loader、elf、link script、print.c,成功完成了作业,但是对于我在lab1干了啥事没有一个宏观了解。

​ 第二遍也是跟着指导书走的,主要是为了完成思考题。这次注意到了boot loader中的三次初始化、会使用指导书中各种之前“看会”了的工具,对本次实验的流程有个一个大概的了解,我们整个lab1其实就只做了一个操作系统的启动而已。

​ 第三次学习是因为我决定扫盲,所以上网学了makefile,通过阅读makefile,我知道了整个lab的框架,又因为第二次学习时学会了“反汇编”这个好东西,所以就自己在虚拟机上随便玩,反汇编我们的虚拟机。必须要说OS项目真的是结构清晰、命名讲究。boot用于OS的启动后的初始化,lib中存的是本次实验中的print文件,是我们自己的lib,gxemul中存的是我们的OS,readelf中的是我们自己的readelf小工具……。

​ 除了感觉OS好nb之外,还感觉这玩意好花时间啊。下周OO电梯月就来了,课业压力好大啊,希望我的头发能活过这一学期。

指导书反馈

  1. 指导书错误
    指导书p73的Thinking1.4,显然没有把内容复制全,以下为mooc网上的截图和指导书的截图。
    image-20220327085603575
    image-20220327085618724
  2. mooc指导书中,此图右上角的va+i位置标错了,其应该在bin_size的结束位置
    image-20220327093453913

残留难点

​ gcc链接过程中,动态库和静态库的链接形式。

​ 链接器链接文件时,内核文件可以直接指出要的地址空间,实际也会加载过去,那么一般文件呢?可执行文件已经完成了编译与链接,即各函数的逻辑地址已经确定,一大群可执行文件需要的的逻辑地址势必有重叠,操作系统是如何解决这个问题的。

posted @ 2022-04-29 14:19  tantor  阅读(66)  评论(0编辑  收藏  举报