要在MBR的64字节分区表(偏移0x1BE-0x1FD)中设置主分区信息,需遵循分区条目结构规范(每个主分区占16字节),并通过汇编指令逐字段构造分区参数。以下是完整实现步骤与代码:
一、前置知识:MBR分区表结构
MBR的分区表位于自身偏移0x1BE处(即加载到内存0x7C00后,分区表地址为0x7C00+0x1BE=0x7DDE),包含4个主分区条目(每个16字节),或3主分区+1扩展分区。每个主分区条目字段如下(小端序):
| 偏移(相对于分区表) | 字段含义 | 说明 |
|---|---|---|
| 0 | 引导标志(Boot Indicator) | 0x80=活动分区(可引导),0x00=非活动 |
| 1 | 起始磁头(Starting Head) | 磁头号(0-255) |
| 2 | 起始扇区(Starting Sector) | 扇区号(低6位,1-63) |
| 3 | 起始柱面(Starting Cylinder) | 柱面号(高2位来自偏移2,低8位来自偏移3,共10位) |
| 4 | 系统类型(System Type) | 文件系统标识(如0x0B=FAT32,0x83=EXT4,0x07=NTFS) |
| 5 | 结束磁头(Ending Head) | 结束磁头号 |
| 6 | 结束扇区(Ending Sector) | 结束扇区号(低6位) |
| 7 | 结束柱面(Ending Cylinder) | 结束柱面号(高2位来自偏移6,低8位来自偏移7) |
| 8-11 | 起始LBA(Starting LBA) | 分区第一个扇区的线性地址(4字节,小端序) |
| 12-15 | 扇区总数(Sector Count) | 分区包含的扇区数(4字节,小端序) |
二、汇编代码实现:设置主分区
以下代码将两个主分区信息写入MBR分区表:
- 分区1:活动分区,FAT32文件系统,起始LBA
0x2000(硬盘第131072扇区),大小0x1000扇区(512KB); - 分区2:非活动分区,EXT4文件系统,起始LBA
0x3000,大小0x2000扇区(1MB)。
1. 定义关键常量
org 0x7C00 ; MBR加载到内存0x7C00(必须)
bits 16 ; 实模式汇编
; 定义MBR内部分区表地址(0x7C00 + 0x1BE = 0x7DDE)
mbroffset equ 0x7C00
partition_table equ mbroffset + 0x1BE
2. 设置分区表
逐字段构造两个主分区的16字节条目:
; ------------------- 分区1:活动分区(FAT32) -------------------
; 引导标志:活动(0x80)
mov byte [partition_table + 0], 0x80
; 起始磁头:0
mov byte [partition_table + 1], 0x00
; 起始扇区:0x10(低6位),起始柱面高2位:0 → 起始柱面0x000
mov byte [partition_table + 2], 0x10
; 起始柱面低8位:0
mov byte [partition_table + 3], 0x00
; 系统类型:FAT32(0x0B)
mov byte [partition_table + 4], 0x0B
; 结束磁头:0
mov byte [partition_table + 5], 0x00
; 结束扇区:0x10,结束柱面高2位:0 → 结束柱面0x000
mov byte [partition_table + 6], 0x10
; 结束柱面低8位:0
mov byte [partition_table + 7], 0x00
; 起始LBA:0x00002000(小端序:低字节在前)
mov byte [partition_table + 8], 0x00 ; LBA低字节(2^0)
mov byte [partition_table + 9], 0x20 ; LBA中字节(2^8)
mov byte [partition_table + 10], 0x00 ; LBA高字节(2^16)
mov byte [partition_table + 11], 0x00 ; LBA最高字节(2^24)
; 扇区总数:0x00001000(4096扇区,小端序)
mov byte [partition_table + 12], 0x00
mov byte [partition_table + 13], 0x10
mov byte [partition_table + 14], 0x00
mov byte [partition_table + 15], 0x00
; ------------------- 分区2:非活动分区(EXT4) -------------------
; 引导标志:非活动(0x00)(偏移partition_table+16)
mov byte [partition_table + 16], 0x00
; 起始磁头:0
mov byte [partition_table + 17], 0x00
; 起始扇区:0x20,起始柱面高2位:0 → 起始柱面0x000
mov byte [partition_table + 18], 0x20
; 起始柱面低8位:0
mov byte [partition_table + 19], 0x00
; 系统类型:EXT4(0x83)
mov byte [partition_table + 20], 0x83
; 结束磁头:0
mov byte [partition_table + 21], 0x00
; 结束扇区:0x20,结束柱面高2位:0 → 结束柱面0x000
mov byte [partition_table + 22], 0x20
; 结束柱面低8位:0
mov byte [partition_table + 23], 0x00
; 起始LBA:0x00003000(小端序)
mov byte [partition_table + 24], 0x00
mov byte [partition_table + 25], 0x30
mov byte [partition_table + 26], 0x00
mov byte [partition_table + 27], 0x00
; 扇区总数:0x00002000(8192扇区,小端序)
mov byte [partition_table + 28], 0x00
mov byte [partition_table + 29], 0x20
mov byte [partition_table + 30], 0x00
mov byte [partition_table + 31], 0x00
3. 验证与补充
- 分区表完整性:若需设置4个主分区,重复上述逻辑填充
partition_table+32(第三个分区)和partition_table+48(第四个分区)。 - MBR签名:最后需确保MBR末尾添加
0xAA55签名(通常在代码末尾用times指令填充):times 512 - ($ - $$) db 0 ; 填充剩余字节为0 dw 0xAA55 ; MBR必须的签名
三、编译与测试
1. 编译MBR为二进制
用NASM编译生成mbr.bin:
nasm -f bin mbr.asm -o mbr.bin
2. 写入硬盘映像
将mbr.bin写入硬盘映像的LBA 0(MBR位置):
dd if=mbr.bin of=hard_disk.img bs=512 count=1 seek=0
3. 验证分区表
用Bochs加载硬盘映像,通过info disk命令查看分区表:
bochs -f bochs.cfg # 启动Bochs
info disk # 查看硬盘分区信息
若输出显示两个主分区(活动分区FAT32、非活动分区EXT4),说明分区表设置成功。
关键说明
- LBA与CHS的转换:现代系统更依赖LBA(线性寻址),CHS字段可留空或与LBA一致(如本示例)。
- 系统类型:需根据内核文件系统选择正确的类型码(如EXT4是
0x83,NTFS是0x07)。 - 扇区对齐:分区起始LBA需对齐扇区大小(512字节),避免性能问题。
通过以上代码,可在MBR分区表中正确设置主分区信息,为后续内核加载或分区管理奠定基础。

6400

被折叠的 条评论
为什么被折叠?



