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程序

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354