内核引导启动程序.ppt_第1页
内核引导启动程序.ppt_第2页
内核引导启动程序.ppt_第3页
内核引导启动程序.ppt_第4页
内核引导启动程序.ppt_第5页
已阅读5页,还剩85页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Linux操作系统内核分析,湘潭大学信息工程学院,讲课内容,bootsect.s程序分析 setup.s程序分析 head.s程序分析 要求大家知道每个程序的作用!,操作系统引导,应用程序,操作系统,引导程序,BIOS,装载,装载,装载,?,?,磁盘结构,磁道:不同半径的同心圆称为磁道,扇区:512B,磁头:每个磁盘有两个面,每个面都有一个磁头,使用磁头号、柱面号、扇区号可唯一确定一个扇区,引导扇区,引导扇区是磁盘的第一个扇区(0磁头0磁道1扇区)。 引导扇区中的程序是负责装载操作系统的程序,被成为自举程序或引导程序(bootstrap)。 限制:自举程序的大小为512B,且最后两个字节必须为

2、0 xaa55。,开机过程,开机 BIOS完成加电自检 将引导盘的引导扇区读入到物理内存0 x7c00处 检查0 x7c00+510开始的两个字节是否是0 xaa55 跳到0 x7c00执行,P36,实模式内存寻址,+,物理地址,逻辑地址,基地址,64K,1M,段地址:段内偏移,bootsect程序,bootsect程序就是一个引导程序,负责把Linux操作系统内核从存储设备装入内存。 用汇编语言编写,遵循Intel汇编语法,装载过程,0 x000000,0 x007c00,0 x010000,0 x090000,0 x090200,0 x100000,setup,bootsect,syste

3、m,移动自己,movw指令: 从ds:si移动一个字到es:di,然后根据标志寄存器中direct标志位,把si和di分别加2(d=0)或减2(d=1)。 rep:重复执行后面的命令,重复次数放在cx寄存器中,每执行一次后面的命令则把cx中的值减1,直到cx为0。,移动自己,ds=0 x7c0; si=0; /0 x7c0:0 es=0 x9000;di=0; /0 x9000:0 cx=256; While(cx0) 从ds:si移动一个字到es:di; if( d=0 ) si+=2; di+=2; else si-=2; di-=2; cx-; ,移动自己,0 x7c0,0 x9000,

4、go,go,Jumpi go,initseg,装载中断,0 x13中断,2号功能 类似于函数:int load(驱动器号,磁头号,磁道号,扇区号,要读扇区数量,读入内存地址),P39第67,装载setup,驱动器号:软盘 磁头号:0磁头 磁道号:0磁道 开始扇区号:2(?) 要读扇区数量:4 读入内存地址:0:0 x90200,装载System,限制 13中断一次只能读同一磁道上的扇区 实模式下内存段大小不能超过64K 解决方法 一次读一个扇区 读完后 检测磁道是否读完,是则调整到下一个磁道; 检测内存段是否满了,是则调整到下一个内存段。,装载System,未读入,已读入,Min(未读入扇区字

5、节大小,内存段空余字节大小),装载System,磁盘读取规则:当0磁头的某个磁道读完,下一次就读1磁头的相同磁道;当1磁头的某个磁道读完,下一次就读0磁头的下一个磁道。例如:0磁头0磁道,1磁头0磁道,0磁头1磁道,1磁头的1磁道。,装载system,1、if( 已读大小=64K ) then 段地址+=64K;已读大小=0; 2、可读入的扇区数量=(64k-已读大小)/512B; 3、if(可读入的扇区数量+当前扇区号=磁道扇区总量) then 可读入的扇区数量=磁道扇区总量-当前扇区号; 4、读入 5、if(磁道上无剩余扇区) then if(磁头号为0) then 磁头号=1;扇区号=1

6、; else 磁头号=0;磁道号+;扇区号=1;,跳入setup,139行 jmpi 0,SETUPSEG,在37行定义为0 x9020,虚拟地址:0 x9020:0 物理地址:0 x90200,setup的开始地址,讲课内容,bootsect.s程序分析 setup.s程序分析 head.s程序分析,程序功能,1-106行:获取并保存系统参数 113-126行:移动system 130-193行:进入保护模式,获得并保存系统参数,通过BIOS中断调用获得系统参数 把获得的系统参数保存在0 x90000开始的内存块中,还记得0 x90000地址上的内容吗?,程序举例,38行读光标位置: 0 x

7、10中断0 x03功能: 输入参数: ah:0 x03 bh:页号 输出参数: dh:行号 dl:列号,mov ax,0 x9000 mov ds,ax mov ah,0 x03 xor bh,bh int 0 x10 mov 0,dx,ds:,程序举例,获得内存大小: 0 x15中断0 x88功能: 输入参数: ah:0 x88 输出参数: ax:扩展内存大小,单位KB,movah,#0 x88 int0 x15 mov2,ax,系统参数保存布局,程序功能,1-106行:获取并保存系统参数 113-126行:移动system 130-193行:进入保护模式,移动system,把System从

8、0 x10000(64K)移到0 x00000 为什么一开始不把system装载到物理内存0 x00000处? 在bootsect和setup前一段程序中用到了实模式下的中断调用,而这些中断的处理函数地址(中断向量表)调用被安排在物理内存0 x00000开始的内存中,移动system,0,0中断处理函数的地址,1中断处理函数的地址,4,中断向量表,移动system,0 x0000:0,0 x1000:0,0 x2000:0,0 x3000:0,0 x4000:0,0 x5000:0,0 x6000:0,0 x7000:0,0 x8000:0,0 x9000:0,es:di,ds:si,程序功能

9、,1-106行:获取并保存系统参数 113-126行:移动system 130-193行:进入保护模式,保护模式寻址,寻址就是逻辑地址到物理地址的转换。 在保护模式下有两种内存管理机制:分段和分页,其中分页是可选的。 三种不同地址 逻辑地址:包含在机器语言指令中的地址,由一个段:段内偏移组成。 线性地址:逻辑地址到物理地址变换间的中间层。 物理地址:内存单元的地址。,P16第2.5节,保护模式寻址,分段,分页,分段,分段段描述符,保护模式下把内存分为多个段,每个段用一个描述符(数据结构)用来描述它的属性,包括段的开始地址、段长度、类型、访问权限等。 段描述符由8个字节组成。,段描述符的结构,B

10、ASE 字段:指向段的基地址 粒度标志G:段大小的单位。G=0时以字节为单位,否则以4096B为单位。 LIMIT字段:段的大小,段的长度=段大小*1(G=0)或 段大小*4k(G=1) 系统标志S:系统段(S=0),用于存储内核数据;否则是普通代码段或数据段 TYPE字段:描述段的类型 DPL字段:描述符特权级别,表示为访问这个段而要求的CPU最小特权级。 Present字段:段不在内存中(S=0),否则段在内存中。Linux总是把此标志设为1,因为Linux从来不把段交换到磁盘上去。 D或B字段:段偏移量的地址是32位(D=1),否则是16位。 AVL字段:Linux不使用 保留字段,总是

11、为0,BASE(0-15),LIMIT(0-15),BASE(16-23),TYPE,S,DPL,1,BASE(24-31),LIMIT (16-19),AVL,0,B/D,G,描述符表,保存有多个段描述符的内存块(数组)叫做描述符表,分为全局描述符表(Global Descriptor Table,GDT)和局部描述符表(Local Descriptor Table,LDT) GDT中定义的内存段可以被所有进程使用,通常只定义一个; LDT中定义的内存段只被进程自己使用,通常每个进程一个LDT。 GDT在内存中的地址存放在寄存器gdtr中,而当前进程使用的LDT的地址存放在寄存器ldtr中,

12、段选择子,实模式中,段寄存器保存的是段的基地址 保护模式中,段寄存器内容的含义发生了改变,它不再指向一个物理段的基地址了,而是一个段描述符的索引,通常把它称为段选择子 13位索引,指定了放在GDT或LDT中的相应段描述符 TI指定了描述符是放在GDT(TI=0)中还是在LDT中(TI=1) 两位RPL(Requestor Privilege Level)指定了进程的特权级别,RPL=DPL才能访问成功,Index,TI,RPL,0,2,3,1,15,分段的实现,给定一个逻辑地址 检查段选择子中的TI标志,决定段描述符是保存在哪个描述符表中,并到相应的寄存器中取得描述符表的基地址 把索引字段的值

13、乘以8(段描述符的大小),加上描述符表的基地址,从而得到段描述符 用段描述符中段的基地址加上逻辑地址中的偏移量,得到了线性地址,GDTR/LDTR,*,+,段描述符,+,线性地址,特权级别,IA32提供了03四个特权级别,数字越小,级别越高 高特权级可以访问低特权级和同一特权级,而低特权级不能随便访问高特权级,否则产生常规保护错误(GP) Linux只使用了其中的两个级别,即0级别,对应内核态;3级别,对应用户态,特权级别,Index,TI,RPL,0,2,3,1,15,BASE(0-15),LIMIT(0-15),BASE(16-23),TYPE,S,DPL,1,BASE(24-31),LI

14、MIT (16-19),AVL,0,B/D,G,只有段选择子的RPL=段描述符中的DPL才允许访问该描述符所代表的内存段,一般只考虑CS选择子的RPL,要做的事,段机制由CPU自动实现,我们要做的事包括: 定义好描述符表 把描述符表的基地址装入gdtr或ldtr 使用正确的段选择子,gdt的定义,205行 gdt: .word0,0,0,0 .word0 x07FF/ 8M .word0 x0000/基地址为0 .word0 x9A00/可读可执行的代码段,dpl=0 .word0 x00C0/粒度=4K .word0 x07FF / 8M .word0 x0000 /基地址为0 .word0

15、 x9200 /可读写的数据段,dpl=0 .word0 x00C0 /粒度=4K,gdt的定义,BASE(0-15),LIMIT(0-15),BASE(16-23),TYPE,S,DPL,1,BASE(24-31),LIMIT (16-19),AVL,0,B/D,G,0000000000000000,0000011111111111,00000000,1010,1001,00000000,0000,1100,低字节,高字节,0 x0000,0 x07FF,0 x00C0,0 x9A00,装载gdtr,GDTR寄存器包括两部分:32位的物理地址,以及16位GDT大小(以字节为单位) 设置好GD

16、T之后,我们需要通过LGDT指令将设定的gdt的入口地址和gdt表的大小装入GDTR寄存器。 可以使用LGDT指令来设置GDT。 lgdt addr(保存gdt基地址和大小的地址),装载gdtr,134行:lgdt gdt_48 222行:gdt_48: .word0 x800 /gdt长度2kb,256项 .word512+gdt,0 x9 /gdt的基地址,setup,进入保护模式,控制寄存器CR0 PE:允许保护模式,PE=1切换到保护模式,PE,进入保护模式,191行 movax,#0 x0001 lmsw ax /把ax的值装载到cr0中,执行完setup后的内存映像,跳到head中执行,jmpi 0,8,1,0,00,基地址为0,长度为8M,gpl为0的代码段,基地址为0,长度为8M,gpl为0的数据段,index,ti,rpl,段选择子0 x10指的是GDT中的数据段 段选择子0 x08指的是GDT中的代码段,讲课内容,boot

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论