如何知道扇区存储的文件名_历史性的一跳 从启动扇区跳转到 loader

本文详细介绍了如何通过BIOS中断读取软盘,实现从启动扇区跳转到Loader,从而加载并执行自定义的操作系统程序。文章涵盖了复位软盘、读取软盘扇区、解析FAT项、创建Loader Demo以及将控制权交给Loader的全过程。
摘要由CSDN通过智能技术生成

1. 引言

上一篇文章中,我们详细介绍了 FAT12 文件系统的构成,并且在 linux 环境下构建了我们自己的软盘,虽然这在此前我们已经实现过了很多次。
实战 FAT12 文件系统

本文,我们就来通过上述原理,实现软盘读取,并且加载并让我们的启动盘跳转进入到软盘上文件所写的程序。
这样,我们就终于可以和长期以来伴随我们的 freedos 系统说再见了,终于可以使用原生的 bochs 调试功能了,再也不用使用蹩脚的 magic break 了。

2. 通过 BIOS 中断读取软盘

BIOS 中断对我们来说已经不陌生了,我们曾经使用过 10H 号中断来实现一个字符串的打印。
BIOS 的 13H 号中断就是用来操作软盘的,他通过触发时寄存器的值,实现了下面两个功能。

2.1. 复位软盘

触发时,如果 ah = 0,dl 为 驱动器号,则中断将造成软驱复位。

2.2. 读取软盘

触发时,如果寄存器值如下,则读取相应数据到 es:bx 缓冲区中:

  • ah = 02h
  • al = 读取扇区数
  • ch = 柱面/磁道号
  • cl = 起始扇区号
  • dh = 磁头号
  • dl = 驱动器号
  • es:bx = 数据缓冲区

2.3. 通过扇区号计算柱面号与磁头号

根据上一篇文章中介绍的原理,我们可以知道,对于一个 1.44M 的软盘来说,总共有两个盘面,每面 80 个磁道,每个磁道 18 个扇区,因此 2  18  80 * 512 = 1.44M。
那么,如何获取柱面号、磁头号、盘片起始扇区号呢,根据上面的原理,也很简单:

柱面号 = 扇区号 / 每磁道扇区数 / 2
磁头号 = 扇区号 / 每磁道扇区数 & 1
起始扇区号 = 扇区号 % 每磁道扇区数 + 1

2.4. 通过汇编程序读取软盘扇区

下面的函数实现了一个软盘指定数量扇区的读取:

; ----- 从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中 -----  
ReadSector:
push bp
mov bp, sp
sub esp, 2 ; 开辟两个字节的堆栈区域保存要读的扇区数: byte [bp-2]

mov byte [bp-2], cl
push bx
mov bl, [BPB_SecPerTrk] ; bl: 每磁道扇区数
div bl ; 商保存在 al 中,余数保存在 ah 中
inc ah ; 获取其实扇区号
mov cl, ah ; cl mov dh, al shr al, 1 ; 获取柱面号 mov ch, al ; ch and dh, 1 ; 获取磁头号 pop bx mov dl, [BS_DrvNum] ; 驱动器号 (0 表示 A 盘) .GoOnReading: mov ah, 2 ; 读 mov al, byte [bp-2] ; 读 al 个扇区 int 13h jc .GoOnReading ; 如果读取错误 CF 会被置为 1, 这时就不停地读, 直到正确为止 add esp, 2 pop bp ret

3. 软盘数据的读取

通过上面的 ReadSector 函数,我们已经可以实现软盘上一个指定扇区的读取了,但是,一个文件只要大于 512 字节,就会被存储在多个扇区上,此时我们就需要去解析 FAT 扇区中存储的 FAT 项,从而循环跳转到下一个存储文件内容的扇区中,最终实现整个文件的读取。

14b7ccc2e99be830a243a40c7a3ba888.png

如上图所示,FAT 项存在一个问题,那就是他是 12 字节的,我们每次读取一个字节的话,要读取三次才能取到两个 FAT 项,因此解析起来存在一定的复杂性。
下面的函数实现了指定 FAT 项的读取,结果存放在 ax 中:

GetFATEntry:  
push es
push bx
push ax

; 在 BaseOfLoader 后面留出 4K 空间用于存放 FAT
mov ax, BaseOfLoader
sub ax, 0100h
mov es, ax

; 判断 ax 奇偶性,赋值 bOdd 变量
pop ax
mov byte [bOdd], 0 ; bOdd 变量用于存放当前是奇数次读取还是偶数次读取
mov bx, 3
mul bx ; dx:ax = ax * 3
mov bx, 2
div bx ; dx:ax / 2 ==> ax cmp dx, 0 jz LABEL_EVEN mov byte [bOdd], 1 ; 奇数
LABEL_EVEN: ; 计算 FAT 项所在扇区号 xor dx, dx mov bx, [BPB_BytsPerSec] div bx ; dx:ax / BPB_BytsPerSec ; ax ; dx push dx mov bx, 0 ; bx add ax, SectorNoOfFAT1 ; ax = FAT1 起始扇区号 + 指定读取扇区号 = FATEntry 所在的扇区号 mov cl, 2 call ReadSector ; 读取 FATEntry 所在的扇区, 一次读两个 ; 赋值结果给 ax 并矫正结果 pop dx add bx, dx mov ax, [es:bx] cmp byte [bOdd], 1 jnz LABEL_EVEN_2 shr ax, 4 LABEL_EVEN_2: and ax, 0FFFh
LABEL_GET_FAT_ENRY_OK: pop bx pop es ret

4. 创建 loader demo

我们在系列之初,就完成了一个启动盘的创建,输出了 hello world 字符串:
实现一个操作系统

那么,接下来我们要做的就是创建一个 loader.bin 程序,让我们的启动程序找到并加载 loader.bin,由 loader.bin 负责拉起我们后面要写的操作系统。

4.1. loader demo

由于启动程序一旦将控制权交给 loader.bin,loader 就不再受任何限制,我们就可以自由的编写我们所需要的 loader 程序了,因此,本文我们重点在启动程序将控制权交给 loader 的过程,因此 loader 只要能显示一行字符串就可以了。

org    0100h  
mov ax, cs
mov ds, ax
mov di, (80*3 + 2) * 2 ; 屏幕第 3 行, 第 2 列
mov ax, 0B800h
mov gs, ax
mov ah, 0Fh ; 0000: 黑底 1111: 白字
mov si, BootMessage
xor cx, cx
mov cl, byte [MessageLength]
print_loop:
lodsb
mov [gs:di], ax
add bl, 1
add di, 2
loop print_loop

jmp $

BootMessage: db "techlog loader"
MessageLength: db $-BootMessage

4.2. 放入软盘

通过上一篇文章中所介绍的,我们直接通过命令将编译后的 loader.bin 放入软盘即可:

nasm -o loader.bin loader.asm
mount -o loop boot.img /mnt/floppy
cp loader.bin /mnt/floppy
umount /mnt/floppy

5. 让启动程序找到 loader demo

5.1. 复位软驱

首先,我们要执行复位中断,复位软驱:

xor    ah, ah  
xor dl, dl
int 13h

5.2. 循环读取根目录区找到元信息

接下来,我们要循环读取根目录区,找到 loader.bin 在根目录区中的元数据信息:

; 在根目录区寻找 LOADER.BIN  
; wSectorNo 为根目录区扇区号,初始为 19
mov word [wSectorNo], SectorNoOfRootDirectory
LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
; 根目录区已读完,则说明未找到
cmp word [wRootDirSizeForLoop], 0
jz LABEL_NO_LOADERBIN
dec word [wRootDirSizeForLoop]

; 读取扇区
mov ax, BaseOfLoader
mov es, ax
mov bx, OffsetOfLoader
mov ax, [wSectorNo]
mov cl, 1
call ReadSector

mov si, LoaderFileName ; ds:si = "LOADER BIN"
mov di, OffsetOfLoader ; es:di = BaseOfLoader:0100
cld ; df = 0

; 循环读取目录条目
mov dx, 10h ; 当前扇区所有目录条目循环次数
LABEL_SEARCH_FOR_LOADERBIN:
; 循环结束,已完成当前扇区目录条目读取
cmp dx, 0
jz LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR
dec dx

; 比较目录条目中 DIR_Name 是否与 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 ; 字符不同,说明当前非目录条目
LABEL_GO_ON:
inc di
jmp LABEL_CMP_FILENAME

; 非当前条目,跳至下一条目
LABEL_DIFFERENT:
and di, 0FFE0h ; 让 es:di 指向当前条目起始位置
add di, 20h ; 跳至下一条目
mov si, LoaderFileName
jmp LABEL_SEARCH_FOR_LOADERBIN

; 非当前扇区,跳至下一扇区
LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
add word [wSectorNo], 1
jmp LABEL_SEARCH_IN_ROOT_DIR_BEGIN

; 未找到,终止流程
LABEL_NO_LOADERBIN:
mov dh, 2 ; "No LOADER."
call DispStr ; 显示字符串
jmp $

; 找到 loader.bin,继续流程
LABEL_FILENAME_FOUND:

5.3. 获取文件在数据区中起始扇区号

; 获取 loader.bin 对应的数据区簇号,保存在栈中  
and di, 0FFE0h ; di = 当前条目起始位置
add di, 01Ah ; es:di 指向 DIR_FstClus,对应数据区簇号
mov cx, word [es:di]
push cx

; 获取文件所在扇区号,保存在 cx 中
mov ax, RootDirSectors ; 根目录扇区数
add cx, ax ; 因为 BPB_SecPerClus 为 1,每簇 1 扇区
add cx, DeltaSectorNo ; 所以,文件所在扇区号 = 根目录起始扇区号 + 根目录扇区数 + 文件数据区簇号 - 2

5.4. 读取文件并载入内存

现在,我们已经有了文件在数据区中的起始扇区号,通过 FAT 区中的 FAT 项,我们就可以递归获取整个文件了。

    ; es:bx = loader.bin 将要被加载到的内存物理地址  
mov ax, BaseOfLoader
mov es, ax
mov bx, OffsetOfLoader

; 循环读取 loader.bin
mov ax, cx ; ax LABEL_GOON_LOADING_FILE: ; 打点,表示准备读取一个扇区,展示 Booting.... push ax push bx mov ah, 0Eh mov al, '.' mov bl, 0Fh int 10h pop bx pop ax mov cl, 1 call ReadSector pop ax ; 取出此 Sector 在 FAT 中的序号 call GetFATEntry ; 读取 FAT 项值 cmp ax, 0FFFh ; 判断是否完成读取 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 ; 显示字符串

6. 将控制权交给 loader

既然整个 loader.bin 已经被加载到了内存中,那么,我们只需要通过一个跳转指令,跳转到被加载到内存的起始地址,就可以完成控制权的转移,也就是开始 loader 的执行了:

jmp    BaseOfLoader:OffsetOfLoader

7. 程序运行结果

运行我们的镜像,可以看到:

71701d46ed4946e741ce58c54e62e566.png

8. 加载其他 loader

本文重点就在于我们对启动程序的修改,loader 其实并不重要,也就是说,我们可以把此前我们写过的任何程序作为 loader.bin 来启动。
下面是之前中断相关文章的 demo 演示:

315a298e61db6b7c22bfeba18ffaa331.png

9. 微信公众号

欢迎关注微信公众号,以技术为主,涉及历史、人文等多领域的学习与感悟,每周三到七篇推文,只有全部原创,只有干货没有鸡汤。

99069fee01646dfcc29243b7e49d9886.png

10. 附录 — 完整代码

10.1. Makefile

BOOT:=boot.asm  
LDR:=loader.asm
IDTLDR:=protect.asm
BOOT_BIN:=$(subst .asm,.bin,$(BOOT))
LDR_BIN:=$(subst .asm,.bin,$(LDR))

IMG:=boot.img
FLOPPY:=/mnt/floppy/

.PHONY : everything

everything : $(BOOT_BIN) $(LDR_BIN)
# bximg
dd if=$(BOOT_BIN) of=$(IMG) bs=512 count=1 conv=notrunc
sudo mount -o loop $(IMG) $(FLOPPY)
sudo cp $(LDR_BIN) $(FLOPPY) -v
sudo umount $(FLOPPY)

clean :
rm -f $(BOOT_BIN) $(LDR_BIN)

$(BOOT_BIN) : $(BOOT)
nasm $< -o $@

$(LDR_BIN) : $(LDR)
nasm $< -o $@

idt:
nasm boot.asm -o boot.bin
nasm protect.asm -o loader.bin
dd if=$(BOOT_BIN) of=$(IMG) bs=512 count=1 conv=notrunc
sudo mount -o loop $(IMG) $(FLOPPY)
sudo cp $(LDR_BIN) $(FLOPPY) -v
sudo umount $(FLOPPY)

10.2. loader.asm

org    0100h  
mov ax, cs
mov ds, ax
mov di, (80*3 + 2) * 2 ; 屏幕第 3 行, 第 39 列
mov ax, 0B800h
mov gs, ax
mov ah, 0Fh ; 0000: 黑底 1111: 白字
mov si, BootMessage
xor cx, cx
mov cl, byte [MessageLength]
print_loop:
lodsb
mov [gs:di], ax
add bl, 1
add di, 2
loop print_loop

jmp $

BootMessage: db "techlog loader"
MessageLength: db $-BootMessage

10.3. boot.asm

org  07c00h  

BaseOfStack equ 07c00h ; Boot状态下堆栈基地址(栈底, 从这个位置向低地址生长)
BaseOfLoader equ 09000h ; LOADER.BIN 被加载段地址
OffsetOfLoader equ 0100h ; LOADER.BIN 被加载偏移地址

RootDirSectors equ 14 ; 根目录区扇区数
SectorNoOfRootDirectory equ 19 ; Root Directory 的第一个扇区号
SectorNoOfFAT1 equ 1 ; FAT1 的第一个扇区号 = BPB_RsvdSecCnt
DeltaSectorNo equ 17 ; 用于计算文件的开始扇区号 BPB_RsvdSecCnt + (BPB_NumFATs * FATSz) - 2

jmp short LABEL_START ; Start to boot.
nop ; jmp 语句 3 字节,nop 补足 4 字节

; FAT12 磁盘头
BS_OEMName DB 'ForrestY' ; OEM String, 8 字节
BPB_BytsPerSec 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 ; 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 ; AH = 6, AL = 0h
mov bx, 0700h ; 黑底白字(BL = 07h)
mov cx, 0 ; 左上角: (0, 0)
mov dx, 0184fh ; 右下角: (80, 50)
int 10h

mov dh, 0
call DispStr

; 复位软驱
xor ah, ah
xor dl, dl
int 13h

; 在根目录区寻找 LOADER.BIN
; wSectorNo 为根目录区扇区号,初始为 19
mov word [wSectorNo], SectorNoOfRootDirectory
LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
; 根目录区已读完,则说明未找到
cmp word [wRootDirSizeForLoop], 0
jz LABEL_NO_LOADERBIN
dec word [wRootDirSizeForLoop]

; 读取扇区
mov ax, BaseOfLoader
mov es, ax
mov bx, OffsetOfLoader
mov ax, [wSectorNo]
mov cl, 1
call ReadSector

mov si, LoaderFileName ; ds:si = "LOADER BIN"
mov di, OffsetOfLoader ; es:di = BaseOfLoader:0100
cld ; df = 0

; 循环读取目录条目
mov dx, 10h ; 当前扇区所有目录条目循环次数
LABEL_SEARCH_FOR_LOADERBIN:
; 循环结束,已完成当前扇区目录条目读取
cmp dx, 0
jz LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR
dec dx

; 比较目录条目中 DIR_Name 是否与 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 ; 字符不同,说明当前非目录条目
LABEL_GO_ON:
inc di
jmp LABEL_CMP_FILENAME

; 非当前条目,跳至下一条目
LABEL_DIFFERENT:
and di, 0FFE0h ; 让 es:di 指向当前条目起始位置
add di, 20h ; 跳至下一条目
mov si, LoaderFileName
jmp LABEL_SEARCH_FOR_LOADERBIN

; 非当前扇区,跳至下一扇区
LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
add word [wSectorNo], 1
jmp LABEL_SEARCH_IN_ROOT_DIR_BEGIN

; 未找到,终止流程
LABEL_NO_LOADERBIN:
mov dh, 2 ; "No LOADER."
call DispStr ; 显示字符串
jmp $

; 找到 loader.bin,继续流程
LABEL_FILENAME_FOUND:
; 获取 loader.bin 对应的数据区簇号,保存在栈中
and di, 0FFE0h ; di = 当前条目起始位置
add di, 01Ah ; es:di 指向 DIR_FstClus,对应数据区簇号
mov cx, word [es:di]
push cx

; 获取文件所在扇区号,保存在 cx 中
mov ax, RootDirSectors ; 根目录扇区数
add cx, ax ; 因为 BPB_SecPerClus 为 1,每簇 1 扇区
add cx, DeltaSectorNo ; 所以,文件所在扇区号 = 根目录起始扇区号 + 根目录扇区数 + 文件数据区簇号 - 2

; es:bx = loader.bin 将要被加载到的内存物理地址
mov ax, BaseOfLoader
mov es, ax
mov bx, OffsetOfLoader

; 循环读取 loader.bin
mov ax, cx ; ax LABEL_GOON_LOADING_FILE: ; 打点,表示准备读取一个扇区,展示 Booting.... push ax push bx mov ah, 0Eh mov al, '.' mov bl, 0Fh int 10h pop bx pop ax mov cl, 1 call ReadSector pop ax ; 取出此 Sector 在 FAT 中的序号 call GetFATEntry ; 读取 FAT 项值 cmp ax, 0FFFh ; 判断是否完成读取 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 ; 显示字符串 jmp BaseOfLoader:OffsetOfLoader ; 跳转到已加载到内 ; -------------------------- 变量 --------------------------------
wRootDirSizeForLoop dw RootDirSectors ; Root Directory 占用的扇区数, 在循环中会递减至零.
wSectorNo dw 0 ; 要读取的扇区号
bOdd db 0 ; 奇数还是偶数
LoaderFileName db "LOADER BIN", 0 ; LOADER.BIN 之文件名 ; 为简化代码, 下面每个字符串的长度均为 MessageLength
MessageLength equ 9 BootMessage: db "Booting " ; 9字节, 不够则用空格补齐. 序号 0
Message1 db "Ready. " ; 9字节, 不够则用空格补齐. 序号 1
Message2 db "No LOADER" ; 9字节, 不够则用空格补齐. 序号 2 ; ---- 显示一个字符串, 函数开始时 dh 中应该是字符串序号(0-based) ---- DispStr: mov ax, MessageLength mul dh add ax, BootMessage mov bp, ax ; ┓ mov ax, ds ; ┣ ES:BP = 串地址 mov es, ax ; ┛ mov cx, MessageLength ; CX = 串长度 mov ax, 01301h ; AH = 13, AL = 01h mov bx, 0007h ; 页号为0(BH = 0) 黑底白字(BL = 07h) mov dl, 0 int 10h ; int 10h ret ; ----- 从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中 ----- ReadSector: push bp mov bp, sp sub esp, 2 ; 开辟两个字节的堆栈区域保存要读的扇区数: byte [bp-2] mov byte [bp-2], cl push bx mov bl, [BPB_SecPerTrk] ; bl: 每磁道扇区数 div bl ; 商保存在 al 中,余数保存在 ah 中 inc ah ; 获取其实扇区号 mov cl, ah ; cl mov dh, al shr al, 1 ; 获取柱面号 mov ch, al ; ch and dh, 1 ; 获取磁头号 pop bx mov dl, [BS_DrvNum] ; 驱动器号 (0 表示 A 盘) .GoOnReading: mov ah, 2 ; 读 mov al, byte [bp-2] ; 读 al 个扇区 int 13h jc .GoOnReading ; 如果读取错误 CF 会被置为 1, 这时就不停地读, 直到正确为止 add esp, 2 pop bp ret ; ---- 读取序号为 ax 的 Sector 在 FAT 中的条目, 放在 ax 中 ---- GetFATEntry: push es push bx push ax ; 在 BaseOfLoader 后面留出 4K 空间用于存放 FAT mov ax, BaseOfLoader sub ax, 0100h mov es, ax ; 判断 ax 奇偶性,赋值 bOdd 变量 pop ax mov byte [bOdd], 0 ; bOdd 变量用于存放当前是奇数次读取还是偶数次读取 mov bx, 3 mul bx ; dx:ax = ax * 3 mov bx, 2 div bx ; dx:ax / 2 ==> ax cmp dx, 0 jz LABEL_EVEN mov byte [bOdd], 1 ; 奇数
LABEL_EVEN: ; 计算 FAT 项所在扇区号 xor dx, dx mov bx, [BPB_BytsPerSec] div bx ; dx:ax / BPB_BytsPerSec ; ax ; dx push dx mov bx, 0 ; bx add ax, SectorNoOfFAT1 ; ax = FAT1 起始扇区号 + 指定读取扇区号 = FATEntry 所在的扇区号 mov cl, 2 call ReadSector ; 读取 FATEntry 所在的扇区, 一次读两个 ; 赋值结果给 ax 并矫正结果 pop dx add bx, dx mov ax, [es:bx] cmp byte [bOdd], 1 jnz LABEL_EVEN_2 shr ax, 4 LABEL_EVEN_2: and ax, 0FFFh
LABEL_GET_FAT_ENRY_OK: pop bx pop es ret times 510-($-$$) db 0 ; 填充剩余空间,使生成的二进制代码恰好为512字节 dw 0xaa55 ; 结束标志

10.4. bochsrc.bxrc

###############################################################  
# Configuration file for Bochs  
###############################################################  

# how much memory the emulated machine will have  
megs: 32  

# filename of ROM images  
romimage: file=$BXSHARE/BIOS-bochs-latest  
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest  
vga: extension=vbe, update_freq=15  

magic_break: enabled=1  

# what disk images will be used  
floppya: 1_44=boot.img, status=inserted  

# choose the boot disk.  
boot: a  
# log: stdout.log  

# enable key mapping, using US layout as default.  
keyboard: keymap=$BXSHARE/keymaps/x11-pc-us.map  
mouse: enabled=1  
mouse: type=imps2, enabled=1  
mouse: type=serial, enabled=1  
mouse: enabled=0, toggle=ctrl+f10  

magic_break: enabled=1

11. 附录 — 系列目录

实现一个操作系统

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值