自己动手写操作系统 第四章总结

本章主要内容是建立一个功能比較完好的引导扇区也称为 boot sector

首先回想一下一个操作系统从开机到执行的过程

1.引导

2.载入内核入内存

3.跳入保护模式

4.開始运行内核

可见在内核開始运行前还有非常多工作要做,假设所有交给boot sector,512字节非常可能不够用,所以我们须要将这个

功能分担出来,这个模块就是loader

如今,boot sector 的功能就是负责把loader载入到内存中,而且把控制权交给它,到此,boot sector就完毕任务了

而载入内核的功能就交给了loader

如今再来看看执行过程

1.boot sector引导载入loader程序,并将控制权交给loader

2.loader把内核载入到内存中,并负责进入保护模式(要实现分页等功能),然后将控制权交给内核

3.内核进行接下来的操作

在第四章中我们基本的任务是写一个boot sector,让他来载入loader

同一时候学习软盘的fat12格式

先大体对程序流程有一个认识

1.首先我们须要一个写一个DOS能够识别的引导盘,注意引导扇区须要有BPB等头信息才干被微软DOS识别,所以加上它

然后通过jmp short LABEL_START:让我们開始执行引导扇区,这里有一个问题须要注意,为什么我们的引导扇区是写在floppy上的,而我们的计算机是怎么能执行它呢?这程序肯定是在内存中的,那么它是什么时候被载入到内存中的呢?

解答,在计算机加电后BIOS回查看软盘的第一个扇区的最后两个字节是不是0xaa55,假设是的话,就觉得这个扇区是可引导的,然后将这512字节的内容载入到内存中的07c00h中,然后開始执行,所以我们的boot sector是不须要我们手动进行载入到内存中的,可是我们的loader.bin和kernel却不行,他们仅仅能以文件形式存在软盘的数据区然后我们须要在boot sector中载入loader.bin到内存中,然后将控制权交给它,接着通过loader.bin将kernel载入到内存中,然后将控制权交给内核

2.将loader载入到内存中,这里我们须要用到BIOS的int 13h中断来读取软盘,也就是将软盘数据区的内容载入到内存中来,这个内存是预先设定好的,并要记住这个内存位置,由于当我们将loader从软盘数据区载入到内存中后我们须要jmp到这个位置以便将控制权交给它

这里我们将读取软盘的工作交给一个叫readsector的函数,它接受两个參数,扇区逻辑号,和要读取的扇区数目,要注意的问题是我们里给出的是扇区的逻辑号,可是用int 13h中断须要确切的物理位置,所以在函数中我们要进行这个转换才行

须要注意的地方就是怎样将逻辑扇区号转换成可供int 13h调用的物理软盘位置,以及int 13h的调用方法,以及loader将要存储的内存位置

3.当然,要读取loader的内容到内存中,首先最重要的就是在软盘中找到loader的位置才行,否则从哪里将数据转移到内存中,这里须要注意的地方有下面几点

1.怎样着手寻找?首先须要了解软盘的结构,包含,boot sector , fat1 表,fat2表,根文件夹,数据区

2.那么怎样下手呢?首先,我们要知道全部数据区的文件的文件名称都是在根文件夹的条目中,这个32位的条目中存放了关于这个文件的各种信息,详见p128,当中如今最重要的就是文件名称(条目中的前11个字节,8字节的文件名称,3字节的扩展名),以及接下来连续读取的时候须要用到的32字节中偏移0x1Ah处存放的两字节的这个文件的事实上簇号(这个簇号与扇区类似,可是又不是一样的,而是有一一相应的映射关系),如今在寻找loader的步骤中我们须要的就是文件名称,我们要遍历软盘的根文件夹区中的每个条目中的前11字节,看看是不是和我们预先设定号的loader的文件名称全然一致(比方loader.bin)

假设一致,那么记住这个根文件夹中的条目,由于接下来我们要用到这个条目中的之前说的偏移0x1Ah处的文件第一个簇号(通过这个簇号我们能够找到第一个扇区,由于他们是一一相应的),在这个遍历中我们须要三个嵌套循环,第一个是根文件夹占用的扇区总数,这里是19,所以要遍历19次,它的作用是每次循环将一个扇区取出来存到一个临时存放扇区的地方,然后以下的循环对这个扇区进行遍历操作,这个循环中嵌套一个循环,这个第二级循环的作用是遍历一个扇区中的每个条目(512/32次),接下来这个循环又嵌套一个循环,这个第三级循环的作用是遍历这一个条目的前11个字符,推断是不是和我们要找的文件名称全然一致,若一致,则跳出循环进行下一个操作,否则将一直遍历(最多19
* (512 / 32) * 11次),若没找到则提示找不到loader

3.若我们在第二步中找到了loader,我们就要对这个根文件夹条目进行操作了(32位),我们首先确定这个文件夹的起始位置,然后找到这个文件夹的偏移1Ah处,这里有最重要的簇号,通过它我们就能找到全部的loader占用的扇区,并将他们载入到一个连续的内存区域,载入完毕后就jmp到这个内存地址,然后就完毕了控制权从BIOS到loader的转移

4.如今我们找到了loader的起始簇号,那么怎样找到下一个簇号呢?这时候就要靠fat表了,fat表中存放着非常多12位的fatentry,在根文件夹条目中的偏移26字节的位置事实上存放的就是fatentry的编号,这个编号是从2開始的,0, 1两个是不用的,同一时候数据区的第0, 1两个扇区是不用的,所以我们说他们是一一相应的,通过在根文件夹中的关键条目我们得到了第一个数据扇区的簇号,也就是它在fat表中的第一个fatentry的编号,这个编号的位置存放的值是下一个数据簇号(同一时候也是下一个fatentry的编号),这种话我们就能够一直找,知道这个fatentry的值是FFFh的时候说明文件结束了,我们找到了全部的数据,假设在找的同一时候我们还将这个找到的扇区读取到那个连续的内存区域,那么找完的同一时候我们也就完毕了loader载入到内存中的任务了,注意这期间有两个比較难的地方,第一是通过fatentry的编号找到这个fatentry的位置,我们须要有奇偶两种情况,还有就是通过簇号找到其相应的逻辑扇区号(由于我们要通过逻辑扇区号来进行readsector将扇区内容载入到数据区中)

5.到了这里,我们就基本完毕了载入loader到内存中的步骤,接下来要做的就是通过jmp baseofloader:offsetofloader来完毕控制权的转移了

注意!本书的p130下方有关fatentry的图是错误的!这里害我花了非常长时间来考虑getfatentry这个函数

以下贴出我的带有完整凝视的代码,注意这代码是照着书上敲的,顺序不太一样,可能也会有点问题,可是关键的是有凝视,

;boot.asm,载入loader,方法,遍历软盘,知道找到文件名称loader.bin

%define _BOOT_DEBUG_

%ifdef _BOOT_DEBUG_

org 0100h

%else

org 07c00h  ;告诉编译器程序将要载入到这里

%endif

%ifdef _BOOT_DEBUG_

BaseOfStack equ 0100h   ;栈底,栈向低地址生长

%else

BaseOfStack equ 07c00h  ;

%endif

;事实上从这里開始都是磁盘的头

jmp short LABEL_START

nop ;这个nop为什么不可缺少!!!!!!!!!!!!!!

;原因看书上p126上的引导扇区的格式,能够看到開始处必须是一个跳转指令

;jmp LABEL_START

;nop

;接下来是fat12磁盘的头,作用是在boot sector的開始出,注意这里的位置是哪里

BS_OEMName            DB ‘ForrestY‘    ;OEM String,产商名字

BPB_BytesPerSec        DW 512            ;    每扇区的字节数

BPB_SecPerClus        DB 1            ;

BPB_RsvdSecCnt        DW 1            ;Boot记录多少扇区

BPB_NumFATs            DB 2            ;共同拥有多少FAT表

BPB_RootEntCnt        DW 224            ;根文件夹文件数最大值

BPB_TotSec16        DW 2880            ;逻辑扇区总数

BPB_Media            DB 0xF0            ;媒体描写叙述符

BPB_FATSz16            DW 9            ;每FAT扇区数

BPB_SecPerTrk        DW 18            ;每磁道扇区数

BPB_NumHeads        DW 2            ;磁头数

BPB_HiddSec            DD 0            ;隐藏扇区数

BPB_TotSec32        DD 0

BS_DrvNum            DB 0

BS_Reserved1        DB 0

BS_BootSig            DB 29h

BS_VolID            DD 0

BS_VolLab            DB ‘Tinix0.01  ‘

BS_FileSysType        DB ‘Fat12  ‘

LABEL_START:

mov ax,cs    ;

mov ds,ax    ; 初始化数据段

mov es,ax    ;初始化es 为这个段的事实上,由于用到int 10h中断须要es:bp作为串的偏移地址

mov ss, ax

mov sp, BaseOfStack

;清屏    int 10h

mov ax, 0600h

mov bx, 0700h

mov cx, 0

mov dx, 0184fh

int 10h

;因为使用了堆栈,所以这里要初始化堆栈

;    call DispStr

;    jmp $

;从这里開始是在A盘根文件夹寻找loader.bin的程序

xor ah, ah

xor dl, dl

int 13h

mov word [wSectorNo], SectorNoOfRootDirectory ;当中wsectorno是一个变量,当中存放的是根文件夹的第一个扇区号,这是一个常量19,同一时候RootDirSectors是根文件夹占用空间,这里是14,这些值都是開始定义了的

LABEL_SEARCH_IN_ROOT_DIR_BEGIN: ;要找一个文件名称就在根文件夹下寻找即可了,从这里開始就像do{}while開始循环了

cmp word [wRootDirSizeForLoop], 0  ;这里wrootdirsizeforloop是一个变量,初始值为上面那个14

jz LABEL_NO_LOADERBIN ;假设为零,那么就是到了循环结束还没找到文件,跳转到没找到那里,结束

dec word [wRootDirSizeForLoop] ;假设运行到了这里说明还没循环结束,那么就让循环索引减一

mov ax, BaseOfLoader

mov es, ax

mov bx, OffsetOfLoader ;这里BaseOfLoader:OffsetOfLoader是调用readsector函数的时候的缓存取,也就是中断int 13h的缓存区es:bx,每个扇区的内容,都将临时保存到这里

mov ax, [wSectorNo]

mov cl, 1    ;这两个是函数readsector的參数,ax代表逻辑扇区号,cl代表要读的扇区数为1

mov si, LoaderFileName    ; ds:si当中数据段ds被初始化为本程序開始处所以ds:si就是"Loader bin"的字符串位置

mov di, OffsetOfLoader ; es和ds都被初始化为了一样的,也就是程序段的開始处, 如今准备比較offsetofloader中的值了,可是这里baseofloader:offsetofloader是一整个扇区,所以等一下还须要提取出当中的文件名称才行,注意查看书128也的根文件夹条目结构Dir_Name的位置,事实上不用提取,由于偏移量为零,比較前11个字节旧能够了

cld

mov dx, 10h ;每一个扇区512字节,每一个根文件夹32字节,所以一共同拥有512/32=16个文件夹入口,这个dx是为接下来的循环做准备,要遍历整个扇区的根文件夹

LABEL_SEARCH_FOR_LOADERBIN:

cmp dx, 0

jz LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR

dec dx        ;假设没有读完一个扇区就继续读下一个文件夹

mov cx, 11        ;规定文件名称在文件夹入口偏移处为0的前11个字节里

LABEL_CMP_FILENAME:

cmp cx, 0

jz LABEL_FILENAME_FOUND  ;假设循环能运行11次,说明找到了文件名称,假设文件名称不匹配是运行不了11次的

dec cx

lodsb            ;作用,把ds:si的值写到al中,接下来和es:di中的字符比較,这两个ds es分别存了待比較的字符串,这个指令会导致si自增或自减,可是不会改变di的值,所以要在LABEL_GO_ON中手动更改

cmp al, byte [es:di]

jz LABEL_GO_ON ;假设相等,继续比較

jmp LABEL_DIFFERENT; 假设字符不匹配,则跳出循环

LABEL_GO_ON:

inc di

jmp LABEL_CMP_FILENAME    ;因为lodsb仅仅改动了si的值,所以我们须要手动改动di的值

LABEL_DIFFERENT:

and di, 0FFE0h

add di, 20h;这两步是为了让,di指向下一文件夹条目

mov si, LoaderFileName; 让si知会字符串文件名称開始处

jmp LABEL_SEARCH_FOR_LOADERBIN;假设字符布匹配,那么跳回到下个文件夹入口開始运行

LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:;假设一个扇区读完了,那么旧跳到下一个扇区去,知道循环完所有的14个扇区

add word [wSectorNo], 1

jmp LABEL_SEARCH_IN_ROOT_DIR_BEGIN

LABEL_NO_LOADERBIN:

mov dh, 2        ;dh是DispStr的參数,相当于字符串数组,用数字来索引字符串

Call DispStr

%ifdef _BOOT_DEBUG_

mov ax, 4c00h

int 21h

%else

jmp $

%endif

LABEL_FILENAME_FOUND:

mov ax, RootDirSectors        ;在接下来的某行里实用,在deltasector那一行

and di, 0FFE0h            ;di原来指向es:di中的文件名称字符串的结尾处,这里两个语句先是让di,指向第一个字符处,add 01ah后指向偏移26字节的地方,也就是fistcul第一个簇,在数据区中

add di, 01Ah

mov cx, word [es:di]        ;把两字节的长度赋值到cx中,也就是loader.bin在数据区的第一个扇区,注意这个并非逻辑扇区,不过簇

push cx

add cx, ax

add cx, DeltaSectorNo        ;deltasector是17用来计算该扇区的位置,如今cx中存的是逻辑扇区号了

mov ax, BaseOfLoader

mov es, ax

mov bx, OffsetOfLoader        ;es:bx如今是之前那个baseofloader:offsetofloader的位置了,用完了,能够覆盖掉了

mov ax, cx                    ;ax如今是第一个数据区的逻辑扇区号

LABEL_GOON_LOADING_FILE:        ;有了loader.bin的第一个逻辑扇区号,如今能够開始载入进内存中了

push ax                        ;暂存ax,bx由于要调用int 10h须要这两个寄存器

push bx

mov ah, 0Eh

mov al, ‘.‘

mov bl, 0Fh

int 10h

pop bx

pop ax                        ;一用完旧恢复这两个寄存器的值,如今ax中的是loader.bin的第一个扇区号

mov cl, 1                    ;參数ax,是逻辑扇区号,cl是要读几个扇区

call    ReadSector            ;调用readsector来读取该扇区的内容,缓冲区为es:bx,刚刚已经初始化过了

;如今開始读取fatentry

pop ax

call GetFATEntry

cmp ax, 0FFFh                ;假设是0fffh旧说明这是最后一簇了

jz LABEL_FILE_LOADED        ;读取完就跳出循环

push ax                        ;还没有读取完loader.bin,这里保存是给下一轮循环的getfatentry作为參数的,这里保存了下一个entry的数值

mov dx, RootDirSectors        ;同一时候这个entry不仅是下一个entry的位置,同一时候也是下一个数据所在的簇号(相应一个扇区,算法为逻辑扇区=簇号+ RootDirSectors + SectorNoofRootDirectory - 2),在这里也就是ax + 14 + 17,

add ax, dx

add ax, DeltaSectorNo        ;到这里旧得到了数据区的扇区,供下一次的readsector来使用

add bx, [BPB_BytesPerSec]    ;bx+512指向下一个空白的地方来存放下一个数据扇区,初始值是offsetofloader

jmp LABEL_GOON_LOADING_FILE

LABEL_FILE_LOADED:                ;假设读取完了loader.bin,那么就让程序跳转到该内存进行指令的运行,如今就開始将控制权交给loader.bin运行了!注意loader.bin就是一个可运行的,里面都是可运行的,所以直接跳转到我们之前用readsector载入到的内存地方就能够了(这个内存是es:bx, 且通过add, [BPB_BytesPerSec], 一直在增长)

mov dh, 1

call DispStr

jmp BaseOfLoader:OffsetOfLoader    ;这个内存如今放的就是loader.binn的程序,如今相当于在运行loader.bin中的代码了

;这个函数用来读取8+4=12结构的fatentry,但眼下给出的是簇数,这个fatentry的内容既是当下一个fatentry的位置,也是相应数据取数据的簇号,也就是第几个12结构,等下要依据奇偶性得出这个12位的入口,可是如今不知道,这个12位的东西也不过存了下一个loader.bin的文件的下一个扇区这个的信息是包括同一文件的下一个扇区的簇数,这个簇数还要计算才干得到逻辑扇区

GetFATEntry:

push es

push bx

push ax        ;es:bx原来的值baseofloader:offsetofloader,ax原来的值是待读取的fatentry也就是8+4=12的那个值,存在fat表中的信息

mov ax, BaseOfLoader

sub ax, 0100h

mov es, ax            ;在baseofloader后面留出4Kb的空间,用来存放fat?什么fat?fat表还是什么东西

pop ax        ;这是ax中的还是待读取的fatentry项,的簇数不是12位的

mov byte [bOdd], 0

mov bx, 3

mul bx            ;这以后ax的值变了,

mov bx, 2

div bx            ;ax的值变成了该fatentry在fat中的偏移量

cmp dx, 0            ;这里dx是dx:ax * 3 /2 的余数,用来推断ax是奇数还是偶数

jz LABEL_EVEN

mov byte [bOdd], 1        ;推断完后ax的值还是没变的,如今知道了奇偶性,也知道了是第几个fatentry,能够開始找到这个fatentry了

LABEL_EVEN:                    ;假设是偶数个

xor dx, dx

mov bx, [BPB_BytesPerSec]    ;每扇区字节数512

div bx                    ;ax是所在扇区号,dx是在该扇区的偏移量

push dx

mov bx, 0                ;es:bx = baseofloader -100: 00

add ax, SectorNoOfFat1        ;ax就是fatentry所在的扇区号了,sectorNooffat1是fat1表所在的第一个扇区号,也就是1

mov cl, 2                ;一次读取两个扇区,由于fat可能会占用两个扇区

call ReadSector

pop dx                    ;dx中存放的是在该扇区的偏移量

add bx, dx                ;ex:bx就是该entry所在的偏移量

mov ax, [es:bx]            ;把entry所在的字读取出来

cmp byte [bOdd], 1        ;依据奇偶进行fatentry内容的筛选

jnz LABEL_EVEN_2        ;假设是奇数旧跳转

shr ax, 4                ;假设是偶数,仅仅取前12位,注意书上的图p130是有错误的,所以获得entry的方法事实上不是非常难~

LABEL_EVEN_2:            ;也就是说是奇数

and ax, 0FFFFh        ;仅仅取后12位

LABEL_GET_FAT_ENTRY_OK:

pop bx

pop es

ret

;刚刚用到的常量

BaseOfLoader    equ 09000h  ;用int 13h得到的缓存区,用来暂存扇区

OffsetOfLoader    equ 0100h

DeltaSectorNo    equ 17        ;用来计算簇号和扇区的关系的

RootDirSectors    equ 14        ;根文件夹占用扇区个数

SectorNoOfRootDirectory    equ 19        ;根文件夹開始的扇区数

SectorNoOfFat1    equ 1

;变量

wRootDirSizeForLoop    dw RootDirSectors        ;控制循环次数的变量

wSectorNo            dw 0                    ;要读的扇区号

bOdd                db 0                    ;奇数还是偶数

;字符串

LoaderFileName        db "LOADER  BIN", 0        ;字符串以0结尾,假设要用,可是为什么要以零结尾呢?

MessageLength        equ 9

BootMessage:        db "Booting  "

Message1            db "Ready.   "

Message2            db "No LOADER"

DispStr:

mov ax, MessageLength

mul dh        ;字符串长度是固定的,索引乘以长度就是字符串的开头

add ax, BootMessage    ;Booting,也就是字符串数组的開始位置

mov bp, ax

mov ax, ds    ;ds被初始化为本程序的開始处

mov es, ax    ;这三个语句确定了串的地址,如今es是程序開始, bp是该字符串開始到该位置的偏移量 es:bp,就是串的地址

;从这里開始为中断int 10准备參数

mov cx, MessageLength ;cx是串的长度

mov ax,01301h

mov bx,0007ch

mov dl,0

int 10h

ret

;要载入loader进入内存必需要读取软盘,由于loader.bin是直接复制到软盘数据区的,所以如今写一个读取软盘的函数,这里仅仅是读软盘数据,依据逻辑扇区读取,等下要写一个寻找loader.bin文件位置的函数

ReadSector:

push bp

mov bp, sp

sub esp, 2

mov byte [bp - 2], cl

push bx

mov bl, [BPB_SecPerTrk]

div bl

inc ah

mov cl, ah

mov dh, al

shr al, 1

mov ch, al

and dh, 1

pop bx

mov dl, [BS_DrvNum]

.GoOnReading:

mov ah, 2

mov al, byte [bp - 2]

int 13h

jc .GoOnReading

add esp, 2

pop bp

ret

times 510-($-$$) db 0

dw 0xaa55

时间: 2024-11-08 18:59:15

自己动手写操作系统 第四章总结的相关文章

Orange's 自己动手写操作系统 第一章 十分钟完成的操作系统 U盘启动 全记录

材料: 1 nasm:编译汇编源代码,网上很多地方有下 2  WinHex:作为windows系统中的写U盘工具,需要是正版(full version)才有写的权限,推荐:http://down.liangchan.net/WinHex_16.7.rar 步骤: 1 编译得到引导程序的机器代码.用命令行编译汇编源代码:name boot.asm -o boot.bin,其中boot.bin文件产生在命令行的当前目录中. 2 将引导程序写入到U盘引导盘的第一个扇区的第一个字节处(后),即主引导区.

读 自己动手写操作系统

用一个月左右的时间读了<自己动手写操作系统>,这是一本让人读着很过瘾,却也特别累的一本书. http://ike.126.com 对操作系统的兴趣由来已久,只是一直未能找到入门之径.操作系统教材是个令人生畏的东西,它可以告诉人有什么,却不能告诉人为什么,从那里了解的操作系统有如盲人摸到的象,得到各个部分,却不能拥有整体,加之缺乏实践的支持,理论显得苍白空洞.如Linux般的开源操作系统,虽然可以让人坐拥全部源码,但一来规模庞大,让人不知从何入手,二来源码背后更多的是业务--操作系统和硬件知识,

自己动手写操作系统 -- 环境搭建

目录: 软件和工具下载 Bochs虚拟机配置文件 Hello World编辑编译 1. 软件和工具下载 Bochs虚拟机下载安装 下载地址: http://download.pchome.net/system/sysenhance/down-19486.html dd for windows下载安装 下载地址: http://www.downxia.com/downinfo/17093.html nasm for windows下载安装 下载地址: http://download.csdn.ne

自己动手写操作系统--个人实践

近期開始看于渊的<自己动手写操作系统>这本书,刚開始看就发现做系统的引导盘居然是软盘!心里那个汗啊! 如今都是U盘了,谁还用软盘.于是考虑用U盘. 于是開始下面步骤: 1.既然书上说给先要把软盘做引导盘,那我就相似地把U盘做成引导盘.在网上找了半天,发现USboot,于是就用它给自己的U盘做了一个引导盘. 2.把编译后的boot.bin文件用绝对扇区工具写入U盘就万事大吉了.相同,在网上找到了winhex(还有ultraiSO,这个没有什么用),但是这个关键的一步,自己不知道如何用winhex

自己动手写操作系统(一)环境准备

参考书籍为<自己动手写操作系统>于渊著 VMware12 centOS7.4.1708 1.bochs安装 首先下载安装包: 下载地址 然后解压,解压命令:sudo tar -zxvf bochs-2.6.9.tar.gz cd命令进入解压目录,先进行配置 配置命令:./configure --enable -debugger --enable-disasm 然后:sudo make 当我执行这一步的时候,报错了 没有Xlib的话就安装一下,这里进行全部安装:yum install libX*

自己动手写操作系统(一)环境准备【转】

转自:https://blog.csdn.net/qq_41785376/article/details/90739557 参考书籍为<自己动手写操作系统>于渊著 VMware12centOS7.4.1708 1.bochs安装首先下载安装包: 下载地址然后解压,解压命令:sudo tar -zxvf bochs-2.6.9.tar.gz cd命令进入解压目录,先进行配置配置命令:./configure --enable -debugger --enable-disasm 然后:sudo ma

自己动手写字符串库函数 四(C语言)

上一篇 自己动手写字符串库函数 三(C语言) //重置 void my_StrSet(string *des, const char ch) { if (!IsEmpty(des)) return; else { char* des1 = des->str; int desLen = my_StrLen(des->str); while (desLen--) *des1++ = ch; } } //插入字符串 void my_InsertStr(string*strs, const char

网络操作系统第四章课后习题解答

1.磁盘的数据结构包括哪些内容? (1)主引导扇区; (2)操作系统引导扇区; (3)文件分配表; (4)目录区; (5)数据区. 2.什么是基本磁盘和动态磁盘? 基本磁盘: 基本磁盘和旧版本Windows操作系统中使用了相同的磁盘结构.在使用基本磁盘时,我们被限制只能在每个磁盘上创建4个主分区或3个主分区加1个扩展分区.在扩展分区内,还可以创建一个或多个逻辑驱动器. 动态磁盘: 动态磁盘功能最初发布于Windows 2000,用于增强磁盘支持,在磁盘配置变动后需要重启动的次数更少,同时对磁盘的

自己动手写操作系统(二)一个最小的“操作系统”

第一步 首先新建一个boot.asm文件,用vim将书中的代码1-1写入文件中,并保存.然后使用nasm编译. 附上代码: org 07c00h mov ax, cs mov ds, ax mov es, ax call DispStr jmp $ DispStr: mov ax, BootMessage mov bp, ax mov cx, 16 mov ax, 01301h mov bx, 000ch mov dl, 0 int 10h ret BootMessage: db "Hello,