《Linux内核设计的艺术》学习笔记(六)执行setup.s
参考资料
jmpi , SETUPSEG // 0x90200
到这里,bootsect.s的执行就算结束了。控制权转移到了setup.s文件的手中。
setup程序的主要作用是利用ROM BIOS中断读取机器系统数据,并将这些数据保存到0x90000开始的位置。下表基本归纳了Line 109之前的所有代码逻辑。
表1 setup.s前半段代码的作用
内存地址 | 长度(字节) | 名称 | 描述 |
0x90000 | 2 | 光标位置 | 行列都是从0开始,各占一个字节。由int 0x10中断(入口参数为AH=0x03)取得到DX中,并保存到内存。 |
0x90002 | 2 | 扩展内存数 | 系统从1MB开始的扩展内存数值(KB)。由0x15中断(入口参数为AH=0x88)取得到AX中,并保存到内存。 |
0x90004 | 2 | 当前活动页 | 当前显示的页面。由int 0x10中断(入口参数为AH=0x0F)取得到BH中,并保存到内存。 |
0x90006 | 1 | 显示模式 | 同上,由int 0x10中断(入口参数为AH=0x0F)取得到AL中,并保存到内存。 |
0x90007 | 1 | 字符的列数 | 同上,int 0x10中断(入口参数为AH=0x0F)取得到AH中,并保存到内存。 |
0x90008 | 2 | 未知 | 被破坏了。int 0x10中断(入口参数为AH=0x0F,BL=0x10)。 |
0x9000A | 1 | 内存大小标识 | 同上,int 0x10中断(入口参数AH=0x0F,BL=0x10)取得到BL中,并保存到内存(0x00=64K,0x01=128K,0x02=192K,0x03=256K)。 |
0x9000B | 1 | 视频状态 | 同上,int 0x10中断(入口参数AH=0x0F,BL=0x10)取得到BL中,并保存到内存(0x00为彩色模式,I/O端口为0x3DX;0x01为单色,I/O端口为0x3BX)。 |
0x9000C | 2 | 显卡特性参数 | 同上,int 0x10中断(入口参数AH=0x0F,BL=0x10)取得到CX中,并保存到内存。CH和CL各有含义。 |
0x90080 | 16 | 硬盘hd0参数表 | 取中断向量0x41所指的内存值,放于0x9000:0x0080处。由movsb命令实现。 |
0x90090 | 16 | 硬盘hd1参数表 | 取中断向量0x46所指的内存值,放于0x9000:0x0090处。由movsb命令实现。 |
0x901FC | 2 | 根设备号 | 根文件系统所在的设备号在bootsect.s中设置,这里没有代码参与。 见bootsect.s中第251行。 |
接下来使用cli命令屏蔽中断。
cld命令将DF设置为0,增址方向。std与之相反。
通过movsw命令,将system模块从0x10000到0x8FFFF的内存数据块(512KB)移动到0x00000开始的位置。每次移动64KB,共移动8次。
初始化IDT寄存器和GDT寄存器。
选通A20地址线。
重新对8259A中断控制器编程。
通过lmsw命令将0x0001写入到控制寄存器CR0中,打开保护模式。
最后,通过jmpi 0, 8命令跳转至CS段8,偏移地址为0处。即,0x00000处。
图1 setup.s程序结束后内存中程序示意图
setup.s代码如下:
!
! setup.s (C) Linus Torvalds
!
! setup.s is responsible for getting the system data from the BIOS,
! and putting them into the appropriate places in system memory.
! both setup.s and system has been loaded by the bootblock.
!
! This code asks the bios for memory/disk/other parameters, and
! puts them in a "safe" place: 0x90000-0x901FF, ie where the
! boot-block used to be. It is then up to the protected mode
! system to read them from there before the area is overwritten
! for buffer-blocks.
! ! NOTE! These had better be the same as in bootsect.s! INITSEG = 0x9000 ! we move boot here - out of the way
SYSSEG = 0x1000 ! system loaded at 0x10000 ().
SETUPSEG = 0x9020 ! this is the current segment .globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text 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 [],dx ! it from 0x90000. ! Get memory size (extended mem, kB) mov ah,#0x88
int 0x15
mov [],ax ! Get video-card data: mov ah,#0x0f
int 0x10
mov [],bx ! bh = display page
mov [],ax ! al = video mode, ah = window width ! check for EGA/VGA and some config parameters mov ah,#0x12
mov bl,#0x10
int 0x10
mov [],ax
mov [],bx
mov [],cx ! Get hd0 data mov ax,#0x0000
mov ds,ax
lds si,[*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,[*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,#
je is_disk1
no_disk1:
mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
mov ax,#0x00
rep
stosb
is_disk1: ! now we want to move to protected mode ... cli ! no interrupts allowed ! ! first we move the system to it's rightful place mov ax,#0x0000
cld ! 'direction'=0, movs moves forward
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 ! then we load the segment descriptors end_move:
mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-)
mov ds,ax
lidt idt_48 ! load idt with ,
lgdt gdt_48 ! load gdt with whatever appropriate ! 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 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
! we put them right after the intel-reserved hardware interrupts, at
! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
! messed this up with the original PC, and they haven't been able to
! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
! which is used for the internal hardware interrupts as well. We just
! have to reprogram the 's, and it isn't fun. mov al,#0x11 ! initialization sequence
out #0x20,al ! send it to 8259A-
.word 0x00eb,0x00eb ! jmp $+, jmp $+
out #0xA0,al ! and to 8259A-
.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 (0x28)
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0x04 ! - is master
out #0x21,al
.word 0x00eb,0x00eb
mov al,#0x02 ! - is slave
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0x01 ! 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 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
! need no steenking BIOS anyway (except for the initial loading :-).
! The BIOS-routine wants lots of unnecessary data, and it's less
! "interesting" anyway. This is how REAL programmers do it.
!
! Well, now's the time to actually move into protected mode. To make
! things as simple as possible, we do no register set-up or anything,
! we let the gnu-compiled -bit programs do that. We just jump to
! absolute address 0x00000, in -bit protected mode. mov ax,#0x0001 ! protected mode (PE) bit
lmsw ax ! This is it!
jmpi , ! jmp offset of segment (cs) ! This routine checks that the keyboard command queue is empty
! No timeout is used - if this hangs there is something wrong with
! the machine, and we probably couldn't proceed anyway.
empty_8042:
.word 0x00eb,0x00eb
in al,#0x64 ! 8042 status port
test al,#2 ! is input buffer full?
jnz empty_8042 ! yes - loop
ret 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 .text
endtext:
.data
enddata:
.bss
endbss:
《Linux内核设计的艺术》学习笔记(六)执行setup.s的更多相关文章
- linux内核设计与实现学习笔记-模块
模块 1.概念: 如果让LINUX Kernel单独运行在一个保护区域,那么LINUX Kernel就成为了“单内核”. LINUX Kernel是组件模式的,所谓组件模式是指:LINUX K ...
- 《Linux内核设计与分析》第六周读书笔记——第三章
<Linux内核设计与实现>第六周读书笔记——第三章 20135301张忻估算学习时间:共2.5小时读书:2.0代码:0作业:0博客:0.5实际学习时间:共3.0小时读书:2.0代码:0作 ...
- Linux内核设计与实现 读书笔记 转
Linux内核设计与实现 读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://bl ...
- linux内核设计的艺术--系统启动第一步
计算机究竟是如何执行起来的呢,在我学习计算机的时候一直不是非常明确,可是近期借了本<linux内核设计的艺术>算是知道了计算机从按开机到启动操作系统之间究竟做了些什么. 这本书刚開始介绍的 ...
- linux内核分析第四周学习笔记
linux内核分析第四周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- Linux内核分析第二周学习笔记
linux内核分析第二周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- linux内核分析第一周学习笔记
linux内核分析第一周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- 初探内核之《Linux内核设计与实现》笔记上
内核简介 本篇简单介绍内核相关的基本概念. 主要内容: 单内核和微内核 内核版本号 1. 单内核和微内核 原理 优势 劣势 单内核 整个内核都在一个大内核地址空间上运行. 1. 简单.2. 高效 ...
- Linux内核设计与实现 总结笔记(第六章)内核数据结构
内核数据结构 Linux内核实现了这些通用数据结构,而且提倡大家在开发时重用. 内核开发者应该尽可能地使用这些数据结构,而不要自作主张的山寨方法. 通用的数据结构有以下几种:链表.队列.映射和二叉树 ...
- Linux内核设计与实现 总结笔记(第十六章)页高速缓存和页回写
页高速缓存是Linux内核实现磁盘缓存.磁盘告诉缓存重要源自:第一,访问磁盘的速度要远远低于访问内存. 第二,数据一旦被访问,就很有可能在短期内再次被访问到.这种短时期内集中访问同一片数据的原理称作临 ...
随机推荐
- java总结第二次(剩余内容)//类和对象1
7.成员变量和局部变量 成员变量:在类中定义,用来描述对象将要有什么 局部变量:在类的方法中定义,在方法中保存临时数据 区别:作用域不同 局部变量的作用域仅限于定义它的方法 成员变量的作用域在整个类内 ...
- 【python cookbook】【数据结构与算法】15.根据字段将记录分组
问题:想根据字典或者对象实例的某个特定的字典(比如日期)来分组迭代数据 解决方案:itertools.groupby()函数在对数据进行分组时特别有用(前提是先以目标字典进行排序) rows = [ ...
- PHP用substr截取字符串出现中文乱码问题用mb_substr
PHP用substr截取字符串出现中文乱码问题用mb_substr实例:mb_substr('截取中文乱码问题测试',0,5, 'utf-8'); 语法 : string substr (string ...
- rsync的断点续传设置。
关于rsync的断点续传 关于rsync的断点续传 经常copy大文件,由于服务器.路由等网络的不确定性,老是出现 remote server not responding.于是查了下资料,发现rsy ...
- 修改Linux时间一般涉及到3个命令: date, clock, hwclock
原贴:http://203.208.37.104/search?q=cache:p1vAAHvs9ikJ:www.goldthe.com /blog/%3Faction%3Dshowlog%26gid ...
- JavaEE基础(三)
1.Java语言基础(逻辑运算符的基本用法) A:逻辑运算符有哪些 &,|,^,! &&,|| B:案例演示 逻辑运算符的基本用法 注意事项: a:逻辑运算符一般用于连接boo ...
- mysql语句
查询字段长度:SELECT MAX(LENGTH(pd)) FROM `table` where id=2;来检查当前表中字段的字符集设置.show full fields from tableNam ...
- java final .static修饰符
static静态修饰符(使用static修饰符修饰的成员变量.常量.和成员方法成为静态变量.常量和方法,他们统称为静态成员,归整个类所有,不依赖于类的特定实例,被类的所有实例共享,只要这个类被加载,J ...
- ACM题目————图的广度优先搜索
题目描述 图的广度优先搜索类似于树的按层次遍历,即从某个结点开始,先访问该结点,然后访问该结点的所有邻接点,再依次访问各邻接 点的邻接点.如此进行下去,直到所有的结点都访问为止.在该题中,假定所有的结 ...
- [转]application windows are expected to have a root view controller错误
转载地址:http://blog.sina.com.cn/s/blog_6784e6ea01017jfy.html 最新更正:这个提示几乎不影响编译和运行,可以不用设置. 产生这个提示的操作: ...