代码阅读报告1_涂李傲

更新时间:2023-06-29 19:44:25 阅读: 评论:0

代码阅读报告(1)
涂李傲 2010013234软01
目录
1:阅读内容
2:代码阅读
2.1        asm.h
2.2        bootasm.s
2.3        x86.h
2.4        elf.h
2.5        bootmain.c
3:操作系统启动引导的流程分析
4:简答题
5:阅读心得
1:阅读内容
本次阅读包含以下几个文件:
asm.h:是bootasm.s汇编文件所需要的头文件,主要是一些与X86保护模式的段访问方式相关的宏定义。
bootasm.s:定义并实现了bootloader最先执行的函数start,此函数进行了一定的初始化,完成了从实模式到保护模式的转换,并调用bootmain.c中的bootmain函数。
types.h:包含一些无符号整型的缩写定义。
x86.h:一些用GNU C 嵌入式汇编实现的C 函数。
elf.h:定义了ELF 文件的结构。
bootmain.c:定义并实现了bootmain 函数。
2:代码阅读
2.1.asm.h
    该文件是bootasm.s汇编文件所需要的头文件,主要是一些段描述符的宏定义。
        (1)敛容
        #define SEG_NULLASM                                                \
        .word 0, 0;                                                        \
        .byte 0, 0, 0, 0                                                \
        代码功能:把段(长度为8字节)基地址和大小都置为0(感觉有点像null~),然后在bootasm.h中的
gdt:
        SEG_NULLASM                            # null g
调用了这个函数,构建了空段。
        (2)
        #define SEG_ASM(type,ba,lim)                                      \
        .word (((lim) >> 12) & 0xffff), ((ba) & 0xffff);                  \可爱女孩头像萌图片
        .byte (((ba) >> 16) & 0xff), (0x90 | (type)),                    \
                (0xC0 | (((lim) >> 28) & 0xf)), (((ba) >> 24) & 0xff)
        代码功能:定义了长度为8字节的一般段。
        (3)
        #define STA_X    0x8      // Executable gment
#define STA_E    0x4      // Expand down (non-executable gments)
瘦肚子方法
#define STA_C    0x4      // Conforming code gment (executable only)
#define STA_W    0x2      // Writeable (non-executable gments)
#define STA_R    0x2      // Readable (executable gments)cpu过高
#define STA_A    0x1      // Accesd
        定义了段的六种类型
2.2.bootasm.s
        该文件保存于硬盘设备的第一个扇区中,在开机的时候由BIOS加载到物理内存的0x7C00~0x7CFF处,然后在”real mode”下开始执行,此时有%CS=0        %IP=0x7C00
    (1)
        start:
        cli                        # Disable interrupts
    此处开始进入start函数,先发出一条指令“cli”,那么它的用处是关闭中断。这里我的理解是BIOS就像一个小的CPU,它自己会产生中断,但是这个时候BIOS已经运行完了,如果放任这些中断存在的话就会给硬件提供“interrupt handlers”,但是这个时候存在“interrupt handlers”是不安全的,所以我们要关闭中断,等到x86准备好了再重新恢复中断。
    (2)
xorw    %ax,%ax            # Segment number zero
        movw    %ax,%ds            # -> Data Segment
        movw    %ax,%es            # -> Extra Segment
        movw    %ax,%ss            # -> Stack Segment
    由于在BIOS中寄存器的值是不可知的,所以为了后面能够正常运行,在这里需要将寄存器进行初始化,这样代码就很直观了。就是先将寄存器%ax置为0,再将0值赋给%ds,%es和%ss
    (3)
    ta20.1:
        inb    $0x64,%al              # Wait for not busy
        testb  $0x2,%al
        jnz    ta20.1
        movb    $0xd1,%al              # 0xd1 -> port 0x64
        outb    %al,$0x64
ta20.2:
        inb    $0x64,%al              # Wait for not busy
        testb  $0x2,%al
        jnz    ta20.2
        movb    $0xdf,%al              # 0xdf -> port 0x60
        outb    %al,$0x60
无可替代的英文
    根据x86相关文档,gment:offt模式可以表示21位的物理地址,但是 Intel 8088 只支持 20位内存地址,但是通过段-偏移方式可以支持21位内存地址。这样一来 Intel 8088 会将自动丢弃最高位的数据从而出现错误。IBM为了避免这个问题,于是提供了一种兼容方式:当键盘控制器输出端口的第 2位为低位时, A20始终清零,而当其置为高位时,A20可以正常使用。
    在这段代码中通过检测0x64寄存器中的第二位是否为1来判断键盘缓存中是否有数据。当键盘空闲(第二位为0时)的时候向0x64寄存器中写入0xd1(表示下一个写入 0x60 端口的数据将被置于 8042 键盘控制器的输出端口),向0x60寄存器中写入0xdf(将键盘控制端口的第二位置为1)打开A20地址线,这样就可以使用21位地址啦!
群管理员
(4)
lgdt    gdtdesc
movl    %cr0, %eax
orl    $CR0_PE, %eax
movl    %eax, %cr0
    第一行的作用是将GDT的地址设置为gdtdesc。一旦装载了GDT 寄存器,扇区就会通过将CR0_PE 装入寄存器cr0开启“protected mode”。后面三行的作用则是置%cr0 寄存器的 PE 位。$CR0_PE=1,因此,这三行是置%cr0 寄存器的第 0 位为 1,该位为 0 时,CPU 运行于“real mode”,为 1 时,CPU 运行于“protected mode”。当第四行执行完成后,CPU 就运行在保护模式下了。
    (5)莫尔道嘎
        ljmp    $(SEG_KCODE<<3), $start32
    这一行因为有很长的注释,所以显得很直观。由于在进入“protected mode”的时候不会让系统进入32位模式,所以设置这么一个触发事件,将程序从16位转换到32位模式下。
    (6)
start32:
# Set up the protected-mode data gment registers
movw    $(SEG_KDATA<<3), %ax    # Our data gment lector
movw    %ax, %ds                # -> DS: Data Segment
movw    %ax, %es                # -> ES: Extra Segment
movw    %ax, %ss                # -> SS: Stack Segment
movw    $0, %ax                # Zero gments not ready for u
movw    %ax, %fs                # -> FS
movw    %ax, %gs                # -> GS
连连看20合1    这一块的作用和bootasm.s最前面一块的作用基本是类似的,就不多说了。
(7)
        movl    $start, %esp
        call    bootmain
    将$start的地址(0x7C00)赋值给%esp寄存器,将0x7C00设置为栈顶,之后栈指针就会从 0x7c00 开始递减,而不会覆盖掉启动扇区的代码。而后面那一行就要开始调用bootmain函数了,这个函数到目前为止还没有出现,所以我会在后面详细说。
    (8)
movw    $0x8a00, %ax            # 0x8a00 -> port 0x8a00
movw    %ax, %dx
outw    %ax, %dx
movw    $0x8ae0, %ax            # 0x8ae0 -> port 0x8a00
outw    %ax, %dx
pin:
jmp    spin
        这段代码从boot.pdf上来看好像是用来处理错误的,一般情况下我们不会调用,而一旦调用就会出现死循环,这个时候有这么一句话:“A real boot ctor might attempt to print an error message first”。估计这样的直接结果就是重新启动计算机吧……
        好的,现在我们已经把bootasm.s给过了一遍,感觉总体上和boot.pdf讲的差不多,接下来我们来看看几个头文件~
    2.3        x86.h
    该头文件包含了嵌入式汇编的C函数,供 C程序使用汇编指令。由于在第一次作业中不是所有定义过的函数都出现了,所以下面我只介绍在bootmain.c中被用到的函数;
    (1)
staticinline uchar
inb(ushort port)
{
  uchar data;
  asm volatile("in %1,%0" : "=a" (data) : "d" (port));

本文发布于:2023-06-29 19:44:25,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1068649.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:函数   键盘   定义   中断
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图