[学习xv6课程]:lesson3-lecture 2

Xv6 lesson 3

课程内容

PC的硬件只是和X86的编程

这里是以PPT形式来展示了PC电脑的硬件结构,主要是要电脑结构,x86编程,gcc 调用协议,PC的模拟仿真。

硬件中说明电脑的大致的输入输出结构,CPU,储存结构,这个很符合冯衣·诺曼架构。电脑的储存中存放数据和指令。接着结构在执行指令时,代码时以指针形式,顺序执行代码。而对于CPU内部,简单介绍了通用寄存器,关于这几个寄存器的作用是:寄存器作为CPU内部资源,自然是最快的储存器,但量少,那么为了使代码运行速度更快,则使用通用寄存器作为缓冲单元,每次如加减,先从硬盘或者内存中调用数据到通用寄存器,然后加减再储存回存储器。除了通用寄存器,还有特殊寄存器,如:PC指针,Linker寄存器等。

接下来,介绍的是内存的操作,IO空间和指令。硬件地址的布局,大家可以详细的记住,这个对以后学习有好处。

其中”From C to running program”这一节初学者眼仔细取理解,怎么理解呢?

 

从你写的代码到机器码,它不是简单的翻译过程。首先要将你写的代码(.c)文件通过编译器(gcc)编译成汇编(.asm)。然后将汇编(.asm)编译成可执行文件(.o)文件吗,其中的.o文件大多以elf文件格式存在。最好Linker(ld链接器)将若干个.o文件链接起来编程一个程序。最好通过loader将其加载内存。

 

预习(Preparation

在《book-rev6.pdf》中有两个附录(appendix),附录A与附录B主要讲的是:

附录A:

PC 硬件:

这部分内容主要讲的PC的硬件组成,要知道PC 抽象为三个组件:CPU、内存和输入/输出 (I/O) 设备。其余的可以看原书籍,或者推荐看中文的计算机组成原理一书。

处理器与内存:

处理器只能度取程序和按照程序来走,从内存地址中取出要执行的机器码和操作数,它并不能修改程序。

现代的x86架构的处理器有832位的通用寄存器:%eax, %ebx,%ecx, %edx, %edi, %esi, %ebp, %esp。另外一个程序计数器(PC-program counter):%eip。如果知道内部cpu的运行结构就无需阅读下去,初学者最好学习改部分知识。

寄存器快但是贵,所以寄存器使用的比较少,只有CPU内有少量的寄存器。所以现代计算的内存架构通常都是层级架构:寄存器-L1 cache-L2 cache-主存(RAM)。这样的速度是递减的,但能够很好的解决价格和速度问题。

输入输出(I/O:

X86电脑提供了特殊指令来读取或输出通过IO端口。这些指令的硬件实现与读写内存本质上是一样的。早期的 x86 处理器有一个额外的地址线:0 表示从 I/O 端口读/写,1 表示从主端口读/写。许多计算机体系结构没有单独的设备访问指令。反而设备具有固定的内存地址,处理器与设备(在操作系统的要求下)通过在这些地址读取和写入值。事实上,现代 x86 架构使用这种技术,称为内存映射(Memory map)

附录B

启动器(boot loader:

在你的操作系统程序启动前,还有一段程序需要运行。在PC中,它叫做BIOS,它储存在主板的ROM上,这里我知道的就是电脑的BIOS储存在一个小的芯片上,而非硬盘上。BIOS的工作就是准备好环境,比如:启动硬盘,启动内存,散热器,屏幕等驱动,然后将硬盘中的第一段代码(或者启动代码)引导进内存中,就让CPU直接读取内存中的代码去执行。

BIOS会执行初始化硬件代码,而它运行完了后会将程序控制权转给boot代码(从0x7C00开始)的代码。这段代码存放在硬盘的第一个512字节扇区,并且将该程序加载带内存0x7c00位置。总的来说就是BIOS会引导bootasm.S和bootmain.c到内存中执行。

原文执行过程:

具体来说,它转移控制从引导扇区加载的代码,引导磁盘的第一个 512 字节扇区。引导扇区包含引导加载程序:将内核加载到内存中的指令。 BIOS 在内存地址 0x7c00 加载引导扇区,然后跳转(设置处理器的 %ip) 到该地址。(注意一些16进制地址)

xv6 引导加载程序包含两个源文件,一个用 16 位和 32 x86 程序集(bootasm.S; (8200))组合编写的和一个用 C 编写的 (bootmain.c; (8300))

代码:引导程序汇编:

这里应该先下载xv6的源码,地址是:git clone git://pdos.csail.mit.edu/xv6/xv6.git。没有网的可以在附件中寻找(该网站我clone不下来,上git找的)

bootasm.s中可以看到:

:bootasm.S源码开始

start下面第一句是cli,这个是用来关中断的。中断是一种以硬件方式来唤醒OS进行处理的,BIOS是一个紧凑的操作系统,它可能会以中断处理方式来初始化硬件的,当BIOS不再运行时,或者说boot loader开始时,这样的方式就不再合适或者安全去处理来自硬件的中断。当xv6内核启动时(在第二章),有可以重新开中断。(BIOS需要用中断初始化代码,而boot程序这样的中断方式不安全,所以要关掉)。

xv6的视角来说x86 CPU是使用的虚拟地址来执行,而真实情况是x86需要逻辑地址(见图:逻辑地址、线性地址和物理地址之间的关系。)的指令来执行,所以其中加一个地址转换即可。逻辑地址是由段选择器和偏移量组成,有时候可以写成:段:偏移。分段硬件执行上述转换以生成线性地址。如果启动了分页硬件功能(请看第一章),它能将线性地址转换为逻辑地址。否则CPU会将线性地址当作逻辑地址。(xv6使用虚拟地址,而x86使用逻辑地址来跑,而逻辑地址又会由硬件从物理地址转换来)

Xv6系统中,因为某些历史原因,将虚拟地址等同于逻辑地址,也就是说物理地址经过地址转换器后就是虚拟地址。

BIOS不保证%ds, %es, %ss的内容,所以bootasm.S(后面称为:汇编boot)中要在cli(关中断后)将以上寄存器设置为0,所以借用%ax设为0来实现置0功能。

虚拟段由21bit,而intel 8088只能寻址20bit,那么就忽略最高位,但是由于后来硬件支持更多位数寻址,那么现在如果键盘控制器的输出端口的第2 bit是高,就启用21位地址,如果是低,就舍弃高位。

 

 

图:逻辑地址、线性地址和物理地址之间的关系。

未完待续,敬请期待!

 

posted @ 2022-03-21 20:15  邪恶法师  阅读(68)  评论(0编辑  收藏  举报