从linux0.11学习linux内核设计之模式转换:实模式-保护模式(1)
来源:互联网 发布:linux samba rpm 下载 编辑:程序博客网 时间:2024/05/22 09:48
作者:朱克锋
转载请注明出处:http://blog.csdn.net/linux_zkf
在上篇文章中bootsec已经把所有程序都加载到计算机的内存中的一定位置,下面接着上篇文章的结尾
jmpi 0,SETUPSEG开始要进入setup程序开始执行。
看一下这行代码:
jmpi 0,SETUPSEG
这行代码的作用就是跳转到SETUPSEG出开始执行,就是setup程序加载的位置,OK,此时setup接着bootsec开始继续执行.
在setup开始执行做的第一件事就是读取计算机系统数据,具体代码如下:
entry start
start:
! ok, the read went well so we get current cursor position and save it for
! posterity.
mov ax,#INITSEG ! this is done in bootsect already, but...
mov ds,ax
mov ah,#0x03 ! read cursor pos
xor bh,bh
int 0x10 ! save it in known place, con_init fetches
mov [0],dx ! it from 0x90000.
! Get memory size (extended mem, kB)
mov ah,#0x88
int 0x15
mov [2],ax
! Get video-card data:
mov ah,#0x0f
int 0x10
mov [4],bx ! bh = display page
mov [6],ax ! al = video mode, ah = window width
! check for EGA/VGA and some config parameters
mov ah,#0x12
mov bl,#0x10
int 0x10
mov [8],ax
mov [10],bx
mov [12],cx
! Get hd0 data
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0080
mov cx,#0x10
rep
movsb
! Get hd1 data
mov ax,#0x0000
mov ds,ax
lds si,[4*0x46]
mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
rep
movsb
! Check that there IS a hd1 :-)
mov ax,#0x01500
mov dl,#0x81
int 0x13
jc no_disk1
cmp ah,#3
je is_disk1
no_disk1:
mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
mov ax,#0x00
rep
stosb
is_disk1:
从代码中可以看到读取的数据覆盖了bootsec的程序!!!!对头,bootsec已经使用完了,使命已经完成,留着无用,干掉吧,呵呵呵,过河拆桥啊,不过正是这种过河拆桥的做法合理的利用了计算机的内存,bootsec所占的内存位512字节,读取的机器系统数据占510字节,仅仅只有2个字节没有被覆盖!!!利用率非常之高。
接下来就是见证历史的时刻了:系统将由实模式转换到保护模式!现代操作系统由此产生!
读取机器系统数据之后紧接着就是:
cli
可不要小看了这个mini代码,他的作用就是关闭中断,从此时开始无论系统是否产生中断,系统都不会响应此中断,直到后来的main函数打开中断,不过那时系统响应的不再是BIOS的中断了,而是由系统自己提供的了。
在setup中,关闭中断之后就是把system从开始的SYSSEG移到0x00000处,代码如下:
do_move:
mov es,ax ! destination segment
add ax,#0x1000
cmp ax,#0x9000
jz end_move
mov ds,ax ! source segment
sub di,di
sub si,si
mov cx,#0x8000
rep
movsw
jmp do_move
在0x00000处原来存放的是BIOS的一些东西,中断向量表,数据等等,这样的移动和前面一样,原来的数据全被新数据覆盖了。
紧接着setup执行如下代码:
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
。。。。。
gdt:
.word 0,0,0,0 ! dummy
.word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000 ! base address=0
.word 0x9A00 ! code read/exec
.word 0x00C0 ! granularity=4096, 386
.word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000 ! base address=0
.word 0x9200 ! data read/write
.word 0x00C0 ! granularity=4096, 386
idt_48:
.word 0 ! idt limit=0
.word 0,0 ! idt base=0L
gdt_48:
.word 0x800 ! gdt limit=2048, 256 GDT entries
.word 512+gdt,0x9 ! gdt base = 0X9xxxx
这段代码的作用就是setup利用自己的数据信息对中断描述符表寄存器IDTR和全局描述符表寄存器GDTR进行初始化。
初始化中断描述符表寄存器IDTR和全局描述符表寄存器GDTR之后执行到这里:
! that was painless, now we enable A20
call empty_8042
mov al,#0xD1 ! command write
out #0x64,al
call empty_8042
mov al,#0xDF ! A20 on
out #0x60,al
call empty_8042
打开A20!!!!
前面说过实模式的中断机制已经被关闭和破坏,但是又不能没有中断机制,所以要为保护模式下建立中断机制,在setup中将对可编程的终端控制器进行重新编程,代码如下:
moval,#0x11 ! initialization sequence
out #0x20,al ! send it to 8259A-1
.word 0x00eb,0x00eb ! jmp $+2, jmp $+2
out #0xA0,al ! and to 8259A-2
.word 0x00eb,0x00eb
mov al,#0x20 ! start of hardware int's (0x20)
out #0x21,al
.word 0x00eb,0x00eb
mov al,#0x28 ! start of hardware int's 2 (0x28)
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0x04 ! 8259-1 is master
out #0x21,al
.word 0x00eb,0x00eb
mov al,#0x02 ! 8259-2 is slave
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0x01 ! 8086 mode for both
out #0x21,al
.word 0x00eb,0x00eb
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0xFF ! mask off all interrupts for now
out #0x21,al
.word 0x00eb,0x00eb
out #0xA1,al
搞定这些之后,即进入以下代码:
mov ax,#0x0001 ! protected mode (PE) bit
lmsw ax ! This is it!
jmpi 0,8 ! jmp offset 0 of segment 8 (cs)
注意这行代码:
jmpi 0,8
这里就跳到head程序了。
到此呢,setup程序执行完毕,后面就由head继续来完成。
在下一篇文章中我将继续head程序分析、学习linux。加油
- 从linux0.11学习linux内核设计之模式转换:实模式-保护模式(1)
- 从linux0.11学习linux内核设计之模式转换:实模式-保护模式(2)
- linux0.00内核剖析之2.保护模式内存管理
- 从linux0.11学习linux内核设计之开始
- 从linux0.11学习linux内核设计之程序加载
- Linux0.11内核--8086中的实模式
- Linux内核0.12——从一个简单的多任务内核实例学习保护模式
- 从保护模式到实模式的转换
- 从保护模式到实模式的转换
- Linux0.11内核--32位保护模式GDT(全局描述符表)
- linux内核完全剖析之(1)——80x86保护模式
- Swift设计模式之保护代理模式
- linux 内核 设计模式
- 从操作系统内核看设计模式--linux内核中的Observer
- 汇编学习笔记之实模式/保护模式内存寻址
- 汇编学习笔记之实模式/保护模式区别
- [设计模式]学习设计模式之二(原则1)
- 实模式保护模式
- 排序算法分析(JAVA实现)
- DAO设计模式
- C++ : #include "stdafx.h"
- 字符串(string)类型
- ubantu -- NFS -- TFTP
- 从linux0.11学习linux内核设计之模式转换:实模式-保护模式(1)
- linux下如何隐藏进程(ps/top)
- XML解析
- 顺序堆栈
- Go语言入门系列之安装及HelloWorld
- gvim+插件开发,体验
- 【*】POJ-3899(数论很难)(Lucky Numbers——统计)
- 字符串操作
- javabean的继承与反射