bootsect Linux,Linux内核源码学习——bootsect.s

1.启动BIOS

加电瞬间强行将CS值设置为0xF000,IP值置为0xFFF0. CS:IP=0xFFFF0,指向BIOS的地址范围

BIOS在内存最开始的位置(0x00000)用1KB构建了中断向量表,后面紧接着256字节构建BIOS数据区,大约57KB以后的位置加载了中断服务程序

中断向量表:256个中断向量,每个中断4个字节,2个是CS,2个是IP,每个向量指向一个中断服务程序

2.把软盘中的操作系统程序加载到内存

2.1 BIOS中断0x19把第一扇区bootsect内容加载进去

CPU接收到一个int 0x19中断,然后再去中断向量表里找这个中断向量。中断向量指向0x0e6f2(中断服务程序入口地址),这个中断服务程序的作用是把软盘第一扇区中的程序(512B)加载到内存中的指定位置,即将软驱0号磁头对应盘面的0磁道1扇区的内容复制到内存0x7C00处。

2.2 把第二批和第三批程序加载到内存

规划内存

.globl begtext, begdata, begbss, endtext, enddata, endbss

.text

begtext:

.data

begdata:

.bss

begbss:

.text

!对后续操作涉及的内存位置进行设置

SETUPLEN = 4 ! nr of setup-sectors

BOOTSEG = 0x07c0 ! original address of boot-sector

INITSEG = 0x9000 ! we move boot here - out of the way

SETUPSEG = 0x9020 ! setup starts here

SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).

ENDSEG = SYSSEG + SYSSIZE ! where to stop loading

复制bootsect

将源地址0x07C00的bootsect复制到目的地址0x90000

!将源地址0x07C00的bootsect复制到目的地址0x90000

! 代码主要设定源地址和目标地址后,使用循环指令rep和移动指令movw进行移动

entry start

start:

mov ax,#BOOTSEG !BOOTSEG = 0x07c0

mov ds,ax ! ds寄存器置为0x07c0

mov ax,#INITSEG !INITSEG = 0x9000

mov es,ax

mov cx,#256 !计数器,提供需要复制的字的数量 256字=512字节

sub si,si !sub是做减法操作,此处将si,di自己减自己,即置0。

sub di,di

!移动时源地址ds:si=0x07c0:0x0000,目的地址es:di=0x9000:0x0000

!即将BIOS移动到0x9000(0x07c0用于放置bootsect.s)

rep !rep指令作用:重复执行后面一句操作,并递减cx的值,直到cx=0停止

movw !movw指令作用:这里从内存[si]处移动cx个字到[di];注意一次的移动单位是“字”, mov指令+w(word)是一次移动一个字

jmpi go,INITSEG !将BIOS移动到0x9000后,跳转(go)到INITSEG(0x9000),CS=0x90000

! 对ds,ex,ss,sp进行调整

go: mov ax,cs

mov ds,ax

mov es,ax

! put stack at 0x9ff00. !下面两条指令是将堆栈指针sp指向0x9ff00处(即0x9000:0xff00)

mov ss,ax

mov sp,#0xFF00 ! arbitrary value >>512

将setup程序加载到内存

借助0x13中断向量,从第二个扇区开始的4个扇区

!INT 0x13的使用方法:

!ah = 0x20-读磁盘扇区到内存; al = 需要读出的扇区数量;

!ch=磁道(柱面)号的低8位; cl =开始扇区(位0-5),磁道号高2位(位6-7);

!dh = 磁头号; dl = 驱动器号;

!es:bx = 指向数据缓冲区;

!如果出错则CF标志置位,ah中是出错码。

load_setup:

mov dx,#0x0000 ! drive 0, head 0 磁头号0,驱动器号0

mov cx,#0x0002 ! sector 2, track 0,开始扇区2,磁道号0

mov bx,#0x0200 ! address = 512, in INITSEG es:bx=0x9000:0x0200 即数据缓冲区为0x90200

mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors,SETUPLEN初始设置为4,ax=0x0210,ah=0x02-读磁盘扇区到内存,需要读出的扇区数量-4

int 0x13 ! read it 打开中断

jnc ok_load_setup ! ok - continue jnc指令:如果(上条指令)成功,则跳转,即中断INT 0x13成功,则继续执行ok_load_setup

mov dx,#0x0000 ! 如果不成功,则复位驱动器,并重试(重新跳转函数load_setup)

mov ax,#0x0000 ! reset the diskette

int 0x13

j load_setup

ok_load_setup:

! Get disk drive parameters, specifically nr of sectors/track 利用BIOS中断0x13取磁盘参数表中当前启动引导盘的参数

! 这段代码主要还是获得每磁道的扇区数量,保存在了sectors中

mov dl,#0x00 !驱动器号为0

mov ax,#0x0800 ! AH=8 is get drive parameters,AH=8,是INT 0x13取磁盘驱动器的参数,AL初始化0,作为返回值

int 0x13 ! 打开中断

mov ch,#0x00

seg cs ! 此条指令表示下一条语句的操作数在cs段寄存器所指的段中

mov sectors,cx

mov ax,#INITSEG

mov es,ax

将system模块加载到内存,加载240个扇区

! Print some inane message

! 显示信息:“Loading system ... 回车”,共显示24个字符

! 使用BIOS中断0x10功能号ah=0x03和ah=0x13实现

! BIOS中断0x10功能号ah=0x03,功能:读光标位置

! 输入:bh=页号

! 返回:ch=扫描开始线;cl=扫描结束线;dh=行号; dl=列号

! BIOS中断0x10功能号ah=0x13,功能:显示字符串

! 输入:al=放置光标方式及规定属性。0x01表示使用bl中属性值,光标停在字符串结尾处;

! es:bp 指向要显示的字符串起始位置。 cx=显示字符串个数; bh=显示页面号

! bl=字符属性; dh=行号; dl=页号

mov ah,#0x03 ! read cursor pos 读光标

xor bh,bh ! 将bh置为0

int 0x10

mov cx,#24 ! 24个字符

mov bx,#0x0007 ! page 0, attribute 7 (normal) bh=0,页=0; bl=7,字符属性=7

mov bp,#msg1 ! es:bp指向要显示的字符串

mov ax,#0x1301 ! write string, move cursor ah=0x13使用中断0x10功能号;al=0x01,使用bl中属性值

int 0x10 ! 打开中断,串口打印字符串

! 上面使用中断0x10显示字符,首先使用ah=0x03功能获取光标位置以及行号列号,作为ah=0x13中断的入参;

! 而后使用ah=0x13中断将存在es:bp寄存器的字符串打印在串口屏幕,只要在使用中断时,将输入设定好即可。

! ok, we've written the message, now

! we want to load the system (at 0x10000) 将system模块加载到内存0x10000往后的120KB中

mov ax,#SYSSEG !SYSSEG=0x10000

mov es,ax ! segment of 0x010000

call read_it

call kill_motor

此时整个操作系统的代码已经全部加载至内存。

确定一下根设备号

! After that we check which root-device to use. If the device is

! defined (!= 0), nothing is done and the given device is used.

! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending

! on the number of sectors that the BIOS reports currently.

! 确定根文件系统设备号并保存其设备号于root_dev

! Linux中,软驱的主设备号是2,次设备号=type*4+nr,其中nr为0-3分别对应软驱A、B、C和D;

! type是软驱类型(2->1.2MB或7->1.44MB)。

! 因为7*4+0=28,所以/dev/PS0 (2,28)指1.44MB A驱动器,其设备号是0x021c(2*256+28)

! 同理,/dev/at0 (2,8)值1.2MB A驱动器,设备号是0x0208

! 取上面获得的每磁道扇区数,如果sectors=15说明是1.2MB的驱动器;如果sectors=18说明是1.44M软驱(为什么?);

! 因为是可引导的驱动器,所以肯定是A驱

seg cs

mov ax,root_dev

cmp ax,#0

jne root_defined ! 检查root_dev是否是空,如果否,则说明其已经存入根设备号,直接跳转后面

seg cs ! 此条指令表示下一条语句的操作数在cs段寄存器所指的段中如果以Masm语法写,

seg cs和mov bx,sectors两句合起来,等价于mov bx, cs:[sectors], 这里使用了间接寻址方式。

重复一下前面的解释,mov [sectors],ax表示将ax中的内容存入ds:sectors内存单元,而mov cs:[sectors],ax强制以cs作为段地址寄存器,因此是将ax的内容存入cs:sectors内存单元

mov bx,sectors

mov ax,#0x0208 ! /dev/ps0 - 1.2Mb

cmp bx,#15 ! 将sectors与15对比,如果相同,则ax=0x0208,最终赋值给root_defined

je root_defined

mov ax,#0x021c ! /dev/PS0 - 1.44Mb

cmp bx,#18 ! 将sectors与18对比,如果相同,则ax=0x021c,最终赋值给root_defined

je root_defined

undef_root:

jmp undef_root

root_defined: !将获取的驱动设备号存入root_dev

seg cs

mov root_dev,ax

跳转到setup的第一条指令

! after that (everyting loaded), we jump to

! the setup-routine loaded directly after

! the bootblock:

jmpi 0,SETUPSEG ! 跳转到setup程序开始处(即0x90200)执行setup程序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的高校科研信息管理系统实现了操作日志管理、字典管理、反馈管理、公告管理、科研成果管理、科研项目管理、通知管理、学术活动管理、学院部门管理、科研人员管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让高校科研信息管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值