Living@Greatwall

entry.S

lab1提到bootloader的c文件最后会加载内核到物理地址0x10000处(64K)处,然后再执行内核的入口entry.S函数。

这里要特别注意:在此之前,所有的都是直接操作物理地址(怎么做到的?实时模式就不用说了,16位寻址1MB, 进入保护模式后,32位,bootloader把所有段寄存器设成0,除了esp,这个必须设置到正确的物理地址。 而且分页机制也没有使能,所以线性地址就是物理地址)。

在编译image时,kernel.ld会将内核的c代码的(entry.S仍在物理地址空间执行)起始地址链接到0xF0100000,也就是当内核执行c代码main时, 所有的指令的寻址都是以这个为基础,但是内核的实际物理地址是在0x100000,所以进入内核后第一件事就是要建立一个映射: 将起始地址为0xF0100000映射到物理地址0x100000(为以后的c代码执行准备好)。

内核入口函数entry.S中(仍在物理地址空间0x100000执行),一开始就是做这件事,使能分页机制(设置CR0):

 # Load the physical address of entry_pgdir into cr3.  entry_pgdir
 # is defined in entrypgdir.c …

lab1 exercise1

lab1主要熟悉qemu x86使用环境,各种实验工具,包括qemu与gdb联合调试等,熟悉pc的bootstrap过程,包括BIOS和bootloader。 该练习主要是实现一个backtrace函数,解析当前函数调用栈帧,并需要解析出当前函数的文件名、函数名、行号信息,如下面所示:

K> backtrace
Stack backtrace:
  ebp f010ff78  eip f01008ae  args 00000001 f010ff8c 00000000 f0110580 00000000
         kern/monitor.c:143: monitor+106
  ebp f010ffd8  eip f0100193  args 00000000 00001aac 00000660 00000000 00000000
         kern/init.c:49: i386_init+59
  ebp f010fff8 …

ELF文件

ELF(Executable and linking format)文件格式是Linux系统下的一种常用目标文件(object file)格式,有三种主要类型:

  • 用于执行的可执行文件(executab file),用于提供程序的进程映像,加载的内存执行。 这也是本实验的OS文件类型。

  • 用于连接的可重定位文件(relocatable file),可与其它目标文件一起创建可执行文件和共享目标文件。

  • 共享目标文件(shared object file),连接器可将它与其它可重定位文件和共享目标文件连接成其它的目标文件, 动态连接器又可将它与可执行文件和其它共享目标文件结合起来创建一个进程映像。

ELF文件是由一个ELF header和紧接着的几个program header(长度不等),这些program header指明了每个段的大小和内容,如:

*.text

*.rodata

*.data

1. Elf header结构

这里只分析与本实验相关的ELF可执行文件类型。ELF header在文件开始处描述了整个文件的组织。ELF的文件头包含整个执行文件的 控制结构,其定义在elf.h中:

struct  elfhdr  {
  uint  magic …

qemu和gdb调试

这里介绍如何用qemu和gdb联合调试:

1)在JOS目录下执行make qemu-gdb(或者make qemu-nox-gdb),此时qemu会执行并且等待gdb的连接; 2)然后在打开一个新的terminal,在同一个目录下输入:gdb即可(原理就是在这个目录下有个.gdbinit文件,gdb会读取这个文件); 没有出现错误的话,会出现下面的内容:

The target architecture is assumed to be i8086 [f000:fff0] 0xffff0: ljmp $0xf000,$0xe05b 0x0000fff0 in ?? () + symbol-file obj/kern/kernel 如果出现错误:warning: File "/home/yj/yangjin/xv6/jos/.gdbinit" auto-loading has been declined by …

stab释疑

Reference: https://sourceware.org/gdb/onlinedocs/stabs.html

1. stabs简介

stabs代表一种信息格式,用来将程序的信息展示给调试器debugger。

1.2. Debugging information flow

一般编译流程:gcc把.c编译成.s,汇编器把.s转化成.o,链接器把.o和库文件组合生成可执行文件; 当-g选项打开时,gcc会往.s文件中加入额外的调试信息,然后这些调试信息被加入到.o和可执行文件中。 这个调试信息包括c源文件的一些信息,如文件名,行号,变量的类型和范围(type, scope),函数名字, 参数和范围(function names, parameters,scopes)。在最后生成的可执行文件中,会生成一个symbol table 和string table,debugger就是利用这两个表来获取程序的信息的。

注意 …

x86中断与异常

1、三种特殊的中断事件

异步中断(asynchronous interrupt)也称外部中断,简称中断 (interrupt):由CPU外部设备引起的外部事件如I/O中断、 时钟中断、控制台中断等是异步产生的 (即产生的时刻不确定),与CPU的执行无关;

异常(exception):而把在CPU执行指令期间检测到不正常的或非法的条件(如除零错、地访问越界)所引起的内部事件称作 同步中断(synchronous interrupt);

异常:把在程序中使用请求系统服务的系统调用而引发的事件, 称作陷入中断(trap interrupt),也称软中断(soft interrupt), 系统调用(system call)简称trap。

2、保护模式下的中断处理过程

当CPU收到中断(通过8259A完成,有关8259A的信息请看附录A)或者异常的事件时,它会暂停执行当前的程序或任务, 通过一定的机制跳转到负责处理这个信号的相关处理例程中,在完成对这个事件的处 理后再跳回到刚才被打断的程序或任务中。

中断向量和中断服务例程的对应关系主要是由IDT(中断描述符表)负责。操作 系统在IDT中设置好各种中断向量对应的中断描述符 …

lab1: bootloader

非计算机科班出生,OS学的不好,以前都学的是概念和理论知识,并没有动手实现一个操作系统。后来发现MIT有一门很有名的OS课程6.828,所以利用业余时间学了学。这门课程设计的很好, 从头到尾写一个操作系统,一共有7个实验,一步一步深入,OS名字叫JOS,本文纪录一下lab1的知识。

一、BIOS工作

1. bios启动后会读取bootloader

bootloader处于主引导扇区MBR(大小为512字节),主引导扇区由3部分组成: 主引导记录:也就是bootloader,大小占446字节; 分区表:占64字节; * 硬盘有效标志:0xAA55,也就是练习一的第二个问题,BIOS读取MBR时,会检查这两个幻数,如果不正确,则被认为是没有分区的硬盘。注意sign.c文件就是用来生成一个bootloader的工具。

2.上电后的第一条指令地址为0xFFFFFFF0

这是启动后的第一条执行指令,EPROM,而在该地址处只存放了一条跳转指令,跳到BIOS程序的起始点;BIOS完成自检和初始化后,会选择一个启动设备 (如软盘,硬盘等),并且读取该设备的主引导扇区到内存的0x7c00地址处,然后跳到0x7c00出执行bootloader,此时bootloader所在的地址为:0x7c00 -- 0x7d00;

实时模式与保护模式的区别 …

x86寄存器基础

http://oss.org.cn/kernel-book/ch02/2.3.1.htm

1. i386寄存器

80386作为80X86系列中的一员,必须保证向后兼容,也就是说,既要支持16位的处理器,也要支持32位的处理器。在8086中,所有的寄存器都是16位的, 下面我们来看一下80386中寄存器有何变化:

  • 把16位的通用寄存器、标志寄存器以及指令指针寄存器扩充为32位的寄存器段寄存器仍然为16位

  • 增加4个32位的控制寄存器

  • 增加4个系统地址寄存器

  • 增加8个调式寄存器

  • 增加2个测试寄存器

2. 通用寄存器

8个通用寄存器是8086寄存器的超集,它们的名称和用途分别为:

  • EAX 一般用作累加器

  • EBX 一般用作基址寄存器(Base)

  • ECX 一般用来计数(Count)

  • EDX 一般用来存放数据(Data)

  • ESP 一般用作堆栈指针(Stack Pointer)

  • EBP 一般用作基址指针(Base Pointer)

  • ESI …