笔记来自哈工大李志军老师课程,另补充了源码

1、通电时x86pc的cpu处于实模式,

2、CS = 0xFFFF  IP = 0000

3、寻址0xFFFF0 (这是属于bios中的一块内存空间)

4、检查RAM、键盘、显示器、软硬磁盘

5、将磁盘0道0扇区读入0x7c00处,(512Byte,OS引导)(MBR :最多446字节的启动代码、4个硬盘分区表项(每个表项16字节,共64字节)、2个签名字节(0x55,0xAA))

6、设置CS=07c0H,  IP=0x0000,

在linux0.11中MBR启动指令是文件bootsect.s(as86汇编)

    bootsect.s中的常量   

ospf cost值和metric值 ospf cost 1_IP

 

 

 

 

    其中第一个扇区加载到07c00H处后,就立即被移动到了90000H,源码中移动了512个字节,刚好将第一个扇区完全移动走

       jmpi  go INITSEG    (go(代表程序起始的位置到go这个指令所在的位置) 对应IP  INITSEG(初始直接赋值为9000H)对应CS)  这句话保证程序移动后依然可以正常按顺序执行 

7、......经过一些指令后  int 13  (执行13号中断程序)  (前面一段指令就是为13号中断程序做准备)

    13号中断  是读磁盘扇区的中断,ah =0x02 代表读磁盘  al为扇区数量(为4),ch柱面号(为2,因为boot在第一个扇区) ,cl 开始位置 ,

    dh 磁头号00 dl驱动号00  es:bx 内存地址(因为要紧挨着bootsect,因此这里应被之前置为90200H),

8、打印出屏幕开机提示,loading system。。。此时就在屏幕显示这句话时,cpu将os读到内存中(10000H),  

9、jmpi 0 SETUPSEG(IP:0     CS:9020H) (跳转到setup.s程序中执行)

此时操作系统在10000H处

setup.s

ospf cost值和metric值 ospf cost 1_IP_02

1、...执行几句指令后(这些指令将所有段寄存器,都置为9000),通过#0x888 为参数 int 0x15 中断程序 获取内存的大小 获取的值放入ax中 ,

  然后将ax 赋值到  [2] (间接寻址,前面默认加上段寄存器,就是这里的地址) 0x90002 这里存放着扩展内存大小  (最初只有1M内存(x86,24根地址线),1M 以后的内存就叫做扩展内存)

 

    1、取出光标的 位置,包括 其他参数到0x90000处

 2、int0x15中断 ,获取内存的大小放入到0x90002位置处 ,(最初x86机器内存大小1M(20位地址线),多余的就叫做扩展内存)

 3、执行do_move将操作系统移动到由0开始的内存空间中  (linux 0.11,中将10000H  移动到00000H,移动了 0x8000次),

  之前将bootsect 从0x 07c00处移动走也是因为要为这里移动操作系统留下空间

 

ospf cost值和metric值 ospf cost 1_保护模式_03

 

  ds si   es  di   (一般movw,movsw(移动一个字) 的源地址和目的地址) 

并且不修改任何操作数:CMP destination,source ,所以在linux中cmp ax  #0x9000  后ax 还是 1000

 4、setup 引导cpu进入保护模式,(具体指令是在setup.s最后 mov ax , #0x0001   mov   cro  ax   jmpi   0  8  (这是第一条32位指令, 意思是跳转到0地址处,cs<<4 +IP已经不是这条指令的取址方式了)  )

   32 位下cpu的解释程序发生了变化,

    CR0寄存器:

          一个32位寄存器 【|PG |.......(30位)......|PE|】 PE = 0就是实模式 16位  PE = 1 就是保护模式   PG =1 启动分页

          (上面指令,把1 给了ax  再传到PE位上)

 5、保护模式下地址翻译和中断处理

    保护模式下地址翻译  :gdt  global descriptor table( 是通过  cpu 硬件实现的 ,为了地址翻译够快)

    此时cs 叫做选择子 ,里面存放的是查表的下标,就是gdt表项的索引,真正的基地址放在表项中,

    setup会初始化gdt表 ,然后lgdt gdt 48  (这条指令是用来设置保护模式下中断和寻址方式的)

    每个表项64位,8是通过字节寻址8*8,就是第二个表项 

  

ospf cost值和metric值 ospf cost 1_保护模式_04

 

 

此时最后的 jmpi 0 8 彻底进入到操作系统中了

这里既然要进行严格控制每段程序的存放位置和执行程序,因此在编译的过程中要严格按照顺序进行编译,因此需要用一个编译工具 make系统源码中有makefile

 

head.s

( setup.s进入保护模式后,这里还有一些初始化操作  设置系统栈,开启A20等 ,这里是32位汇编代码,源操作数在左目标操作数在右侧,16位下是源在右目标在左侧)

head.s

在此程序最后 执行 setup_paging设置页表,最后ret,弹出setup_paging 后就进入到c文件范围,执行了一个永不停止的main 程序

执行main.c 中间的mian函数,

跳出方式,-----c语言组后都需要编译成汇编  ,  c函数跳转的方式,也就和这里跳转的方式一样

  c函数执行过程

  A (){B();返回位置}  这里在调用B 函数时会先记录 B函数的返回地址,然后 jmp   B 程序开始地址   B函数在执行结束后会ret  到这个返回地址上继续执行

head.s源码部分

ospf cost值和metric值 ospf cost 1_ospf cost值和metric值_05

 

这里清楚的说明了不能返回到L6,L6有个死循环程序,这里可以猜出os是个永远不会有返回结果的一段程序,永远执行不完

main.c

main中做了一系列初始化操作  

ospf cost值和metric值 ospf cost 1_IP_06

 

概括:整个内容可以包括两个部分,1,读入内存   2,初始化