博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习linux0.11内核代码——引导启动程序setup.s
阅读量:2512 次
发布时间:2019-05-11

本文共 3179 字,大约阅读时间需要 10 分钟。

一、功能描述

setup.s是一个操作系统加载程序,主要作用是
1)利用ROS BIOS中断读取机器系统数据,并将这些数据保存到0x90000开始的位置(覆盖了bootsect程序所在地方),所取得的参数和保留的内存位置如下表:
这里写图片描述
2)将setup程序将system模块从0x10000-0x8ffff整块向下移动到内存绝对地址0x00000处;
3)加载中断描述符表寄存器(idtr)和全局描述符表寄存器(gdtr),开启A20地址线,重新设置两个中断控制芯片8259A,将硬件中断号重新设置为0x20-0x2f;
4)最后设置CPU的控制寄存器CR0,进入32位保护模式运行,并跳转到system模块最前面的head.s程序。
二、代码注释
定义宏:

INITSEG = 0x9000  ! we move boot here - out of the waySYSSEG  = 0x1000 ! system loaded at 0x10000 (65536).SETUPSEG = 0x9020 ! this is the current segment

1) 利用ROS BIOS中断读取机器系统数据,并将这些数据保存到0x90000开始的位置

①使用BIOS中断0x10功能号ah=0x03,读光标位置,并保存在内存0x90000处(2字节)。
中断0x10功能号ah=0x03介绍:
输入:bh=页号
返回:ch=扫描开始线; cl=扫描结束线; dh=行号(0x00顶端); dl=列号(0x00最左边)

mov    ax,#INITSEG      ! this is done in bootsect already, but...mov  ds,ax        !ds=0x9000,即即将保存光标的寄存器地址mov  ah,#0x03    ! read cursor posxor    bh,bh                   !第0页int     0x10           ! save it in known place, con_init fetchesmov  [0],dx                  !将光标行和列号保存在ds x 10H + 0

②利用BIOS中断0x15功能号 ah=0x88 取系统所含扩展内存大小并保存在内存0x90002处

中断返回值: ax= 从0x100000 (1M)处开始的扩展内存大小(KB)。若出错则CF置位,ax = 出错码

mov  ah,#0x88int     0x15 !开启BIOS中断0x15 ah=0x88,ax=返回值mov  [2],ax…

代码51-104同①②,均是使用BIOS中断功能获取相关数据,由于使用方式相似,很好理解,没什么内容,不再赘述。

2) 将setup程序将system模块从0x10000-0x8ffff整块向下移动到内存绝对地址0x00000处

! now we want to move to protected mode ...         cli                        ! 禁用硬件中断! first we move the system to it's rightful place         mov  ax,#0x0000         cld                       ! cld是清方向标志位,使DF=0(使一次计数+1,如果DF=1,则一次计数-1)do_move:         mov  es,ax           !目的地址es:di 初始0x0:0x0         add    ax,#0x1000         cmp   ax,#0x9000 ! 比较是否把最后一段代码移动完         jz       end_move         mov  ds,ax          !源地址ds:si,初始0x1000:0x0         sub    di,di         sub    si,si            ! di、si清零         mov          cx,#0x8000  !计数器,移动0x8000(0x10000-0x8fff)字         rep         movsw         jmp   do_move

我们需要将system模块从0x10000-0x8ffff移动到0x00000,那么初始(源)地址就是0x1000:0x0,目的初始地址是0x0:0x0,共移动0x8000(0x10000-0x8fff)字。那么我们使用rep循环操作去移动,每次移动完毕使用cmp语句去判断,是否移动到结尾(0x9000),其中源寄存器ds:si,目的寄存器es:di,这就是上面整段语句的含义。

3)加载中断描述符表寄存器(idtr)和全局描述符表寄存器(gdtr),开启A20地址线,重新设置两个中断控制芯片8259A,将硬件中断号重新设置为0x20-0x2f

①加载中断描述符表和全局描述符表

end_move:         mov  ax,#SETUPSEG ! right, forgot this at first. didn't work :-)         mov  ds,ax         lidt    idt_48                  ! load idt with 0,0          lgdt   gdt_48                 ! load gdt with whatever appropriate         …         设置IDT表,这里先设置一个长度为0的空表         idt_48:         .word         0                          ! idt limit=0         .word         0,0                       ! idt base=0L         设置GDT表gdt_48:         .word         0x800                  ! gdt limit=2048, 256 GDT entries         .word         512+gdt,0x9        ! gdt base = 0X9xxxx

②开启A20地址线

call    empty_8042        !测试8042状态寄存器,等待输入缓冲器空,只有当输入缓冲器空才可以对其执行写命令         mov  al,#0xD1             ! command write  0xD1命令码——表示要写数据到8042的P2端口。P2端口的位1用于A20线的选通,数据要写到0x60口         out    #0x64,al         call    empty_8042        !等待输入缓冲器空,看命令是否被接受         mov  al,#0xDF             ! A20 on         out    #0x60,al         call    empty_8042        !测试:若输入缓冲器为空,则表示A20线已选通

3) 最后设置CPU的控制寄存器CR0,进入32位保护模式运行,并跳转到system模块最前面的head.s程序.。

这里写图片描述

你可能感兴趣的文章
xml
查看>>
使用 Left Join 的一个错误说明
查看>>
Scala入门系列(十一):模式匹配
查看>>
Sql Server 生成数据透视表 (行列转换等经典SQL语句)
查看>>
理解sizeof()
查看>>
Vue学习笔记之vue-cli脚手架安装和webpack-simple模板项目生成
查看>>
SqlServer 扩展属性
查看>>
优先队列
查看>>
一些程序和工具
查看>>
java8 运算语法集
查看>>
IDEA关于重命名
查看>>
Es6 中let var和 const 了解
查看>>
巧用队列之”Voting“
查看>>
Oracle数据类型number(m,n)
查看>>
C#多线程学习(一) 多线程的相关概念
查看>>
JS构造函数、原型对象、隐含参数this
查看>>
注册用户
查看>>
TZC Intercommunication System
查看>>
HDU 4571 SPFA+DP
查看>>
centos 创建以日期为名的文件夹
查看>>