浅析Linux源码:bootsect.s,setup.s,head.s

     最近在学习操作系统,就看了下Linux0.11版的源码解析,写一点自己的体会。

     PC开机之后,80X86进入实模式,并且从BIOS(RAM)里的某个地址开始,读取代码到CPU,并执行。BIOS对机器自检,并从内存0x0000处初始化中断向量(BIOS的),中断向量可以这样理解,子函数的入口地址,CPU调用BIOS的中断向量,可以获得一些硬盘等参数,后面会用到。这些子函数据猜测应该是在BIOS里面。中断向量表占用大概1M的空间(0x0000-0x1000)。

     然后,BIOS把磁盘或者硬盘的第一个扇区(磁盘引导区)读入内存的0x7c00处,BIOS完事了。

     这里,第一个扇区装的是bootsect.s,好了,下面是它的代码:

   

   这段代码很长很长,做的事情却不是很多。

   代码前面做了一些变量定义,每个代码段在物理内存的起始地址等。

   程序从start开始执行。

   它做的第一件事情就是把自己移动到0x9000处。ds:si=0x07C0:0x0000->es:di=0x9000:0x0000,这样做是要干嘛呢?是为了以后加载setup.s和system模块,因为在bootsect.s里面调用了0x0000内存处的中断向量,同样,setup.s也要调用,所以0x1000以下的地址要留给中断向量,而system又比较大(<512KB),8086实模式下寻址范围只有1M,只能把自己的代码移过来移过去了。

  好了,现在bootsect.s到达了0x9000处,紧接着,它调用BIOS的int 0x13中断,把磁盘的第二个扇区开始,读取四个扇区到它后面,

就是0x9020(setup.s)以上的地址。这样,bootsect.s的功能就完成了。具体中断调用的格式很无聊,没有仔细去研究。不过8086实模式下的编程倒是很有意思,cs,ds,es,ss,都可以随便玩,可以移动自身代码,在1M如此小的寻址范围内,应该是一种很常用的方法。

   下面就不贴setup.s的代码了,很长,功能也很单一。

    setup.s主要工作是利用BIOS中断向量表读取一些系统参数,比如光标位置,硬盘参数,等。然后,BIOS中断向量表就没啥用了,setup.s把system模块移动到0x0000处,这里用到了一个小的技巧。

    由system模块比较长,cx只能表示一个十六位的数字,最多就是0xFFFF。所以这里做了一个嵌套循环,每次只移动64K的代码,分为8次移动,刚刚好把0x1000的代码移动到了0x9000处。如果把cx表示移动的字节数(0x8000每次),显然0x8000*4超过了一个十六位数可以表示的范围。这个比较好玩。

    好了,下面,加载idt和gdt,idt是中断门描述符表,gdt是全局描述符表。这里,为了head里调用保护模式,所以先load下idt和gdt,具体的数值在该程序的末尾,idt_48,gdt_48里面。

   然后,刊A20地址线是否关闭(IBM的历史遗留问题,不管了),然后做了一件痛苦的事情:

   对俩中断芯片编程。这也是遗留问题吧貌似。

   中断芯片,顾名思义,就是终端到来时,发给CPU的信号,CPU在时钟的作用下,每隔10ms干一次活,终端可以在间隙里向CPU发送一些固定的信号,就是通过终端芯片发送(俩8259),比如,键盘,鼠标,异常等,这些中断发给CPU之后,CPU会响应他们或者不管他们(丢进队列),然后,idt表就神奇的起作用了:CPU根据发送过来的信号(int),找相应的中断函数去处理,idtr寄存器的值保存了当前idt表的内存位置,然后根据中断的数值找到处理中断的函数,做相应的处理,在后面还会看到,中断处理函数有个特殊的机制:需要保存当前寄存器的值之后,再调用中断函数。这用C显然是不可能实现的,汇编又大显身手了。

  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值