Linux 操作系统内核代码(一)

boot.s与head.s

BIOS

开机以后首先执行BIOS,BIOS完成了一下三个任务:

  1. 自检:检查硬件
  2. 把引导盘第一个扇区(512B)加载到内存0x7c00处
  3. 加载中断描述符表到0x00处

boot.s

Overview

boot.s

boot.s共512字节,以0xAA55结尾,是由BIOS加载进内存的,完成了以下4项工作;(注:此时系统处于实模式

load

  • 0x7c00处的跳转语句:硬件的跳转与软件不同,这里的jump是一个隐式赋值语句,其中cs被赋值为0x7c0,ip被赋值为5;
  • 下面一些列就是初始化各个寄存器。

load head.s

在这里插入图片描述

  • int 0x13:这是个中断,通过0x13中断将head.s从启动盘软驱加载到内存0x10000处。
  • 0x13=19所以在中断描述符表中的第19个描述符开始(每个中断描述符4B)——每行4个描述符,第19个在第5行,由于描述符是从第0个开始算,所以0x13中断指的是第5行最后一个中断FE E3 00 F0
  • 大端存储:所以CS=F0 00, IP=E3 FE;
  • 指令地址=CS<<4 + IP——执行完int 0x13后执行的指令(中断处理程序)地址为000fe3fe(注:二进制左移4位即16进制左移1位
  • 计算:F000<<4=F0000;F0000+E3FE=0xFE3FE;
  • 如何从中断处理程序回到int 0x13下条指令?——执行0x13事将下一条指令IP压入栈中,栈地址为SS:SP即SS<<4+SP
  • 下图中可以看到压栈前sp=0x400;ss=0x7c0,所以栈顶为7c00+400=0x800;

在这里插入图片描述

  • 下图可以看出压栈后栈顶为7c00+3fa=0x7ffa;
    在这里插入图片描述

  • 栈中依次被压入了:EFLAGS;CS;IP
    在这里插入图片描述

  • 当想从中断处理程序返回时就可以弹出栈顶内容获得下条指令的地址;

mov head.s

在这里插入图片描述

  • 由于0x00处有中断描述符表,所以head.s没有直接加载到0x00处。

prepare for the protected mode

由于boot.s只有512B所以这里只进行简单的初始化,复杂初始化留给head.s。

  • lidt(load IDT)将ds:0x0069处的内容填入IDT(此时ds=0x7c0,所以实际上是将地址0x7c69处的内容填入IDT)
    在这里插入图片描述
  • lgdt(load GDT)同理,0x7c6f处代码为:
    在这里插入图片描述
  • 代码中的gdt地址处的代码:
    在这里插入图片描述
    根据GDT格式:
    在这里插入图片描述
    填入后为:
    在这里插入图片描述
  • 设置CR0寄存器,最后一位表示保护模式和实模式。
    在这里插入图片描述
  • boot.s load head.s to the 0x0 in the memory and then initialize gdt, change the CR0, when jumpi , the hardware scans the CR0 and know it’s in protected mode then cs=8, ip = 0;
  • 实模式cs16位,而保护模式32位,因此保护模式下CS用法与实模式不同。
  • Segment Selector
Index (13b)TL(1b)RPL(2b)

将0x8填入其中可知Index = 1;CS作为索引查GDT表。

  • 其中的RPL代表特权模式,00为内核模式,11为用户模式。
  • jumpi即完成了赋值又跳转到head.s第一条指令了。

head.s

初始化寄存器

在这里插入图片描述

  • 初始化DS,由于现在是执行0x0处的代码段,数据段也从原来的0x7c0处更改为现在的0x0,即GDT中的0x2处。
  • lss是load SS
  • init_stack:
    在这里插入图片描述
  • init_stack上一句是指往内存中写128次4B的0,即0.5k个0用于预留的栈空间。

初始化IDT、GDT

初始化IDT
  • 代码1:
    在这里插入图片描述

  • 这里的lea(load effective address)语句是为edx赋值

  • ignore_int——ds:0x114,其中ds=0x10,查过GDT表后得到edx=0x0+0x114=0x114

  • eax=0x80000;ax = 0x0000

  • dx=0x114,所以movw dx ax后,eax=0x80114

  • 接下来给dx赋值后,edx=0x8E00

  • idt——ds:0x198,所以edi=0x0+0x198=0x198

  • ecx=256

  • 代码2:
    在这里插入图片描述

  • (edi)是IDT表地址,经过上边的赋值后eax可以被填入IDT表(由于这个表的形式,所以不得不折腾一下寄存器才能填入)

  • edx是(edi)即IDT表基地址的高4B位置,edi+8及偏移8B准备填写下8B

  • 一共填256次知道ecx为0

  • lidt 是把lidt_opcode填入IDT表:
    在这里插入图片描述

  • 256项,每项8字节,由于从0开始算所以减1

  • idt处填了2k个0;

欢迎大家交流和指正,后续继续完善!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ape:hello code world

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值