linux-0.11分析:boot文件 setup.s 第二篇随笔
boot文件 setup.s 第二篇随笔
参考 [github这个博主的][ https://github.com/sunym1993/flash-linux0.11-talk ]
中断获取光标的位置,和从磁盘读取一些东西
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... INITSEG = 0x9000
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.
读取光标的位置在dx中,dh(高8位)存储的是行号,dl(第8位)存储的是列号.
然后把dx存入偏移地址为[0],段地址为0x9000中:0x9000:0x0000
获取一些其他信息,内存大小、显卡位置、一些配置参数存入到内存中
; 获取内存大小(扩展内存,kB)
mov ah,#0x88
int 0x15
mov [2],ax ; 获取显示卡数据:
mov ah,#0x0f
int 0x10
mov [4],bx ; bh = 显示页面
mov [6],ax ; al = 显示模式模式,ah=窗口宽度 ; 检查EGA/VGA和一些配置参数
mov ah,#0x12
mov bl,#0x10
int 0x10
mov [8],ax
mov [10],bx
mov [12],cx
- int 0x15中断获取一些内存信息,存储到0x9000:0x0002中,也就是0x90002
- int 0x10中断获取其他信息,显示页面存储到0x9000:0x0004中,也就是0x90004;显示模式和窗口宽度在ax中,然存储到0x9000:0x0006中,也就是0x90006,al = 显示模式模式,ah = 窗口宽度
- int 0x10中断获取一些配置参数的信息,分别存储到0x90008,0x9000A,0x9000C中
接下来又是利用:rep movsb 复制字节来读取硬盘信息
; 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
lds si,[4*0x41] ;也就是把这个地址的低位给si
hd0是从 es:si = ds:di 读取16个字节:也就是从
0x0000:0x0004 ==> 0x9000:0x0080
hd0是从 es:si = ds:di 读取16个字节:也就是从
0x0000:0x0018 ==> 0x9000:0x0090
setup经过上面的操作:
地址 | 字节 | 存储的东西 |
---|---|---|
0x90000 | 1 | 光标列号 |
0x90001 | 1 | 光标行号 |
0x90002 | 2 | 内存大小 |
0x90004 | 2 | 显示页面 |
0x90006 | 1 | 模式模式 |
0x90007 | 1 | 窗口宽度 |
0x90008 | 2 | 配置参数 |
0x9000A | 2 | 配置参数 |
0x9000C | 2 | 配置参数 |
0x90080 | 16 | hd0硬盘信息 |
0x90010 | 16 | hd1硬盘信息 |
接下来这一段不是很重要在判断hd1是否存在信息
; 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 ;INITSEG=0x9000
mov es,ax
mov di,#0x0090
mov cx,#0x10
mov ax,#0x00
rep
stosb
存储完毕就转到保护模式并且结束中断
is_disk1:
; 现在我们要转到保护模式 ...
cli ; 不允许中断
接下下来又是一段内存数据的复制操作:
mov ax,#0x0000
cld ; 'direction'=0, movs moves forward
do_move:
mov es,ax ; destination segment es = 0x0000
add ax,#0x1000
cmp ax,#0x9000 ;控制循环8次
jz end_move
mov ds,ax ; source segment ds = 0x1000
sub di,di
sub si,si
mov cx,#0x8000 ;每次移动 0x8000次
rep
movsw ;一次移动 2个字节
jmp do_move
cmp ax,#0x9000
jz end_move ;当ax为等于0x9000时就跳转,一直循环移动的8个来回,正好可以跳转
这里也是 es:si = ds:di :
0x10000开始的0x80000个字节移动到 ==> 0x00000开始位置后面的80000个字节
0x10000-0x90000 ==> 0x00000-0x80000
经过上面这一段存储信息,移动内存等等操作现在重新看看内存表
接下来就是从实模式到保护模式的操作了
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_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
实模式和保护模式第一个区别就是寻址方式的改变,
在实模式下是 段地址:偏移地址
在保护模式下:
ds 寄存器里存储的值,在实模式下叫做段基址,在保护模式下叫段选择子 ; 段选择子里存储着段描述符的索引
通过段描述符索引,可以从全局描述符表 GDT 中找到一个段描述符,段描述符里存储着段基址。
段基址取出来,再和偏移地址相加,就得到了物理地址,整个过程如下。
段基址:也就是段描述符基地址
然后经过下面的操作:就可以得到物理地址
GDT 表在哪,在内存中:
lgdt gdt_48 ;通过这条指令来存储这个表的
看看 gdt_48这个表:
gdt_48:
.word 0x800 ; gdt limit=2048, 256 GDT entries
.word 512+gdt,0x9 ; gdt base = 0X9xxxx
gdt 的内存地址:0x90200 + gdt
这就是gdt存储的数据,页数这个表
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
最终的内存结构:( idtr 寄存器 == > 中断描述符表 )
接下来这段代码就是打开20A的地址总线
call empty_8042
mov al,#0xD1 ; command write
out #0x64,al
call empty_8042
mov al,#0xDF ; A20 on
out #0x60,al
也就是当CUP升级到了32位时,由于物理地址总线还是20位的,所以只能使用20位的寻址方式,使用需要手动打开20位的地址总线
接下来这段代码不是很重要
; 嗯,我希望一切顺利。现在我们必须重新编程中断:
; 我们把它们放在intel保留硬件中断之后
; int 0x20-0x2F。在那里,他们不会搞砸任何事情。可悲的是,IBM真的
; 把这件事和原来的电脑搞砸了,他们还没能做到
; 事后纠正。因此,bios在0x08-0x0f处设置中断,
; 它也用于内部硬件中断。我们只是
; 必须重新编程8259,这一点都不有趣。 mov al,#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
不是很重要,这是之后中断信息表
PIC 请求号 中断号 用途 IRQ0 0x20 时钟中断 IRQ1 0x21 键盘中断 IRQ2 0x22 接连从芯片 IRQ3 0x23 串口2 IRQ4 0x24 串口1 IRQ5 0x25 并口2 IRQ6 0x26 软盘驱动器 IRQ7 0x27 并口1 IRQ8 0x28 实时钟中断 IRQ9 0x29 保留 IRQ10 0x2a 保留 IRQ11 0x2b 保留 IRQ12 0x2c 鼠标中断 IRQ13 0x2d 数学协处理器 IRQ14 0x2e 硬盘中断 IRQ15 0x2f 保留 下面是从实模式切换到保护模式的最后步骤
mov ax,#0x0001 ; 保护模式(PE)位
lmsw ax ; This is it;
jmpi 0,8 ; 第8段(cs)的jmp偏移0
前两行,将 cr0 这个寄存器的位 0 置 1,模式就从实模式切换到保护模式了。
jmpi 0,8 就是把段寄存器和偏移地址改变,在保护模式下的寻址方式变了
然后在最后的 计算下 最后执行的位置为0x00000处
这个位置就是最后操作系统的System代码在内存中的位置
System这段代码的文件就是通过
Makefile
这个执行把head.s
和main.c
以及其他的文件整合起来一起导入,接下就看看head.s
代码把
linux-0.11分析:boot文件 setup.s 第二篇随笔的更多相关文章
- linux-0.11分析:boot文件 bootsect.s 第一篇随笔
boot文件 bootsect.s 第一篇随笔 参考 [github这个博主的][ https://github.com/sunym1993/flash-linux0.11-talk ] bootse ...
- Linux 0.11下信号量的实现和应用
Linux 011下信号量的实现和应用 生产者-消费者问题 实现信号量 信号量的代码实现 关于sem_wait和sem_post sem_wait和sem_post函数的代码实现 信号量的完整代码 实 ...
- 【从头到脚品读 Linux 0.11 源码】第一回 最开始的两行代码
从这一篇开始,您就将跟着我一起进入这操作系统的梦幻之旅! 别担心,每一章的内容会非常的少,而且你也不要抱着很大的负担去学习,只需要像读小说一样,跟着我一章一章读下去就好. 话不多说,直奔主题.当你按下 ...
- Linux 0.11中write实现
看了一下Linux 0.11版本号write的实现,首先它在标准头文件unistd.h中有定义 int write(int fildes, const char * buf, off_t count) ...
- Linux 0.11源码阅读笔记-总结
总结 Linux 0.11主要包含文件管理和进程管理两个部分.进程管理包括内存管理.进程管理.进程间通信模块.文件管理包含磁盘文件系统,打开文件内存数据.磁盘文件系统包括空闲磁盘块管理,文件数据块的管 ...
- Linux 0.11源码阅读笔记-文件管理
Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件. 磁盘分区 生磁盘可以被分区,分区中可以安装文件系统, ...
- Linux 0.11源码阅读笔记-中断过程
Linux 0.11源码阅读笔记-中断过程 是什么中断 中断发生时,计算机会停止当前运行的程序,转而执行中断处理程序,然后再返回原被中断的程序继续运行.中断包括硬件中断和软件中断,硬中断是由外设自动产 ...
- Linux 0.11源码阅读笔记-总览
Linux 0.11源码阅读笔记-总览 阅读源码的目的 加深对Linux操作系统的了解,了解Linux操作系统基本架构,熟悉进程管理.内存管理等主要模块知识. 通过阅读教复杂的代码,锻炼自己复杂项目代 ...
- Linux内核:分析coredump文件 - 内核代码崩溃
转自:http://blog.csdn.net/guowenyan001/article/details/12975221 一.分析Core文件 1.1 找到core文件目录,启动mycrash:my ...
随机推荐
- 203. Remove Linked List Elements - LeetCode
Question 203. Remove Linked List Elements Solution 题目大意:从链表中删除给定的数 思路:遍历链表,如果该节点的值等于给的数就删除该节点,注意首节点 ...
- 482. License Key Formatting - LeetCode
Question 482. License Key Formatting Solution 思路:字符串转化为char数组,从后遍历,如果是大写字母就转化为小写字母,如果是-就忽略,如果遍历了k个字符 ...
- 【Java面试】JVM如何判断一个对象可以被回收
Hi, 我是Mic. 今天分享一道一线互联网公司必问的面试题. "JVM如何判断一个对象可以被回收" 关于这个问题,来看看普通人和高手的回答. 普通人: 嗯.......... 高 ...
- C#获取PLC信息 (KepServer)二
具体应用呢,不多说了,上代码,取长补短就是原创 using OPCAutomation; using System; using System.Collections.Generic; using S ...
- ElasticSearch6.4.2
做一个简单的API记录 1.依赖为6.4.2 比较老的版本 2.指定ES集群,可接多个Put(); Setting setting=Setting.builder().put("clust ...
- 基于MybatisPlus代码生成器(2.0新版本)
一.模块简介 1.功能亮点 实时读取库表结构元数据信息,比如表名.字段名.字段类型.注释等,选中修改后的表,点击一键生成,代码成即可提现出表结构的变化. 单表快速转化restful风格的API接口并对 ...
- 在Ubuntu系统下,可执行文件的表现形式
在Windows系统下的可执行文件都带有.exe的后缀,而对于Linux系统下的可执行文件,则不会带有后缀,如下图 对于.txt文件,Ubuntu下也有相应的记事本程序打开,对于.xml,ubuntu ...
- Maven + SSM环境搭建
Maven + SSM 之前Maven+SSM都是照着搭建的,自己想写点什么的时候发现搭建的过程不清楚. 于是花了时间边整理思路边搭建,并把搭建过程记录下来. 视频看来终觉浅,还是需要自己动手实践,捋 ...
- HTML\Flex tips
相关文档 HTML:https://www.w3school.com.cn/html/index.asp bootstrap-css: https://v3.bootcss.com/css/#form ...
- 解决github.com 的响应时间过长以及hosts配置不能保存的问题
github.com 的响应时间过长 1 获取github可以使用的DNS域名 DNS查询 选择TTL值最小的 2 修改hosts配置 打开之后在最后加上如下内容,保存即可 3 出现hosts不能保存 ...