x01.os.18: MBR
硬盘不同于软盘,它是要分区的。这时,mbr(master boot record)便不可少了。安装 os 硬盘的第一扇区,开始有一小段不多于 446 字节的程序,然后是分区表 512-446-2 字节,然后是引导标志 0xAA55 两字节。这一小段程序,便是 mbr 的主体。mbr 首先将其自身复制到 0x0600 处,代码如下:
; 0x7C00 => 0x0600
mov si, sp
push si
mov di, 0x0600
mov cx, 0x200
cld
rep movsw
这是要给分区的引导代码腾位置。操作系统的引导代码,可能位于软盘,光盘等 Media 中,其代码首先便是 org 0x7C00,所以 mbr 复制自身进行重定位,就必不可少了。
第二步,当然就是寻找活动分区的启动代码了。有这么一句:test dl, dl。这个 dl 的值,便是 drive number, 由 bios 的 int 0x19 取得。通过 dl 判断设备的类型,作不同的选择。mbr.s 的内容如下:
; ----------------------
; mbr.s (c) 2014 by x01
; ---------------------- P_EntrySize equ ; 分区表每项为 16 字节
P_PartOffset equ 0x1BE ; 分区表在引导扇区的偏移位置
P_BootOffset equ ; 分区项中引导标志的偏移位置
P_TypeOffset equ ; 分区项中分区类型的偏移位置
P_LbaOffset equ ; 分区项中起始扇区 LBA 的偏移位置 ; Partition table struct
; ----------------------
; offset len description
; 0 1 状态(80h=可引导,00h=不可引导,其他不合法)
; 1 1 起始磁头号
; 2 1 起始扇区号(仅用了低 6 位,高 2 位为起始柱面号的第 8-9 位
; 3 1 起始柱面号的低 8 位
; 4 1 分区类型(System ID)
; 5 1 结束磁头号
; 6 1 结束扇区号(仅用了低 6 位,高 2 位为结束柱面号的第 8-9 位
; 7 1 结束柱面号的低 8 位
; 8 4 起始扇区的 LBA
; 12 4 扇区数目 boot:
xor ax, ax
mov ds, ax
mov es, ax
cli
mov ss, ax ; ds = es = ss = 0, 段偏移地址直接映射为物理地址
mov sp, 0x7C00
sti ; 0x7C00 => 0x0600
mov si, sp
push si
mov di, 0x0600
mov cx, 0x200
cld
rep movsw jmp :0x0600 + active active:
test dl, dl ; BIOS int 19h => dl = drive_nr
; SF <- MSB(dl): most significact bit, 1 is -, 0 is +
jns nextdisk mov si, 0x0600 + P_PartOffset find:
cmp byte [si + P_TypeOffset], ; if not equal 0 then can use
jz nextpart
test byte [si + P_BootOffset], 0x80 ; 0x80: bootable
jz nextpart loadpart:
call load
jc error
ret ; goto secondary boot => 0x0000:0x7C00 nextpart:
add si, P_EntrySize
cmp si, 0x0600 + P_PartOffset + * P_EntrySize
jb find call print
db "No active partition\0"
jmp reboot nextdisk:
inc dl
test dl, dl
js nexthd
int 0x11 ; get active drive info
shl ax, ; floppy info at al[6-7], but after shl at ah[0-1]
and ah,
cmp dl, ah ; dl <= ah then floppy exist
ja nextdisk
call loadfloppy
jc nextdisk
ret nexthd:
call loadfloppy error:
jc handle_err
ret ; load floppy 0 sector
loadfloppy:
mov si, 0x0600 + zero - P_LbaOffset ; load hd boot
load:
mov di, retry:
push dx ; dl = old drive_nr protect push es
push di ; Get disk info(int 0x13: ah=0x8)
; ch: cyl low 8 bit, cl[6-7]: cyl high 2 bit
; cl[0-5]: sectors per track
; dh: heads, dl: drive_nr
mov ah, 0x08
int 0x13 pop di
pop es and cl, 0x3F ; sectors base 1
inc dh ; heads base 0, so inc mov al, cl ; al = cl = sectors per track
mul dh ; ax = cyl sectors = heads * sectors_per_track
mov bx, ax mov ax, word [si + P_LbaOffset + ]
mov dx, word [si + P_LbaOffset + ] ; dx:ax = secondary boot offset cmp dx, (0x16390 * 0xFF * 0x3F - 0xFF) >> 0x10
jae bigdisk div bx ; /: ax is cyl_nr, mod: dx is cyl_offset
xchg ax, dx
mov ch, dl ; ch is cyl_nr low 8 bit div cl ; /: al is head_nr, mod: ah is track offset(base 0)
xor dl, dl
shr dx, ; dl[6-7] = cyl_nr high 2 bit
or dl, ah ; dl low 5 bit store track offset
mov cl, dl ; cl high 2 bit is cyl high 2 bit, cl low 5 bit is track offset
inc cl ; base 1
pop dx ; old drive_nr
mov dh, al ; head_nr => dh
mov bx, 0x7C00 ; es:bx is load addr
mov ax, 0x0201 ; read disk sector entry_point parameter
int 0x13 ; read 1 sector to es:bx
jmp read_check bigdisk:
mov bx, dx
pop dx
push si
mov si, 0x0600 + dap_offset ; dap: disk addr packet, for up 8G
mov word [si + ], ax ; low
mov word [si + 0xA], bx ; high
mov ah, 0x42 ; extend read parameter
int 0x13
pop si read_check:
jnc read_ok
cmp ah, 0x80 ; timeout
je read_bad
dec di
jl read_bad
xor ah, ah
int 0x13
jnc retry read_bad:
stc
ret ; have a bug, need clear zero read_ok:
cmp dword [0x7C00 + ], 0xAA55
jne notboot
ret notboot:
call print
db "Not bootable\0"
jmp reboot handle_err:
mov si, 0x7C00 + err_nr + ; err_nr low bit print_num:
mov al, ah ; ah: int 0x13 error code
and al, 0x0F
cmp al, 0xA
jb digit
add al, 0x7 digit:
add byte [si], al ; err_nr low bit is '0', after add is correct number
dec si ; err_nr high bit
mov cl,
shr ah, cl
jnz print_num
call print
db "Read error" err_nr:
db "00\0" reboot:
call print
db "Hit any key reboot.\0"
xor ah, ah
int 0x16 ; wait key
call print
db "\r\n\0"
int 0x19 ; reboot print:
pop si ; ip => get string addr print_next:
lodsb ; al = *si++
test al, al
jz print_done
mov ah, 0x0E
mov bx, 0x0001
int 0x10
jmp print_next print_done:
jmp si dap_offset:
PacketSize db 0x10
Reserved db 0x0
BlockCount dw 0x1
BufferOffset dw 0x7C00
BufferSegment dw 0x0
BlockNumLow dd 0x0
zero:
BlockNumHigh dd 0x0 times -($-$$) db
BootFlag dw 0xAA55
后面加了两句引导标志,是为了快速检验一下运行效果,实际是不需要的。minix 通过 installboot 程序来完成组装与添加。检验方法如下:
1.编译: nasm -o mbr mbr.s
2.写入硬盘:dd if=mbr of=c.img bs=512 count=1 conv=notrunc
其中,c.img 是硬盘映像。配置 bochs 后运行,可看到因找不到活动分区而停止。当然,这又是另一个问题,就不多说了。
x01.os.18: MBR的更多相关文章
- x01.os.14: 时间都去哪儿了
时间都去哪儿了 老帕的“花儿为什么这样红”,三分钟引起六次欢呼,却败给了张碧晨.试想一下,如果是人气更高的陈冰,即使唱得和张碧晨一模一样,可能仍然不敌老帕,为什么张碧晨就能取胜呢?有这么个笑话:一人弹 ...
- x01.os.13: 文件系统
停了两天电,忽然得空闲.找来破吉他,已然不成弦. 丁丁当当敲,敲到电来到.为把时间捡,熬夜三四点. 从我的置顶随笔 x01.Lab.Download 中下载 x01.os.12.t ...
- x01.os.9: 进程切换
进入内核后,当然不能无所事事.先创建三个进程,分别打印 A,B,C.虽然只是简单的打印,但却是一切扩展的基础,不可等闲视之. 进程切换,涉及一系列的寄存器需要保护,于是,就有了 ProcessStac ...
- x01.os.8: 加载内核
在 x01.os.7 中,借助 freedos,学习了保护模式.但操作系统必须完成引导:boot, 加载内核:loader,kernel,进而管理process,memory,file等. 引导比较简 ...
- x01.os.7: 傻子一样的等
傻子一样的等 昨日出差,办完事后,下午 2:30,准备进长途汽车站买票回家,被一人拦住,说可以带我进去,车马上就要开了,买票来不及.我以为是汽车司机,就跟了进去.进去后,他打了个电话,说 3:30 车 ...
- x01.os.20: compile linux-0.11 on the ubuntu
为什么学习 linux 正如不能依靠美国的 GPS 为我们的导弹指示目标一样,很难想像用运行 windows 的电脑去同美国进行信息战.而朝鲜的网络崩溃,再次警示国人,信息战.网络战离我们并不遥远.l ...
- x01.os.16: 添加功能
准备工作 1.确保是 win xp,如是 win 8,运行 nasm 需按提示同意安装组件. 2.确保 src 和 z_tools 在同一目录下,nasm 已包含在 z_tools 文件夹中. ...
- x01.os.12: 在 windows 中写 OS
在 windows 中写操作系统,需要一系列的辅助工具.在此,要感谢川谷秀实!所有工具,都在 z_tools 文件夹中.有了大师的帮助,不妨也来尝试在 windows 中写一把 OS. 源代码及工具可 ...
- x01.os.19: linux 0.0
linux 0.0 是一个丢失的版本,但赵炯老师又在 linux 0.11 的基础上,使它起死回生.www.oldlinux.org 有大量资源可供下载,值得一看. 1.要编译运行,首先需安装:sud ...
随机推荐
- jQuery-1.9.1源码分析系列(十五) 动画处理——外篇
a.动画兼容Tween.propHooks Tween.propHooks提供特殊情况下设置.获取css特征值的方法,结构如下 Tween.propHooks = { _default: { get: ...
- CSS魔法堂:重拾Border之——解构Border
前言 当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...
- 悟透JavaScript
要理解JavaScript,你得首先放下对象和类的概念,回到数据和代码的本原.前面说过,编程世界只有数据和代码两种基本元素,而这两种元素又有着纠缠不清的关系.JavaScript就是把数据和代码都简化 ...
- [译] Paxos算法详解
1. 概述 Paxos算法被用来实现一个容错的分布式系统,一直以来以晦涩难懂著称.这可能是因为该算法最开始使用希腊文表述的.事实上,它是所有分布式算法中最简单易懂的.Paxos算法的本质其实就是一个共 ...
- WPF资源使用
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x ...
- 【C#进阶系列】26 计算限制的异步操作
什么是计算限制的异步操作,当线程在要使用CPU进行计算的时候,那么就叫计算限制. 而对应的IO限制就是线程交给IO设备(键鼠,网络,文件等). 第25章线程基础讲了用专用的线程进行计算限制的操作,但是 ...
- 无法为目标平台“Microsoft.Data.Tools.Schema.Sql.Sql120DatabaseSchemaProvider”创建扩展管理器
很久没写博客了,这段时间情绪不那么稳定,还是心态的问题... 就简单写个问题的解决方法吧,其实最近遇到的问题蛮多的,就拿这个解决过后又遇到的来写吧. 正如标题一样:VS2013 无法为目标平台“Mic ...
- centos安装禅道的步骤
1.下载 XAMPP 套件: https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/stats/timeline 下载的文件是 xam ...
- [修正] 移动平台曲线不平滑的问题(如:TRectangle, TPath...等)
问题:从 XE4 以来,Firemonkey 曲线绘图在移动平台不平滑的问题一直令人诟病,提交到官方的 QC 也是族繁不及备载,官方似乎有意的避开这个问题,迟迟没有修正. 适用版本:XE4 ~ Ber ...
- 从零开始学Python08作业源码:开发简单的FTP(仅供参考)
服务器端:server_server.py #!usr/bin/env python # -*- coding:utf-8 -*- # auther:Mr.chen # 描述: import sock ...