`

(第4章 2)突破512字节的限制

 
阅读更多

 

一、代码

     启动的过程中,引导扇区boot sector(boot.asm,07c00h开始,最多512bytes)负责把加载器Loader(loader.asm,长度不受限制)载入内存并且把控制权交给她。Loader再加载操作系统内核之前,还要作准备保护模式等一系列工作,就很可能超过512bytes了。

 

     loader.asm代码在这里只是虚晃一枪,其具体功能编写放在“第五章 内核雏形”,不再赘述。

 

     boot.asm中灰色部分为代码“主线”,基本思路为:

(1)LABEL_SEARCH_IN_ROOT_DIR_BEGIN~~~LABEL_FILENAME_FOUND:在FAT12文件系统的“根目录区”中找到"loader.bin"对应的条目。

   执行后[es:di]指向该条目内部的一个字节,而非条目的开始,根据P105“根目录分区的条目格式”可知,[es:di]指向条目中的位置如下图所示:

                                    [DIR_NAME] [DIR_ATTR] [保         留]  [DIR_WrtTime] [DIR_WrtDate] [DIR_FstClus] [DIR_FileSize]

长度(单位:byte):         8+3                 1                10                        2                          2                           2                      4                  

                                 LOADER_ _BIN      *               **********             **                         **                        **                     ****

                                                                    |

                                                                   di: 是字符'N'后面的那个字节

 

(2)LABEL_FILENAME_FOUND子程序:后面ReadSector中会用到int 13中断读磁盘,故在此准备3个寄存器内容——

ax <-- (全局)扇区号

es <--  BaseOfLoader (09000h)

bx <--  OffsetOfLoader (0100h)

   在ReadSector中,会将(全局)扇区号ax 转换成 “柱面号ch”,“磁头号(即盘面号)dh”,“起始扇区号cl”,从而定位到磁盘上的一个扇区。另外,在ReadSector中另行指定“cl为待读扇区数”。int 13h的2号功能(ah=2)会将磁盘上的这若干个扇区读到[es:bx]开始的内存中。

 

(3)LABEL_GOON_LOADING_FILE~~~jmp BaseOfLoader:OffsetOfLoader之前:注意到根据“根目录区条目”只能找到“loader.bin”在磁盘上的“第一个扇区”,因此本部分在FAT表中顺藤摸瓜地找到loader.bin在磁盘上的“后续所有扇区号(这里也是簇号)”,并通过call ReadSector载入内存。

 

(4)jmp BaseOfLoader:OffsetOfLoader这条指令:(前面已经将磁盘中若干个扇区上的loader.bin文件载入BaseOfLoader:OffsetOfLoader开始的连续内存中了,这里)跳转到loader.bin,将控制权交给loader.bin。在下一章中将分析loader完成的功能——加载OS内核+跳入保护模式。

 

loader.asm

org	0100h

	mov	ax, 0B800h
	mov	gs, ax
	mov	ah, 0Fh				; 0000: 黑底    1111: 白字
	mov	al, 'L'
	mov	[gs:((80 * 0 + 39) * 2)], ax	; 屏幕第 0 行, 第 39 列。

	jmp	$		; Start

   

 

boot.asm

 

;%define_BOOT_DEBUG_; 做 Boot Sector 时一定将此行注释掉!将此行打开后用 nasm Boot.asm -o Boot.com 做成一个.COM文件易于调试

 

%ifdef_BOOT_DEBUG_

org  0100h; 调试状态, 做成 .COM 文件, 可调试

%else

org  07c00h; Boot 状态, Bios 将把 Boot Sector 加载到 0:7C00 处并开始执行

%endif

 

;================================================================================================

%ifdef_BOOT_DEBUG_

BaseOfStackequ0100h; 调试状态下堆栈基地址(栈底, 从这个位置向低地址生长)

%else

BaseOfStackequ07c00h; Boot状态下堆栈基地址(栈底, 从这个位置向低地址生长)

%endif

 

BaseOfLoaderequ09000h; LOADER.BIN 被加载到的位置 ----  段地址

OffsetOfLoaderequ0100h; LOADER.BIN 被加载到的位置 ---- 偏移地址

 

RootDirSectorsequ14; 根目录占用空间

SectorNoOfRootDirectoryequ19; Root Directory 的第一个扇区号

SectorNoOfFAT1equ1; FAT1 的第一个扇区号 = BPB_RsvdSecCnt

DeltaSectorNoequ17; DeltaSectorNo = BPB_RsvdSecCnt + (BPB_NumFATs * FATSz) - 2

; 文件的开始Sector号 = DirEntry中的开始Sector号 + 根目录占用Sector数目 + DeltaSectorNo

;================================================================================================

 

jmp short LABEL_START; Start to boot.

nop; 这个 nop 不可少 ???1为何

 

; 下面是 FAT12 磁盘的头

BS_OEMNameDB 'ForrestY'; OEM String, 必须 8 个字节

BPB_BytsPerSecDW 512; 每扇区字节数

BPB_SecPerClusDB 1; 每簇多少扇区

BPB_RsvdSecCntDW 1; Boot 记录占用多少扇区

BPB_NumFATsDB 2; 共有多少 FAT 表

BPB_RootEntCntDW 224; 根目录文件数最大值(  14扇区 * 512字节/扇区 / 32字节/根目录区条目  )

BPB_TotSec16DW 2880; 逻辑扇区总数 (2880扇区 * 512字节/扇区 = 1.4M 字节 = 一个软盘的容量)

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; 如果 wTotalSectorCount 是 0 由这个值记录扇区数

BS_DrvNum  DB 0; 中断 13 的驱动器号

BS_Reserved1  DB 0; 未使用

BS_BootSig  DB 29h; 扩展引导标记 (29h)

BS_VolID  DD 0; 卷序列号

BS_VolLab  DB 'OrangeS0.02'; 卷标, 必须 11 个字节

BS_FileSysType  DB 'FAT12   '; 文件系统类型, 必须 8个字节  

 

LABEL_START:

mov  ax, cs

mov  ds, ax

mov  es, ax

mov  ss, ax

mov  sp, BaseOfStack

 

; 清屏

mov  ax, 0600h

mov  bx, 0700h

mov  cx, 0

mov  dx, 0184fh

int  10h

 

; 上面清屏用到了BIOS中断  int 10h

; int 10h是BIOS对屏幕及显示器提供的服务程序,
; 功能号AH=6:屏幕初始化或上卷,
; 参数AL=0:屏幕为空白,
; 背景和前景颜色BH = Background Color and Foreground color.
; 矩形区域:左上角(行ch,列cl)=(0,0), 右下角(行dh,列dl)=(0x18,0x4f)=(24, 79)

 

mov  dh, 0          ; "Booting  "

call  DispStr        ; 显示字符串

 

        ;  int 13h is a shorthand for BIOS interrupt call 13h, the 20th interrupt vector in an x86-based computer system. The BIOS typically sets up a real mode interrupt handler at this vector that provides sector-based hard disk and floppy disk read and write services using cylinder-head-sector(CHS) addressing.

        ; Drive Table:

        ;                           DL=00h,  1st floppy disk ("drive A:")

        ;                           DL=01h,  2st floppy disk ("drive B:")

        ;                           DL=80h,  1st hard disk 

        ;                           DL=80h,  2st hard disk

        ; Function Table:

        ;                           AH=00h, Reset Disk Drives

        ;                           AH=01h, Get Status of Last Drive Operation

        ;                           AH=02h, Read Sectors From Drive

        ;                           AH=03h, Write Sectors To Drive

        ; Parameters ...

        ; An interrupt handler, also known as an interrupt service routine (ISR), is a callback subroutine in microcontroller firmware, operating system or device driver whose execution is triggered by the reception of an interrupt.

xor  ah, ah; ┓

xor  dl, dl; ┣ 软驱复位

int  13h; ┛

 

; 下面在 A 盘的根目录寻找 LOADER.BIN

mov  word [wSectorNo], SectorNoOfRootDirectory;根目录分区的第一个扇区号SectorNoOfRootDirectory=19

LABEL_SEARCH_IN_ROOT_DIR_BEGIN:

cmp  word [wRootDirSizeForLoop], 0        ; ┓;根目录分区占用的扇区数wRootDirSizeForLoop

jz  LABEL_NO_LOADERBIN                      ; ┣ 判断根目录区是不是已经读完

dec  word [wRootDirSizeForLoop]             ; ┛ 如果读完表示没有找到 LOADER.BIN

 

 

        ; 从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中

        ; call ReadSector后,[BaseOfLoader:OffsetOfLoader] (即[es:bx]),开始存放根目录分区的一个扇区的数据

mov  ax, BaseOfLoader

mov  es, ax                        ; es <- BaseOfLoader

mov  bx, OffsetOfLoader   ; bx <- OffsetOfLoader于是, es:bx = BaseOfLoader:OffsetOfLoader

 

mov  ax, [wSectorNo]         ; ax <- Root Directory 中的某 Sector 号

mov  cl, 1

call   ReadSector

 

; 比较[ds:si] (即"LOADER BIN")和 [es:di](即根目录区中每个条目中 文件的名称)

mov  si, LoaderFileName; ds:si -> "LOADER  BIN"

mov  di, OffsetOfLoader; es:di -> BaseOfLoader:0100 = BaseOfLoader*10h+100

 

cld

mov  dx, 10h    ; 一个扇区大小/根目录区一个条目大小=512byte/32byte=10h 个 ==> 一个扇区有多少条目

 

LABEL_SEARCH_FOR_LOADERBIN:

cmp  dx, 0                                                                    ; ┓循环次数控制,

jz  LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR    ; ┣如果已经读完了一个 Sector,

dec  dx                                                                         ; ┛就跳到下一个 Sector

 

; 下面(粗体斜体部分)实际上是在检查“一个扇区”中的“一个根目录区条目”中是否有loader.bin这个名称出现

; ∴在这里有两个循环,外层循环挨个读取根目录区的每个扇区,内层循环在指定扇区中挨个读取每个条目。

mov  cx, 11

LABEL_CMP_FILENAME:

cmp  cx, 0

jz  LABEL_FILENAME_FOUND; 如果比较了 11 个字符都相等, 表示找到

dec  cx

lodsb                       ; ds:si -> al

cmp  al, byte [es:di]

jz  LABEL_GO_ON

jmp  LABEL_DIFFERENT; 只要发现不一样的字符就表明本 DirectoryEntry 不是

; 我们要找的 LOADER.BIN

LABEL_GO_ON:

inc  di

jmp  LABEL_CMP_FILENAME;继续循环

 

LABEL_DIFFERENT:             ; 一个根目录区中的条目长20h (bytes),详见P105

and  di, 0FFE0h                                                                   ; else ┓di &= E0 为了让它指向本条目开头

add  di, 20h                                                                          ;        ┃

mov  si, LoaderFileName                                                      ;        ┣ di += 20h  下一个目录条目

jmp  LABEL_SEARCH_FOR_LOADERBIN                            ;        ┛

 

LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:

addword [wSectorNo], 1

jmpLABEL_SEARCH_IN_ROOT_DIR_BEGIN

 

LABEL_NO_LOADERBIN:

mov  dh, 2                                       ; "No LOADER."

call  DispStr                                     ; 显示字符串

 

; 由于上面有这样一句:“jz  LABEL_FILENAME_FOUND”,所以程序不会执行如下的预编译,而直接跳到LABEL_FILENAME_FOUND去 !

%ifdef  _BOOT_DEBUG_

mov  ax, 4c00h                                      ; ┓

int     21h                                               ; ┛没有找到 LOADER.BIN, 回到 DOS

%else

jmp  $                                                     ; 没有找到 LOADER.BIN, 死循环在这里

%endif

 

在找到文件的这一刻[es : di] 指向根目录区中相应条目的DIR_NAME中'N'字母后的那个字符,注意到一个“根目录区的条目”的结构如下:(总共长度为0x20h 即32个字节)

;  名称                             偏移

;  DIR_NAME                    0x0

;  DIR_ATTR                    0xB

;  保留位                           0xC

;  DIR_WrtTime                0x16

;  DIR_WrtDate                0x18

;  DIR_FstClus                  0x1A

;  DIR_FileSize                  0x1C

LABEL_FILENAME_FOUND:                                 ; 找到 LOADER.BIN 后便来到这里继续

mov  ax, RootDirSectors

 

and  di, 0FFE0h                                                    ; di -> 当前条目的开始

add  di, 01Ah                                                         ; di -> 首 Sector

; 此时 [es:di] 指向根目录区条目中LOADER.BIN对应的那个条目的开头(一个条目32字节长度)

 

mov  cx, word [es:di]

push  cx                                                                 ; 保存此 Sector 在 FAT 中的序号

add  cx, ax

add  cx, DeltaSectorNo                                          ; cl <- LOADER.BIN的起始扇区号(0-based)

; 此时的cx = word [es:di] + RootDirSectors + DeltaSectorNo

; word [es:di] ==> LOADER.BIN这个文件在FAT12格式数据区中对应的簇号/扇区号

; RootDirSectors ==> 14, 即根目录区占据的扇区数

; DeltaSectorNo  ==>  19-2, 其中19是根目录区之前的扇区数

 

mov  ax, BaseOfLoader

mov  es, ax                                                             ; es <- BaseOfLoader

mov  bx, OffsetOfLoader                                        ; bx <- OffsetOfLoader

mov  ax, cx                                                             ; ax <- Sector 号

 

LABEL_GOON_LOADING_FILE:

push  ax                                       ; `.

push  bx                                       ;  |

mov  ah, 0Eh                                       ;  | 每读一个扇区就在 "Booting  " 后面

mov  al, '.'                                            ;  | 打一个点, 形成这样的效果:

mov  bl, 0Fh                                        ;  | Booting ......

int  10h;  |

pop  bx                                       ;  |

pop  ax                                       ; /

 

mov  cl, 1

call  ReadSector     ; 从第 ax(相对整个磁盘起始的扇区号) 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中

 

;  此时,ax为当前在FAT中的扇区号/簇号

pop  ax                    ; 取出此 Sector 在 FAT 中的序号

call  GetFATEntry

cmp  ax, 0FFFh

;  此时,ax为下一个要读扇区在FAT中的扇区号/簇号

 

; 下面需要将“FAT中的扇区号/簇号“ax 转换为“在整个磁盘中的扇区号”ax

jz  LABEL_FILE_LOADED

push  ax; 保存 Sector 在 FAT 中的序号

mov  dx, RootDirSectors

add  ax, dx

add  ax, DeltaSectorNo

add  bx, [BPB_BytsPerSec]

jmp  LABEL_GOON_LOADING_FILE

LABEL_FILE_LOADED:

 

mov  dh, 1; "Ready."

call  DispStr; 显示字符串

 

; *****************************************************************************************************

; 这一句正式跳转到已加载到内存中的 LOADER.BIN 的开始处,

; 开始执行 LOADER.BIN 的代码。

; Boot Sector 的使命到此结束

jmpBaseOfLoader:OffsetOfLoader

; *****************************************************************************************************

 

 

 

;============================================================================

;变量

;----------------------------------------------------------------------------

wRootDirSizeForLoopdwRootDirSectors; Root Directory 占用的扇区数, 在循环中会递减至零.

wSectorNodw0; 要读取的扇区号

bOdddb0; 奇数还是偶数

 

;============================================================================

;字符串

;----------------------------------------------------------------------------

LoaderFileNamedb"LOADER  BIN", 0; LOADER.BIN 之文件名

; 为简化代码, 下面每个字符串的长度均为 MessageLength

MessageLengthequ9

BootMessage:db"Booting  "; 9字节, 不够则用空格补齐. 序号 0

Message1db"Ready.   "; 9字节, 不够则用空格补齐. 序号 1

Message2db"No LOADER"; 9字节, 不够则用空格补齐. 序号 2

;============================================================================

 

 

;----------------------------------------------------------------------------

; 函数名: DispStr

;----------------------------------------------------------------------------

; 作用:

;显示一个字符串, 函数开始时 dh 中应该是字符串序号(0-based)

DispStr:

movax, MessageLength

muldh

addax, BootMessage

movbp, ax; ┓

movax, ds; ┣ ES:BP = 串地址

moves, ax; ┛

movcx, MessageLength; CX = 串长度

movax, 01301h; AH = 13,  AL = 01h

movbx, 0007h; 页号为0(BH = 0) 黑底白字(BL = 07h)

movdl, 0

int10h; int 10h

ret

 

 

;----------------------------------------------------------------------------

; 函数名: ReadSector

;----------------------------------------------------------------------------

; 作用:

;从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中

ReadSector:

; -----------------------------------------------------------------------

; 怎样由扇区号求扇区在磁盘中的位置 (扇区号 -> 柱面号, 起始扇区, 磁头号)

; -----------------------------------------------------------------------

; 设扇区号为 x

;                           ┌ 柱面号 = y >> 1

;       x           ┌ 商 y ┤

; -------------- => ┤      └ 磁头号 = y & 1

;  每磁道扇区数     │

;                   └ 余 z => 起始扇区号 = z + 1

pushbp

movbp, sp

subesp, 2; 辟出两个字节的堆栈区域保存要读的扇区数: byte [bp-2]

 

movbyte [bp-2], cl

pushbx; 保存 bx

movbl, [BPB_SecPerTrk]; bl: 除数

divbl; y 在 al 中, z 在 ah 中

incah; z ++

movcl, ah; cl <- 起始扇区号

movdh, al; dh <- y

shral, 1; y >> 1 (其实是 y/BPB_NumHeads, 这里BPB_NumHeads=2)

movch, al; ch <- 柱面号

anddh, 1; dh & 1 = 磁头号

popbx; 恢复 bx

; 至此, "柱面号, 起始扇区, 磁头号" 全部得到 ^^^^^^^^^^^^^^^^^^^^^^^^

movdl, [BS_DrvNum]; 驱动器号 (0 表示 A 盘)

.GoOnReading:

movah, 2; 读

moval, byte [bp-2]; 读 al 个扇区

int13h

jc.GoOnReading; 如果读取错误 CF 会被置为 1, 这时就不停地读, 直到正确为止

 

addesp, 2

popbp

 

ret

 

;----------------------------------------------------------------------------

; 函数名: GetFATEntry

;----------------------------------------------------------------------------

; 作用:

;找到序号为 ax 的 Sector 在 FAT 中的条目, 结果放在 ax 中

;需要注意的是, 中间需要读 FAT 的扇区到 es:bx 处, 所以函数一开始保存了 es 和 bx

GetFATEntry:

pushes

pushbx

pushax

movax, BaseOfLoader; `.

subax, 0100h;  | 在 BaseOfLoader 后面留出 4K 空间用于存放 FAT

moves, ax; /

popax

movbyte [bOdd], 0

movbx, 3

mulbx; dx:ax = ax * 3

movbx, 2

divbx; dx:ax / 2  ==>  ax <- 商, dx <- 余数

cmpdx, 0

jzLABEL_EVEN

movbyte [bOdd], 1

LABEL_EVEN:;偶数

; 现在 ax 中是 FATEntry 在 FAT 中的偏移量,下面来

; 计算 FATEntry 在哪个扇区中(FAT占用不止一个扇区)

xordx, dx

movbx, [BPB_BytsPerSec]

divbx ; dx:ax / BPB_BytsPerSec

  ;  ax <- 商 (FATEntry 所在的扇区相对于 FAT 的扇区号)

  ;  dx <- 余数 (FATEntry 在扇区内的偏移)

pushdx

movbx, 0 ; bx <- 0 于是, es:bx = (BaseOfLoader - 100):00

addax, SectorNoOfFAT1 ; 此句之后的 ax 就是 FATEntry 所在的扇区号

movcl, 2

callReadSector ; 读取 FATEntry 所在的扇区, 一次读两个, 避免在边界

  ; 发生错误, 因为一个 FATEntry 可能跨越两个扇区

popdx

addbx, dx

movax, [es:bx]

cmpbyte [bOdd], 1

jnzLABEL_EVEN_2

shrax, 4

LABEL_EVEN_2:

andax, 0FFFh

 

LABEL_GET_FAT_ENRY_OK:

 

popbx

popes

ret

;----------------------------------------------------------------------------

 

times 510-($-$$)db0; 填充剩下的空间,使生成的二进制代码恰好为512字节

dw 0xaa55; 结束标志

 

 

 

 

二、运行方法

方法一:Linux上装bochs虚拟机,然后在bochs虚拟机中运行(由于有时候bochs很难在Linux上安装成功,因此推荐用方法二)

1. 编译boot.asm和loader.asm

[hadoop@sam1 c]$ pwd

/home/hadoop/Desktop/OSImpl/一个操作系统的实现/chapter4/c

[hadoop@sam1 c]$ ls

a.img  bochsrc  boot.asm  loader.asm  Makefile

[hadoop@sam1 c]$ nasm boot.asm -o boot.bin

[hadoop@sam1 c]$ nasm loader.asm -o loader.bin

 

2. 创建a.img软盘镜像,并将boot.asm写入软盘第一个扇区作为“引导扇区”:

[hadoop@sam1 bochs-2.6]$ bximage

...

Do you want to create a floppy disk image or a hard disk image?

Please type hd or fd. [hd] fd

...

Please type 0.16, 0.18, 0.32, 0.36, 0.72, 1.2, 1.44, 1.68, 1.72, or 2.88.

 [1.44]

...

What should I name the image?

[a.img] 

...

[hadoop@sam1 bochs-2.6]$ dd if=/home/hadoop/Desktop/OSImpl/一个操作系统的实现/chapter4/c/boot.bin of=/home/hadoop/Desktop/OSImpl/bochs-2.6/a.img bs=512 count=1 conv=notrunc

 

 

注:必须要设置从软盘a.img启动,因此修改$bochs_home/.bochsrc为如下:

megs:32

romimage:file=/usr/share/bochs/BIOS-bochs-latest

vgaromimage:file=/usr/share/vgabios/VGABIOS-lgpl-latest.bin

 

#floppya: 1_44=freedos.img, status=inserted

#floppyb: 1_44=pm.img,status=inserted

floppya: 1_44=a.img, status=inserted

 

boot: a

 

#disable the mouse

 

#enable key mapping, using US layout as default.

keyboard_mapping: enabled=1, map=gui/keymaps/x11-pc-us.map

 

mouse: enabled=0

 

log:bochsout.txt

 

3. 把loader.bin作为一个普通的文件写入软盘a.img(当然也可以是其他盘)

[hadoop@sam1 bochs-2.6]$ sudo mount -o loop /home/hadoop/Desktop/OSImpl/bochs-2.6/a.img /mnt/floppy/

[sudo] password for hadoop: 

[hadoop@sam1 bochs-2.6]$ sudo cp /home/hadoop/Desktop/OSImpl/一个操作系统的实现/chapter4/c/loader.bin /mnt/floppy -v

`/home/hadoop/Desktop/OSImpl/一个操作系统的实现/chapter4/c/loader.bin' -> `/mnt/floppy/loader.bin'

[hadoop@sam1 bochs-2.6]$ sudo umount /mnt/floppy/

 

注:mount -o loop —— 

        -o: option

        loop: loop device. loop device is a pseudo('fake') device (actually just a file) that acts as a block-based device.

        (1)loop device 区别于loopback device. Sometimes, the loop device if erroneously referred to as 'loopback' device, but this term is reserved for a networking device in the Linux kernel (cf. loopback). The concept of the 'loop' device is distinct from 'loopback', although similar in name.

        (2)为什么命名为loop呢:在使用之前,一个loop设备必须要和一个文件进行连接,这种结合方式给用户提供了一个代替块特殊文件的接口。如果一个文件包含一个完整的文件系统,那么这个文件就可以像一个磁盘设备一样被mount起来。

             对于第一层文件系统,它直接安装(环绕)在我们的计算机物理设备上;而对于这种被mount起来的镜像文件(它也包含有文件系统),则建立在第一层文件系统上,就好像是在第一层文件系统上再环绕一层文件系统似的,所以称为loop.

 

 

4. 开始模拟

[hadoop@sam1 bochs-2.6]$ ./bochs 

 

结果截图:

 

 

方法二:直接在VMware添加一块硬盘,将boot.bin和loader.bin写到这块盘中,然后从这块盘启动

1. 在VMWare中添加一块硬盘后,给他分区、格式化为FAT12

    ***添加过程如图(注意:新添加的硬盘大小最大为32MB(FAT12格式限制)





 
我在添加新硬盘时,虚拟机是启动着的,需要
#reboot

#fdisk -l                             看到新硬盘没有分区的提示:Disk /dev/sdb doesn't contain a valid partition table
#mkfs.vfat -I -F 12 /dev/sdb      不分区(-I)直接把整块硬盘格式化为FAT12格式

2. 将boot.bin和loader.bin写到这块盘中
#cd /home/hadoop/osimpl/OSImplCode/chapter4/c/
#dd if=boot.bin of=/dev/sdb bs=512 count=1        

#cp loader.bin /dev/sdb

3. 然后从从新添加的硬盘/dev/sdb启动
#reboot

//重启时马上按F2,进入BIOS设置界面

 

效果图:

 

 

 

 

  • 大小: 13.4 KB
  • 大小: 39 KB
  • 大小: 38.6 KB
  • 大小: 37.9 KB
  • 大小: 40.4 KB
  • 大小: 34.5 KB
  • 大小: 25.1 KB
  • 大小: 17.6 KB
分享到:
评论

相关推荐

    VB文本框突破64k限制 #资源达人分享计划#

    8. **第三方控件**:市场上有一些第三方控件,如DevExpress的ASP.NET TextBox,它们可能已经解决了64KB的限制,提供更强大的功能。 9. **使用TextBlock控件**:在VB .NET中,TextBlock控件(WPF的一部分)可以显示...

    第2章 从实模式到保护模式1

    由于计算机启动时仅加载MBR(主引导记录)的前512字节,这不足以承载复杂的操作,因此需要bootloader来突破这个限制。bootloader没有512字节的限制,可以加载到内存的任意位置,并负责执行从实模式到保护模式的转换...

    自己动手写操作系统

    4.1 突破512字节的限制125 4.1.1 FAT12126 4.1.2 DOS可以识别的引导盘131 4.1.3 一个最简单的Loader132 4.1.4 加载Loader入内存133 4.1.5 向Loader交出控制权142 4.1.6 整理boot.asm142 4.2 保护模式下的...

    硬盘分区表

    5. **分区类型字节(sys_ind)**:位于第4字节,用于区分不同类型的分区,例如0x0b代表DOS分区,0x80代表旧版Minix分区,0x83代表Linux分区等。 6. **结束磁头号(end_head)**:位于第5字节,标识分区结束位置的...

    行业分类-设备装置-基于JAVA字节码插桩和JAVA方法挂钩检测JAVA沙箱逃逸攻击.zip

    Java沙箱逃逸攻击是指恶意代码试图突破Java安全模型的限制,获取系统级权限或执行非授权操作的行为。为了防止这种攻击,开发者可以利用Java字节码插桩和方法挂钩技术来增强应用的安全性。本文将深入探讨这两种技术...

    FAT16和FAT32文件格式说明

    它通过使用32位(4字节)的簇号来突破FAT16的2GB限制。 ##### 1. **FAT32基本结构** FAT32文件系统的结构与FAT16类似,但具有以下特点: - **DBR及保留扇区**:同FAT16,包含了BPB参数块等重要信息。 - **FAT1**...

    自己动手写操作系统 电子工业出版社 pdf

    4.1 突破512字节的限制125 4.1.1 FAT12126 4.1.2 DOS可以识别的引导盘131 4.1.3 一个最简单的Loader132 4.1.4 加载Loader入内存133 4.1.5 向Loader交出控制权142 4.1.6 整理boot.asm142 4.2 保护模式下的“操作系统...

    GPT与MBr详解与区别

    MBR 占用了硬盘的第一个扇区(通常是 512 字节),其中包含了引导程序和分区表。在这 512 字节中,446 字节用于存放引导代码,64 字节用于存储分区信息。由于 MBR 只允许存在最多四个主分区或三个主分区加一个扩展...

    MBR操作

    这是因为分区大小是由4个字节表示的,而早期的硬盘寻址方式(CHS)的限制导致了这一问题。 为了突破这一限制,引入了扩展分区的概念。通过扩展分区,可以在其内部创建逻辑驱动器(Logical Drives),从而实现对大...

    自己动手写操作系统 pdf

    4.1 突破512字节的限制125 4.1.1 FAT12126 4.1.2 DOS可以识别的引导盘131 4.1.3 一个最简单的Loader132 4.1.4 加载Loader入内存133 4.1.5 向Loader交出控制权142 4.1.6 整理boot.asm142 4.2 保护模式下的“操作系统...

    Discuz! X2.5论坛标题字数突破80的限制实现思路

    为了解决这个问题,用户可以按照以下步骤来突破这个限制,将其扩展到120个字符: 1. **数据库修改**: 首先,你需要进入数据库管理工具,例如phpMyAdmin,找到与论坛相关的三个表:`pre_forum_post`、`pre_forum_...

    MBR、主引导扇区,主分区、扩展分区、逻辑分区,活动分区、引导分区、系统分区、启动分区的区别详解【讲的很清晰】

    MBR,全称Master Boot Record,是硬盘的主引导记录,位于0号柱面、0号磁头的第一个扇区,占用512字节,其中446字节存放引导程序,64字节为分区表DPT,最后2字节为结束标志55AA。MBR的作用在于检测硬盘分区的合法性并...

    1.13c完美255s教程.pdf

    为支持255个镶嵌物,作者利用了物品code的特性,借用前面4个字节的高bit,以及可能的第四个字节的额外位。需要注意的是,物品code的ASCII码需保持在0x80以下,且当mod物品的code达到4字节时,最后一个字节不应超过0x...

    硬盘主引导扇区(MBR、DPT、DBR、BPB)详解

    主引导扇区,简称MBR,是硬盘的第一个扇区,位于0柱面、0磁道、1扇区的位置,占据512字节的空间。MBR中包含有系统引导程序和磁盘分区表。当计算机启动时,BIOS会读取MBR中的引导代码,执行引导过程。如果MBR损坏或被...

    FAT文件系统 (中文版)

    到了Windows系统时代,FAT文件系统随着硬盘容量的不断增长而进化出FAT32版本,它通过使用32位的文件分配表,突破了FAT16的容量限制,能够支持高达2TB(2 Terabytes)的存储分区,尽管实际使用时存在一些限制。...

    扩展int13h调用详解.pdf

    为了解决基本Int13H调用仅能访问8GB硬盘空间的问题,微软等公司制定了扩展Int13H标准,采用线性寻址的方式访问硬盘,突破了8GB的容量限制,并且增加了对可拆卸介质的支持。 #### 二、Boot Sector结构简介 ##### 1....

    自己动手写操作系统(含源代码).part2

    经过四年的磨练成长,于渊又拿出第二版的书稿《Orange'S:一个操作系统的实现》,这本书是属于真正 Hacker的。我虽然已经有多年不写代码了,但看这本书的时候,让我又重新感受到做程序员的乐趣:用代码建设属于自己...

    windows磁盘文件系统

    为了解决这一问题,硬盘厂商引入了新的INT13服务扩展标准,使用64位LBA(Logical Block Addressing)地址,来扩展硬盘寻址能力,从而突破了原有的限制。 总的来说,Windows磁盘文件系统是由多个组成部分构成的复杂...

Global site tag (gtag.js) - Google Analytics