MIT6.828 Lab1:第2部分 The Boot Loader

MIT 6.828 学习笔记3 Lab1实验报告 Lab1实验报告Exercise 31. At what point does the processor start executing 32-bit code? What exactly causes the switch from 16- to 32-bit mode?在0x7c2d处的指令ljmp $PROT_MODE_CSEG, $protcseg跳转到了32位代码处,即从0x7c3 阅读详情

  对于PC来说,软盘,硬盘都可以被划分为一个个大小为512字节的区域,叫做扇区。一个扇区是一次磁盘操作的最小粒度。每一次读取或者写入操作都必须是一个或多个扇区。如果一个磁盘是可以被用来启动操作系统的,就把这个磁盘的第一个扇区叫做启动扇区。当BIOS找到一个可以启动的软盘或硬盘后,它就会把这512字节的启动扇区加载到内存地址0x7c00~0x7dff这个区域内。

  对于6.828,我们将采用传统的硬盘启动机制,这就意味着我们的boot loader程序的大小必须小于512字节。整个boot loader是由一个汇编文件,boot/boot.S,以及一个C语言文件,boot/main.c组成。Boot loader必须完成两个主要的功能。

  1. 首先,boot loader要把处理器从实模式转换为32bit的保护模式,因为只有在这种模式下软件可以访问超过1MB空间的内容。

  2. 然后,boot loader可以通过使用x86特定的IO指令,直接访问IDE磁盘设备寄存器,从磁盘中读取内核。

      对于boot loader来说,有一个文件很重要,obj/boot/boot.asm。这个文件是我们真实运行的boot loader程序的反汇编版本。所以我们可以把它和它的源代码即boot.S以及main.c比较一下。

Exercise3:
  在地址0x7c00处设置断点,这是boot sector被加载的位置。然后让程序继续运行直到这个断点。跟踪/boot/boot.S文件的每一条指令,同时使用boot.S文件和系统为你反汇编出来的文件obj/boot/boot.asm。你也可以使用GDB的x/i指令来获取去任意一个机器指令的反汇编指令,把源文件boot.S文件和boot.asm文件以及在GDB反汇编出来的指令进行比较。
  追踪到bootmain函数中,而且还要具体追踪到readsect()子函数里面。找出和readsect()c语言程序的每一条语句所对应的汇编指令,回到bootmain(),然后找出把内核文件从磁盘读取到内存的那个for循环所对应的汇编语句。找出当循环结束后会执行哪条语句,在那里设置断点,继续运行到断点,然后运行完所有的剩下的语句。
回答:
下面分析一下这道练习中所涉及到的两个重要文件,它们一起组成了boot loader。分别是/boot/boot.S和/boot/main.c文件。其中前者是一个汇编文件,后者是一个C语言文件。当BIOS运行完成之后,CPU的控制权就会转移到boot.S文件上。所以我们首先看一下boot.S文件。
  /boot/boot.S: 

.globl start
start:
.code16                # Assemble for 16-bit mode
cli                    # Disable interrupts

  这几条指令就是boot.S最开始的几句,其中cli是boot loader的第一条指令。这条指令用于把所有的中断都关闭。因为在BIOS运行期间有可能打开了中断。此时CPU工作在实模式下。

cld                         # String operations increment

  这条指令用于指定之后发生的串处理操作的指针移动方向。

# Set up the important data segment registers (DS, ES, SS).
xorw    %ax,%ax             # Segment number zero
movw    %ax,%ds             # -> Data Segment
movw    %ax,%es             # -> Extra Segment
movw    %ax,%ss             # -> Stack Segment

  这几条命令主要是在把3个段寄存器,ds,es,ss全部清零,因为经历了BIOS,操作系统不能保证这三个寄存器中存放的是什么数,这也是为后面进入保护模式做准备。

# Enable A20:
# For backwards compatibility with the earliest PCs, physical
# address line 20 is tied low, so that addresses higher than
# 1MB wrap around to zero by default.  This code undoes this.
seta20.1:
inb     $0x64,%al               # Wait for not busy
testb   $0x2,%al
jnz     seta20.1

movb    $0xd1,%al               # 0xd1 -> port 0x64
outb    %al,$0x64

seta20.2:
inb     $0x64,%al               # Wait for not busy
testb   $0x2,%al
jnz     seta20.2

movb    $0xdf,%al               # 0xdf -> port 0x60
outb    %al,$0x60

  这部分指令在准备把CPU的工作模式从实模式转换为保护模式。我们可以看到其中包括inb,outb这样的IO端口命令。所以这些指令都是在对外部设备进行操作。根据下面的链接:

   http://bochs.sourceforge.net/techspec/PORTS.LST

  我们可以查看到,0x64端口属于键盘控制器804x,名称是控制器读取状态寄存器。下面是它各个位的含义。
  这里写图片描述

  所以16~18号指令是在不断的检测bit1。bit1的值代表输入缓冲区是否满了,也就是说CPU传送给控制器的数据是否已经取走了,如果CPU想向控制器传送新数据的话,必须先保证这一位为0。所以这三条指令会一直等待这一位变为0,才能继续向后运行。
  当0x64端口准备好读入数据后,现在就可以写入数据了,所以19~20这两条指令是把0xd1这条数据写入到0x64端口中。当向0x64端口写入数据时,则代表向键盘控制器804x发送指令。这个指令将会被送给0x60端口。
这里写图片描述

  通过图中可见,D1指令代表下一次写入0x60端口的数据将被写入给804x控制器的输出端口。可以理解为下一个写入0x60端口的数据是一个控制指令。
  然后21~24号指令又开始再次等待,等待刚刚写入的指令D1,是否已经被读取了。
  如果指令被读取了,25~26号指令会向控制器输入新的指令0xdf。通过查询我们看到0xDF指令的含义如下
这里写图片描述

  这个指令的含义可以从图中看到,使能A20线,代表可以进入保护模式了。

# Switch from real to protected mode, using a bootstrap GDT
# and segment translation that makes virtual addresses 
# identical to their physical addresses, so that the 
# effective memory map does not change during the switch.
lgdt    gdtdesc
movl    %cr0, %eax
orl     $CR0_PE_ON, %eax
movl    %eax, %cr0

  首先31号指令 lgdt gdtdesc,是把gdtdesc这个标识符的值送入全局映射描述符表寄存器GDTR中。这个GDT表是处理器工作于保护模式下一个非常重要的表。这条指令的功能就是把关于GDT表的一些重要信息存放到CPU的GDTR寄存器中,其中包括GDT表的内存起始地址,以及GDT表的长度。这个寄存器由48位组成,其中低16位表示该表长度,高32位表该表在内存中的起始地址。所以gdtdesc是一个标识符,标识着一个内存地址。从这个内存地址开始之后的6个字节中存放着GDT表的长度和起始地址。我们可以在这个文件的末尾看到gdtdesc,如下:

# Bootstrap GDT
.p2align 2                               # force 4 byte alignment
gdt:
    SEG_NULL                               # null seg
    SEG(STA_X|STA_R, 0x0, 0xffffffff)      # code seg
    SEG(STA_W, 0x0, 0xffffffff)            # data seg

gdtdesc:
    .word   0x17                           # sizeof(gdt) - 1
    .long   gdt                            # address gdt

  其中第3行的gdt是一个标识符,标识从这里开始就是GDT表了。可见这个GDT表中包括三个表项(4,5,6行),分别代表三个段,null seg,code seg,data seg。由于xv6其实并没有使用分段机制,也就是说数据和代码都是写在一起的,所以数据段和代码段的起始地址都是0x0,大小都是0xffffffff=4GB。
  在第4~6行是调用SEG()子程序来构造GDT表项的。这个子函数定义在mmu.h中,形式如下:  

#define SEG(type,base,lim)                    \
                 .word (((lim) >> 12) & 0xffff), ((base) & 0xffff);    \
                 .byte (((base) >> 16) & 0xff), (0x90 | (type)),        \
                 (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)

  可见函数需要3个参数,一是type即这个段的访问权限,二是base,这个段的起始地址,三是lim,即这个段的大小界限。gdt表中的每一个表项的结构如图所示:
这里写图片描述
 
   每个表项一共8字节,其中limit_low就是limit的低16位。base_low就是base的低16位,依次类推。
   然后在gdtdesc处就要存放这个GDT表的信息了,其中0x17是这个表的大小-1 = 0x17 = 23,紧接着就是这个表的起始地址gdt。

# Switch from real to protected mode, using a bootstrap GDT
# and segment translation that makes virtual addresses 
# identical to their physical addresses, so that the 
# effective memory map does not change during the switch.
lgdt    gdtdesc
movl    %cr0, %eax
orl     $CR0_PE_ON, %eax
movl    %eax, %cr0

  当加载完GDT表的信息到GDTR寄存器之后。紧跟着3个操作,32~34指令。 这几步操作是在修改CR0寄存器的内容。CR0寄存器还有CR1~CR3寄存器都是80x86的控制寄存器。其中$CR0_PE的值定义于”mmu.h”文件中,为0x00000001。可见上面的操作是把CR0寄存器的bit0置1,CR0寄存器的bit0是保护模式启动位,把这一位置1代表保护模式启动。

ljmp    $PROT_MODE_CSEG, $protcseg

  这只是一个简单的跳转指令,这条指令的目的在于把当前的运行模式切换成32位地址模式。

protcseg:
# Set up the protected-mode data segment registers
movw    $PROT_MODE_DSEG, %ax    # Our data segment selector
movw    %ax, %ds                # -> DS: Data Segment
movw    %ax, %es                # -> ES: Extra Segment
movw    %ax, %fs                # -> FS
movw    %ax, %gs                # -> GS
movw    %ax, %ss                # -> SS: Stack Segment

   修改这些寄存器的值,这些寄存器都是段寄存器。这里的23~29步之所以这么做是按照规定来的,如果刚刚加载完GDTR寄存器我们必须要重新加载所有的段寄存器的值,而其中CS段寄存器必须通过长跳转指令,即23号指令来进行加载。所以这些步骤是在第19步完成后必须要做的。这样才能是GDTR的值生效。

#Set up the stack pointer and call into C.
movl    $start, %esp
call bootmain

  接下来的指令就是要设置当前的esp寄存器的值,然后准备正式跳转到main.c文件中的bootmain函数处。我们接下来分析一下这个函数的每一条指令:

// read 1st page off disk
readseg((uint32_t) ELFHDR, SECTSIZE*8, 0);

  这里面调用了一个函数readseg,这个函数在bootmain之后被定义了:

void readseg(uchar *pa, uint count, uint offset);

  它的功能从注释上来理解是,把距离内核起始地址offset个偏移量存储单元作为起始,将它和它之后的count字节的数据读出送入以pa为起始地址的内存物理地址处。

  所以这条指令是把内核的第一个页(4MB = 4096 = SECTSIZE*8 = 512*8)的内容读取的内存地址ELFHDR(0x10000)处。其实完成这些后相当于把操作系统映像文件的elf头部读取出来放入内存中。

  读取完这个内核的elf头部信息后,需要对这个elf头部信息进行验证,并且也需要通过它获取一些重要信息。所以有必要了解下elf头部。

  注: http://wiki.osdev.org/ELF

elf文件:elf是一种文件格式,主要被用来把程序存放到磁盘上。是在程序被编译和链接后被创建出来的。一个elf文件包括多个段。对于一个可执行程序,通常包含存放代码的文本段(text section),存放全局变量的data段,存放字符串常量的rodata段。elf文件的头部就是用来描述这个elf文件如何在存储器中存储。
需要注意的是,你的文件是可链接文件还是可执行文件,会有不同的elf头部格式。
if (ELFHDR->e_magic != ELF_MAGIC)
       goto bad;

  elf头部信息的magic字段是整个头部信息的开端。并且如果这个文件是格式是ELF格式的话,文件的elf->magic域应该是ELF_MAGIC的,所以这条语句就是判断这个输入文件是否是合法的elf可执行文件。

ph = (struct Proghdr *) ((uint8_t *) ELFHDR + ELFHDR->e_phoff);

  我们知道头部中一定包含Program Header Table。这个表格存放着程序中所有段的信息。通过这个表我们才能找到要执行的代码段,数据段等等。所以我们要先获得这个表。
  这条指令就可以完成这一点,首先elf是表头起址,而phoff字段代表Program Header Table距离表头的偏移量。所以ph可以被指定为Program Header Table表头。

eph = ph + ELFHDR->e_phnum;

  由于phnum中存放的是Program Header Table表中表项的个数,即段的个数。所以这步操作是吧eph指向该表末尾。

for (; ph < eph; ph++)
    // p_pa is the load address of this segment (as well
    // as the physical address)
    readseg(ph->p_pa, ph->p_memsz, ph->p_offset);

  这个for循环就是在加载所有段到内存中。ph->paddr根据参考文献中的说法指的是这个段在内存中的物理地址。ph->off字段指的是这段的开头相对于这个elf文件的开头的偏移量。ph->filesz字段指的是这个段在elf文件中的大小。ph->memsz则指的是这个段被实际装入内存后的大小。通常来说memsz一定大于等于filesz,因为段在文件中时许多未定义的变量并没有分配空间给它们。
  所以这个循环就是在把操作系统内核的各个段从外存读入内存中。

((void (*)(void)) (ELFHDR->e_entry))();

  下面回答一下文中提出的四个问题:
 1. 在什么时候处理器开始运行于32bit模式?到底是什么把CPU从16位切换为32位工作模式?
 答:在boot.S文件中,计算机首先工作于实模式,此时是16bit工作模式。当运行完 ” ljmp $PROT_MODE_CSEG, $protcseg ” 语句后,正式进入32位工作模式。根本原因是此时CPU工作在保护模式下。

 2. boot loader中执行的最后一条语句是什么?内核被加载到内存后执行的第一条语句又是什么?
 答:boot loader执行的最后一条语句是bootmain子程序中的最后一条语句 ” ((void (*)(void)) (ELFHDR->e_entry))(); “,即跳转到操作系统内核程序的起始指令处。
   这个第一条指令位于/kern/entry.S文件中,第一句 movw $0x1234, 0x472
 
 3. 内核的第一条指令在哪里?
 答:第一条指令位于/kern/entry.S文件中。

 4. boot loader是如何知道它要读取多少个扇区才能把整个内核都送入内存的呢?在哪里找到这些信息?
 答:首先关于操作系统一共有多少个段,每个段又有多少个扇区的信息位于操作系统文件中的Program Header Table中。这个表中的每个表项分别对应操作系统的一个段。并且每个表项的内容包括这个段的大小,段起始地址偏移等等信息。所以如果我们能够找到这个表,那么就能够通过表项所提供的信息来确定内核占用多少个扇区。
   那么关于这个表存放在哪里的信息,则是存放在操作系统内核映像文件的ELF头部信息中。

6.828 lab1 0.LAB1介绍 实验3个部分: 1.熟悉x86汇编语言,QEMU模拟器,bootstrap过程 2.测试os(jos)内核的bootloader(在lab中boot文件夹下) 3.探究最初的jos 1.LAB1软件准备 0.使用git管理实验资源Git手册 中文版 1.下载 jos包与工具链 git clone https://pdos.csail.mit.edu/6.828/2018/jos.git lab #安装编译工具链 sudo apt-get install -y gcc-m 阅读详情

相关推荐

mit 6.828(清华北大操作系统实习课使用)

完成了6个lab必做的execise部分,希望能为大家提供点帮助~

linux-keyboard.S

/* *  linux/kernel/keyboard.S *                                    #--键盘驱动汇编程序,主要是键盘中断处理程序 *  (C) 1991  Linus Torvalds *//* *    Thanks to Alfred Leung for US keyboard patches *        W

四菜一汤 2093

MIT6.828-2016-中文:MIT 6.828(操作系统)的中文版本

介绍 这是MIT6.828的个人学习笔记,纳入非计算机专业出身,可能会有太多纰漏,烦请大神斧正。个人认为,操作系统是计算机专业课之中综合性很强的一门课,牵涉面广,知识点多,相对也非常难学。 大名鼎鼎的6.828的最大的特点就是基于实践。自己写一个操作系统,把坑都踩过一遍,自然就明白了。 进度 实验1:C,汇编,工具和引导程序 实验2:内存管理 实验3:用户级环境 实验4:抢先式多任务处理 实验5:文件系统,生成和sh

MIT操作系统神课 - 6.828

MIT操作系统神课 - 6.828 想系统学习操作系统的朋友们一定听说过MIT 6.828,这个项目是 MIT大学开源的一个操作系统课程,该课程由浅入深,以理论与实践结合的方式讲解了操作系统的原理以及通过实验循序渐进的方式实现了一个简单的xv6内核。从2020年开始,6.828这门课被拆分为了6.828和6.S081两个独立的课程,6.S081作为本科生的操作系统导论课, 而6.828作为研究生水平的课程专注于对操作系统更深入的研究。 所以本系列博客将以6.S081: Operating System

weixin_41792731的博客 9931

MIT-6.828-OS-Engineering:MIT 6.828操作系统工程2018年秋季课程

MIT 6.828 OS工程 我正在在线参加MIT 6.828操作系统工程课程。 该存储库包含讲义,实验室源代码和学习资源。 课程时间表 讲课 实验室 工具指南 家庭作业 阅读资料

【学习体会】Lighttools8.4.0:软件基本使用+光度学基本概念+系统初始设置

关于Lighttools8.4.0软件的安装教程,详见我的另一篇博文:【软件安装】win10下Lighttools8.4.0(64)光学系统建模软件的安装教程 在本文中,我们将学习到,光度学的基本概念、系统初始设置、物体模型坐标的使用方法、简单光学系统实例、系统浏览器的作用和内容、设置虚拟相机并渲染视图中的图像、仿真结果3D显示等。 如果有其他感兴趣的内容但是我又没有写的,欢迎在评论区留言! 光度学的基本概念 软件的基本介绍 参考博文:https://www.docin.c...

LeonJin的博客 2万+

【6.828学习笔记】MIT6.828总结与归纳

MIT6.828复习归纳总结

Rcary的博客 4398

一体化伺服电机与施耐德PLC TM241CEC24T在Canopen协议下的应用

一.硬件组成 软件组成:施耐德SoMachineV4.3二.○1.打开SoMachineV4.3,点击“新建项目”○2.点击“空白项目”○3.项目命名○4.点击“创建项目” 三. 点击“Logic Builder” 四. ○1.右击项目”PMM_CANOPEN_ST”添加设备○2.点击”LogicController”选择PLC型号TM241CEC24T/U○3.点击“添加设备” 五. ○1.右击CAN_1,添加设备○2.选择“CANopen Perfomance”○3.点击“添加设备”

m0_46512607的博客 2520

MIT6.828实验记录-Lab1

MIT6.828-Lab1实验记录

小开心的博客 1297

【军标】《军用软件计价规范(试行)》和GJB 10162-2021《军用软件计价功能项识别方法》-费用标准解读系列37

2021年2月1日实施的《军用软件计价规范(试行)》(替代了2019年版本)以及2021年3月1日实施的《军用软件计价功能项识别方法》(GJB 10162-2021),是我们平时在军用软件造价咨询中进行软件规模度量、计价和审价的主要依据。《军用软件计价规范(试行)》(4号文)的附件1为《军用软件功能规模度量方法》,即4号文本身包含对软件规模测试的方法(功能点方法主要参考NESMA等国际标准)、规模度量过程、功能点计数和计算规则等相关说明。(四)软件研发费用=软件研发工作量x软件研发人月综合费率。

xiaosenyouli的博客 6121

tewa-707e光猫超级密码获取方法

这款光猫很魔性,没有WIFI,没有USB接口,没有Telnet,试了很多方法去获取超级密码都不行。解密时可能会报错,可能是文件后面部分不晓得是咋拼接过来的,用AES解密时分组数据有问题。3、这个文件是用AES加密了的,直接打开是乱码,所以得用AES解密,key为16个字节的 x00。打开解出来的文件,然后搜索 telecomadmin,就可以发现超级密码了。参考资料里面的光猫不是同一款,但解密的方法基本相同的。

shaowl111的专栏 1万+

MIT6.828 Lab3

MIT6.828 Lab3

qq_41421755的博客 595

FOC观测器之龙伯格观测器

状态观测器: 理论依据:根据控制理论,如果一个系统能够完全通过其检测到的输出值来重构其系统状态,则认为该系统是可观测的。其作用于无传感器转子的位置和速度的检测反馈,再作用到PARK逆变换和转矩磁链控制上。 Luenberger观察器原理图: Luenberger观测器的离散化: (其观测器的闭环参数为经验验证值) 引入估测电流( iα,iβ )的反馈值并离散化(T 为采样时间),可得...

ShawnChan的博客 2万+

LAB_1_Part2_The Boot Loader

1. LEC1_LAB_1_Booting a PC 1.1. Part 2: The Boot Loader 对于6.828,我们将使用传统的硬盘启动机制,这意味着我们的boot loader必须满足于512字节。 boot loader由一个汇编语言源文件boot / boot.S和一个C源文件boot / main.c组成。 1.1.1. boot.S BIOS将boot.S这段代码从硬盘的...

Small_Pond的博客 2810

用AList挂载网盘,无损看VR电影教程,无需下载到PICO头显本地!

用AList挂载网盘 + WebDAV直连头显,看片像拉本地一样流畅,不怕卡顿、不怕没空间,简直是VR看片刚需配置!别再用U盘传电影了,用AList + WebDAV,直接流畅看4K,看片效率翻倍,体验提升一个档次!

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 5544

2026.3.9:具身智能之GraspNet:Ubuntu24.04安装GraspNet

本文详细介绍了在Ubuntu24.04系统下安装GraspNet具身智能框架的全过程。主要包括:1) 创建Python3.9虚拟环境;2) 安装CUDA12.8和PyTorch2.7.0等基础依赖;3) 编译安装pointnet2、knn和graspnetAPI三个核心组件;4) 修改源码适配新版PyTorch;5) 下载预训练权重并成功运行demo。安装过程中特别提示了可能遇到的报错处理方案,最终在GPU环境下实现了GraspNet的部署运行。整个流程涵盖了从环境配置到项目运行的完整步骤,为具身智能研究者

拥抱具身智能,昇腾Ascend C 203

mit6.828 Lab1

Part 1 熟悉x86汇编语言 参考资料:https://pdos.csail.mit.edu/6.828/2018/readings/pcasm-book.pdf 这本书中介绍的是使用nasm汇编器所支持的汇编(Intel Syntax),但在这个lab中实际使用的是GNU汇编器(AT&T Syntax) http://www.delorie.com/djgpp/doc/brenn...

tailuzhecom的博客 1026

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

《MIT 6.828 Lab1: Booting a PC》实验报告

《MIT 6.828 Lab1: Booting a PC》实验报告 本实验的网站链接见:Lab 1: Booting a PC。 实验内容 熟悉x86汇编语言、QEMU x86仿真器、PC开机引导流程 测试6.828 内核的启动加载器(boot loader) 研究6.828 内核的初始化模板(JOS) 实验题目 注意:部分Exercise的解答过程较长,因此专门新建一个文档来记录...

575

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

MIT6.828 LAB1 PART2.2 The Boot loader

加载内核 ELF文件由三大部分组成:一个带有加载信息的文件头,程序段表和程序段。每一个程序段是一块连续的代码或数据。bootloader的工作是把程序段加载到内存中。程序段表中列出了要加载到内存中的所有段。 通过命令 objdump -h obj/kern/kernel 考察JOS内核中所有段的名字大小和地址,如下所示。VMA字段是链接地址,指的是这个段希望被存放到的逻辑地址。LMA字段是加载地址,表示的是这个段被加载到内存后的物理地址。 Sections: Idx Name Si

qq_43012789的博客 345

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

MIT 6.828 Lab1:x86操作系统内核开发实践指南

操作系统内核是计算机系统的核心组件,负责管理硬件资源和提供基础服务。x86架构作为主流计算平台,其启动过程涉及BIOS初始化、引导加载程序和内核加载等关键阶段。通过MIT 6.828 Lab1实验,开发者可以深入理解操作系统底层原理,实践内容包括内存管理、保护模式切换和硬件初始化等核心机制。该实验使用QEMU模拟器和GCC工具链,特别适合学习操作系统开发和系统编程。在工程实践中,掌握GDB调试技术和理解物理内存布局对系统稳定性至关重要,这些技能也是Linux内核开发的基础。

weixin_33845881的博客 482

MIT6.828 LAB1 PART2.1The Boot Loader

实验内容 PC机的软盘和硬盘被划分为固定的512字节的扇区(sector)。扇区是磁盘的最小传输粒度:每个读或写操作的大小必须是一个或多个扇区。第一个扇区称为the boot sector引导扇区,从引导扇区加载操作系统。当BIOS找到可以启动的软盘或硬盘之后,这个512个字节的启动扇区就会被加载到内存,地址为0x7c00~0x7dff区域。 bootloader程序的大小必须是小于512个字节的。bootloader由一个汇编文件boot/boot.S以及一个C语言文件bo...

qq_43012789的博客 379

MIT 6.828 Lab1:x86操作系统启动流程与内核开发实践

操作系统内核开发是计算机系统领域的核心技能,x86架构的启动流程从BIOS阶段到内核加载涉及实模式与保护模式切换等关键技术。通过QEMU模拟器和GDB调试工具,开发者可以深入理解计算机从通电到执行内核代码的完整过程。MIT 6.828课程的Lab1实验正是围绕这些基础概念设计,重点解析引导加载程序实现、内存布局管理以及VGA文本模式控制等底层机制。这些技术不仅对操作系统开发至关重要,也为理解计算机体系结构、系统编程等提供了实践基础。实验中使用QEMU调试和栈回溯分析等技巧,展示了系统级软件开发与调试的典型方

weixin_30800807的博客 399

Xv6 Lab1手记

环境: Ubuntu_LTS18.04 _64位 课程:https://pdos.csail.mit.edu/6.828/2018/schedule.html (2018年秋季) 我跟着官方文件来的,和网上一些其他的开源教程可能有所区别。 Lab 1: Booting a PC Part 1: PC Bootstrap $ git clone http...

w55100的博客 3300

MIT 6.828 JOS学习笔记7. Lab 1 Part 2.2: The Boot Loader

Lab 1 Part 2 The Boot Loader Loading the Kernel 我们现在可以进一步的讨论一下boot loader中的C语言的部分,即boot/main.c。但是在我们分析之前,我们应该先回顾一些关于C语言的基础知识。 Exercise 4:   阅读关于C语言的指针部分的知识。最好的参考书自然是"The C Programming Language"...

weixin_30569033的博客 153

MIT6.828 32位操作系统笔记(5)----GDB调试与qemu monitor

利用qemu 和 gdb 探索PC机 的启动过程。 1、GDB Debug With GDB ctrl + C,终止运行 c , 继续运行 si (or stepi), 执行一条机器指令 b function or b file:line or b *addr 设置断点 info break 查看断点的信息 delete 断点号 ,删除第n 个断点 n 单步执行,不进入函数 step ...

YoungSusie的博客 1470
上一篇: MIT6.828 HW1: boot xv6
下一篇: MIT6.828 Lab2:第1部分 Physical Page Management
bysui
博客等级 码龄14年 199粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值