remove useless boot code
This commit is contained in:
parent
175b9e7da3
commit
af16e1508a
@ -1,288 +0,0 @@
|
|||||||
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
; boot.asm
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
; Forrest Yu, 2005
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
|
|
||||||
;%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_
|
|
||||||
BaseOfStack equ 0100h ; 调试状态下堆栈基地址(栈底, 从这个位置向低地址生长)
|
|
||||||
%else
|
|
||||||
BaseOfStack equ 07c00h ; Boot状态下堆栈基地址(栈底, 从这个位置向低地址生长)
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%include "load.inc"
|
|
||||||
;================================================================================================
|
|
||||||
|
|
||||||
jmp short LABEL_START ; Start to boot.
|
|
||||||
nop ; 这个 nop 不可少
|
|
||||||
|
|
||||||
; 下面是 FAT12 磁盘的头, 之所以包含它是因为下面用到了磁盘的一些信息
|
|
||||||
%include "fat12hdr.inc"
|
|
||||||
|
|
||||||
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 ; int 10h
|
|
||||||
|
|
||||||
mov dh, 0 ; "Booting "
|
|
||||||
call DispStr ; 显示字符串
|
|
||||||
|
|
||||||
xor ah, ah ; ┓
|
|
||||||
xor dl, dl ; ┣ 软驱复位
|
|
||||||
int 13h ; ┛
|
|
||||||
|
|
||||||
; 下面在 A 盘的根目录寻找 LOADER.BIN
|
|
||||||
mov word [wSectorNo], SectorNoOfRootDirectory
|
|
||||||
LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
|
|
||||||
cmp word [wRootDirSizeForLoop], 0 ; ┓
|
|
||||||
jz LABEL_NO_LOADERBIN ; ┣ 判断根目录区是不是已经读完
|
|
||||||
dec word [wRootDirSizeForLoop] ; ┛ 如果读完表示没有找到 LOADER.BIN
|
|
||||||
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
|
|
||||||
|
|
||||||
mov si, LoaderFileName ; ds:si -> "LOADER BIN"
|
|
||||||
mov di, OffsetOfLoader ; es:di -> BaseOfLoader:0100 = BaseOfLoader*10h+100
|
|
||||||
cld
|
|
||||||
mov dx, 10h
|
|
||||||
LABEL_SEARCH_FOR_LOADERBIN:
|
|
||||||
cmp dx, 0 ; ┓循环次数控制,
|
|
||||||
jz LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR ; ┣如果已经读完了一个 Sector,
|
|
||||||
dec dx ; ┛就跳到下一个 Sector
|
|
||||||
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:
|
|
||||||
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:
|
|
||||||
add word [wSectorNo], 1
|
|
||||||
jmp LABEL_SEARCH_IN_ROOT_DIR_BEGIN
|
|
||||||
|
|
||||||
LABEL_NO_LOADERBIN:
|
|
||||||
mov dh, 2 ; "No LOADER."
|
|
||||||
call DispStr ; 显示字符串
|
|
||||||
%ifdef _BOOT_DEBUG_
|
|
||||||
mov ax, 4c00h ; ┓
|
|
||||||
int 21h ; ┛没有找到 LOADER.BIN, 回到 DOS
|
|
||||||
%else
|
|
||||||
jmp $ ; 没有找到 LOADER.BIN, 死循环在这里
|
|
||||||
%endif
|
|
||||||
|
|
||||||
LABEL_FILENAME_FOUND: ; 找到 LOADER.BIN 后便来到这里继续
|
|
||||||
mov ax, RootDirSectors
|
|
||||||
and di, 0FFE0h ; di -> 当前条目的开始
|
|
||||||
add di, 01Ah ; di -> 首 Sector
|
|
||||||
mov cx, word [es:di]
|
|
||||||
push cx ; 保存此 Sector 在 FAT 中的序号
|
|
||||||
add cx, ax
|
|
||||||
add cx, DeltaSectorNo ; 这句完成时 cl 里面变成 LOADER.BIN 的起始扇区号 (从 0 开始数的序号)
|
|
||||||
mov ax, BaseOfLoader
|
|
||||||
mov es, ax ; es <- BaseOfLoader
|
|
||||||
mov bx, OffsetOfLoader ; bx <- OffsetOfLoader 于是, es:bx = BaseOfLoader:OffsetOfLoader = BaseOfLoader * 10h + 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
|
|
||||||
pop ax ; 取出此 Sector 在 FAT 中的序号
|
|
||||||
call GetFATEntry
|
|
||||||
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 ; 这一句正式跳转到已加载到内存中的 LOADER.BIN 的开始处
|
|
||||||
; 开始执行 LOADER.BIN 的代码
|
|
||||||
; Boot Sector 的使命到此结束
|
|
||||||
; *****************************************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;============================================================================
|
|
||||||
;变量
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
;============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 函数名: DispStr
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 作用:
|
|
||||||
; 显示一个字符串, 函数开始时 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
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 函数名: ReadSector
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 作用:
|
|
||||||
; 从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中
|
|
||||||
ReadSector:
|
|
||||||
; -----------------------------------------------------------------------
|
|
||||||
; 怎样由扇区号求扇区在磁盘中的位置 (扇区号 -> 柱面号, 起始扇区, 磁头号)
|
|
||||||
; -----------------------------------------------------------------------
|
|
||||||
; 设扇区号为 x
|
|
||||||
; ┌ 柱面号 = y >> 1
|
|
||||||
; x ┌ 商 y ┤
|
|
||||||
; -------------- => ┤ └ 磁头号 = y & 1
|
|
||||||
; 每磁道扇区数 │
|
|
||||||
; └ 余 z => 起始扇区号 = z + 1
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
sub esp, 2 ; 辟出两个字节的堆栈区域保存要读的扇区数: byte [bp-2]
|
|
||||||
|
|
||||||
mov byte [bp-2], cl
|
|
||||||
push bx ; 保存 bx
|
|
||||||
mov bl, [BPB_SecPerTrk] ; bl: 除数
|
|
||||||
div bl ; y 在 al 中, z 在 ah 中
|
|
||||||
inc ah ; z ++
|
|
||||||
mov cl, ah ; cl <- 起始扇区号
|
|
||||||
mov dh, al ; dh <- y
|
|
||||||
shr al, 1 ; y >> 1 (其实是 y/BPB_NumHeads, 这里BPB_NumHeads=2)
|
|
||||||
mov ch, al ; ch <- 柱面号
|
|
||||||
and dh, 1 ; dh & 1 = 磁头号
|
|
||||||
pop bx ; 恢复 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
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 函数名: GetFATEntry
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 作用:
|
|
||||||
; 找到序号为 ax 的 Sector 在 FAT 中的条目, 结果放在 ax 中
|
|
||||||
; 需要注意的是, 中间需要读 FAT 的扇区到 es:bx 处, 所以函数一开始保存了 es 和 bx
|
|
||||||
GetFATEntry:
|
|
||||||
push es
|
|
||||||
push bx
|
|
||||||
push ax
|
|
||||||
mov ax, BaseOfLoader ; ┓
|
|
||||||
sub ax, 0100h ; ┣ 在 BaseOfLoader 后面留出 4K 空间用于存放 FAT
|
|
||||||
mov es, ax ; ┛
|
|
||||||
pop ax
|
|
||||||
mov byte [bOdd], 0
|
|
||||||
mov bx, 3
|
|
||||||
mul bx ; dx:ax = ax * 3
|
|
||||||
mov bx, 2
|
|
||||||
div bx ; dx:ax / 2 ==> ax <- 商, dx <- 余数
|
|
||||||
cmp dx, 0
|
|
||||||
jz LABEL_EVEN
|
|
||||||
mov byte [bOdd], 1
|
|
||||||
LABEL_EVEN:;偶数
|
|
||||||
xor dx, dx ; 现在 ax 中是 FATEntry 在 FAT 中的偏移量. 下面来计算 FATEntry 在哪个扇区中(FAT占用不止一个扇区)
|
|
||||||
mov bx, [BPB_BytsPerSec]
|
|
||||||
div bx ; dx:ax / BPB_BytsPerSec ==> ax <- 商 (FATEntry 所在的扇区相对于 FAT 来说的扇区号)
|
|
||||||
; dx <- 余数 (FATEntry 在扇区内的偏移)。
|
|
||||||
push dx
|
|
||||||
mov bx, 0 ; bx <- 0 于是, es:bx = (BaseOfLoader - 100):00 = (BaseOfLoader - 100) * 10h
|
|
||||||
add ax, SectorNoOfFAT1 ; 此句执行之后的 ax 就是 FATEntry 所在的扇区号
|
|
||||||
mov cl, 2
|
|
||||||
call ReadSector ; 读取 FATEntry 所在的扇区, 一次读两个, 避免在边界发生错误, 因为一个 FATEntry 可能跨越两个扇区
|
|
||||||
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 ; 结束标志
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
; fat12hdr.inc
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
; Forrest Yu, 2005
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
|
|
||||||
; 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个字节
|
|
||||||
;------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
; -------------------------------------------------------------------------
|
|
||||||
; 基于 FAT12 头的一些常量定义,如果头信息改变,下面的常量可能也要做相应改变
|
|
||||||
; -------------------------------------------------------------------------
|
|
||||||
FATSz equ 9 ; BPB_FATSz16
|
|
||||||
RootDirSectors equ 14 ; 根目录占用空间: RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec; 但如果按照此公式代码过长
|
|
||||||
SectorNoOfRootDirectory equ 19 ; Root Directory 的第一个扇区号 = BPB_RsvdSecCnt + (BPB_NumFATs * FATSz)
|
|
||||||
SectorNoOfFAT1 equ 1 ; FAT1 的第一个扇区号 = BPB_RsvdSecCnt
|
|
||||||
DeltaSectorNo equ 17 ; DeltaSectorNo = BPB_RsvdSecCnt + (BPB_NumFATs * FATSz) - 2
|
|
||||||
; 文件的开始Sector号 = DirEntry中的开始Sector号 + 根目录占用Sector数目 + DeltaSectorNo
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
; load.inc
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
; Forrest Yu, 2005
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
|
|
||||||
BaseOfLoader equ 09000h ; LOADER.BIN 被加载到的位置 ---- 段地址
|
|
||||||
OffsetOfLoader equ 0100h ; LOADER.BIN 被加载到的位置 ---- 偏移地址
|
|
||||||
|
|
||||||
BaseOfLoaderPhyAddr equ BaseOfLoader * 10h ; LOADER.BIN 被加载到的位置 ---- 物理地址 (= BaseOfLoader * 10h)
|
|
||||||
|
|
||||||
;modified by xw, 18/6/12
|
|
||||||
; BaseOfKernelFile equ 08000h ; KERNEL.BIN 被加载到的位置 ---- 段地址
|
|
||||||
BaseOfKernelFile equ 07000h ;
|
|
||||||
OffsetOfKernelFile equ 0h ; KERNEL.BIN 被加载到的位置 ---- 偏移地址
|
|
||||||
|
|
||||||
BaseOfEchoFile equ 07E0h ; KERNEL.BIN 被加载到的位置 ---- 段地址
|
|
||||||
OffsetOfEchoFile equ 0h ; KERNEL.BIN 被加载到的位置 ---- 偏移地址
|
|
||||||
|
|
||||||
BaseOfKernelFilePhyAddr equ BaseOfKernelFile * 10h
|
|
||||||
BaseOfEchoFilePhyAddr equ BaseOfKernelFile * 10h
|
|
||||||
|
|
||||||
|
|
||||||
KernelEntryPointPhyAddr equ 0C0030400h ; 注意:1、必须与 MAKEFILE 中参数 -Ttext 的值相等!! edit by visual 2016.5.10
|
|
||||||
; 2、这是个地址而非仅仅是个偏移,如果 -Ttext 的值为 0x400400,则它的值也应该是 0x400400。
|
|
||||||
|
|
||||||
PageDirBase equ 200000h ; 页目录开始地址: 2M
|
|
||||||
PageTblBase equ 201000h ; 页表开始地址: 2M + 4K
|
|
||||||
|
|
||||||
PageTblNumAddr equ 500h;页表数量放在这个位置 delete by visual 2016.4.28
|
|
||||||
|
|
||||||
FMIBuff equ 007ff000h
|
|
||||||
@ -1,322 +0,0 @@
|
|||||||
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
; pm.inc
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
; Forrest Yu, 2005
|
|
||||||
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
|
|
||||||
; 描述符图示
|
|
||||||
|
|
||||||
; 图示一
|
|
||||||
;
|
|
||||||
; ------ ┏━━┳━━┓高地址
|
|
||||||
; ┃ 7 ┃ 段 ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; 基
|
|
||||||
; 字节 7 ┆ ┆ ┆
|
|
||||||
; 址
|
|
||||||
; ┣━━┫ ② ┃
|
|
||||||
; ┃ 0 ┃ ┃
|
|
||||||
; ------ ┣━━╋━━┫
|
|
||||||
; ┃ 7 ┃ G ┃
|
|
||||||
; ┣━━╉──┨
|
|
||||||
; ┃ 6 ┃ D ┃
|
|
||||||
; ┣━━╉──┨
|
|
||||||
; ┃ 5 ┃ 0 ┃
|
|
||||||
; ┣━━╉──┨
|
|
||||||
; ┃ 4 ┃ AVL┃
|
|
||||||
; 字节 6 ┣━━╉──┨
|
|
||||||
; ┃ 3 ┃ ┃
|
|
||||||
; ┣━━┫ 段 ┃
|
|
||||||
; ┃ 2 ┃ 界 ┃
|
|
||||||
; ┣━━┫ 限 ┃
|
|
||||||
; ┃ 1 ┃ ┃
|
|
||||||
; ┣━━┫ ② ┃
|
|
||||||
; ┃ 0 ┃ ┃
|
|
||||||
; ------ ┣━━╋━━┫
|
|
||||||
; ┃ 7 ┃ P ┃
|
|
||||||
; ┣━━╉──┨
|
|
||||||
; ┃ 6 ┃ ┃
|
|
||||||
; ┣━━┫ DPL┃
|
|
||||||
; ┃ 5 ┃ ┃
|
|
||||||
; ┣━━╉──┨
|
|
||||||
; ┃ 4 ┃ S ┃
|
|
||||||
; 字节 5 ┣━━╉──┨
|
|
||||||
; ┃ 3 ┃ ┃
|
|
||||||
; ┣━━┫ T ┃
|
|
||||||
; ┃ 2 ┃ Y ┃
|
|
||||||
; ┣━━┫ P ┃
|
|
||||||
; ┃ 1 ┃ E ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; ┃ 0 ┃ ┃
|
|
||||||
; ------ ┣━━╋━━┫
|
|
||||||
; ┃ 23 ┃ ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; ┃ 22 ┃ ┃
|
|
||||||
; ┣━━┫ 段 ┃
|
|
||||||
;
|
|
||||||
; 字节 ┆ ┆ 基 ┆
|
|
||||||
; 2, 3, 4
|
|
||||||
; ┣━━┫ 址 ┃
|
|
||||||
; ┃ 1 ┃ ① ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; ┃ 0 ┃ ┃
|
|
||||||
; ------ ┣━━╋━━┫
|
|
||||||
; ┃ 15 ┃ ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; ┃ 14 ┃ ┃
|
|
||||||
; ┣━━┫ 段 ┃
|
|
||||||
;
|
|
||||||
; 字节 0,1┆ ┆ 界 ┆
|
|
||||||
;
|
|
||||||
; ┣━━┫ 限 ┃
|
|
||||||
; ┃ 1 ┃ ① ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; ┃ 0 ┃ ┃
|
|
||||||
; ------ ┗━━┻━━┛低地址
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
; 图示二
|
|
||||||
|
|
||||||
; 高地址………………………………………………………………………低地址
|
|
||||||
|
|
||||||
; | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
|
||||||
; |7654321076543210765432107654321076543210765432107654321076543210| <- 共 8 字节
|
|
||||||
; |--------========--------========--------========--------========|
|
|
||||||
; ┏━━━┳━━━━━━━┳━━━━━━━━━━━┳━━━━━━━┓
|
|
||||||
; ┃31..24┃ (见下图) ┃ 段基址(23..0) ┃ 段界限(15..0)┃
|
|
||||||
; ┃ ┃ ┃ ┃ ┃
|
|
||||||
; ┃ 基址2┃③│②│ ①┃基址1b│ 基址1a ┃ 段界限1 ┃
|
|
||||||
; ┣━━━╋━━━┳━━━╋━━━━━━━━━━━╋━━━━━━━┫
|
|
||||||
; ┃ %6 ┃ %5 ┃ %4 ┃ %3 ┃ %2 ┃ %1 ┃
|
|
||||||
; ┗━━━┻━━━┻━━━┻━━━┻━━━━━━━┻━━━━━━━┛
|
|
||||||
; │ \_________
|
|
||||||
; │ \__________________
|
|
||||||
; │ \________________________________________________
|
|
||||||
; │ \
|
|
||||||
; ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
|
|
||||||
; ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃
|
|
||||||
; ┣━━╋━━╋━━╋━━╋━━┻━━┻━━┻━━╋━━╋━━┻━━╋━━╋━━┻━━┻━━┻━━┫
|
|
||||||
; ┃ G ┃ D ┃ 0 ┃ AVL┃ 段界限 2 (19..16) ┃ P ┃ DPL ┃ S ┃ TYPE ┃
|
|
||||||
; ┣━━┻━━┻━━┻━━╋━━━━━━━━━━━╋━━┻━━━━━┻━━┻━━━━━━━━━━━┫
|
|
||||||
; ┃ ③: 属性 2 ┃ ②: 段界限 2 ┃ ①: 属性1 ┃
|
|
||||||
; ┗━━━━━━━━━━━┻━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
||||||
; 高地址 低地址
|
|
||||||
;
|
|
||||||
;
|
|
||||||
|
|
||||||
; 说明:
|
|
||||||
;
|
|
||||||
; (1) P: 存在(Present)位。
|
|
||||||
; P=1 表示描述符对地址转换是有效的,或者说该描述符所描述的段存在,即在内存中;
|
|
||||||
; P=0 表示描述符对地址转换无效,即该段不存在。使用该描述符进行内存访问时会引起异常。
|
|
||||||
;
|
|
||||||
; (2) DPL: 表示描述符特权级(Descriptor Privilege level),共2位。它规定了所描述段的特权级,用于特权检查,以决定对该段能否访问。
|
|
||||||
;
|
|
||||||
; (3) S: 说明描述符的类型。
|
|
||||||
; 对于存储段描述符而言,S=1,以区别与系统段描述符和门描述符(S=0)。
|
|
||||||
;
|
|
||||||
; (4) TYPE: 说明存储段描述符所描述的存储段的具体属性。
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; 数据段类型 类型值 说明
|
|
||||||
; ----------------------------------
|
|
||||||
; 0 只读
|
|
||||||
; 1 只读、已访问
|
|
||||||
; 2 读/写
|
|
||||||
; 3 读/写、已访问
|
|
||||||
; 4 只读、向下扩展
|
|
||||||
; 5 只读、向下扩展、已访问
|
|
||||||
; 6 读/写、向下扩展
|
|
||||||
; 7 读/写、向下扩展、已访问
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; 类型值 说明
|
|
||||||
; 代码段类型 ----------------------------------
|
|
||||||
; 8 只执行
|
|
||||||
; 9 只执行、已访问
|
|
||||||
; A 执行/读
|
|
||||||
; B 执行/读、已访问
|
|
||||||
; C 只执行、一致码段
|
|
||||||
; D 只执行、一致码段、已访问
|
|
||||||
; E 执行/读、一致码段
|
|
||||||
; F 执行/读、一致码段、已访问
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; 系统段类型 类型编码 说明
|
|
||||||
; ----------------------------------
|
|
||||||
; 0 <未定义>
|
|
||||||
; 1 可用286TSS
|
|
||||||
; 2 LDT
|
|
||||||
; 3 忙的286TSS
|
|
||||||
; 4 286调用门
|
|
||||||
; 5 任务门
|
|
||||||
; 6 286中断门
|
|
||||||
; 7 286陷阱门
|
|
||||||
; 8 未定义
|
|
||||||
; 9 可用386TSS
|
|
||||||
; A <未定义>
|
|
||||||
; B 忙的386TSS
|
|
||||||
; C 386调用门
|
|
||||||
; D <未定义>
|
|
||||||
; E 386中断门
|
|
||||||
; F 386陷阱门
|
|
||||||
;
|
|
||||||
; (5) G: 段界限粒度(Granularity)位。
|
|
||||||
; G=0 表示界限粒度为字节;
|
|
||||||
; G=1 表示界限粒度为4K 字节。
|
|
||||||
; 注意,界限粒度只对段界限有效,对段基地址无效,段基地址总是以字节为单位。
|
|
||||||
;
|
|
||||||
; (6) D: D位是一个很特殊的位,在描述可执行段、向下扩展数据段或由SS寄存器寻址的段(通常是堆栈段)的三种描述符中的意义各不相同。
|
|
||||||
; ⑴ 在描述可执行段的描述符中,D位决定了指令使用的地址及操作数所默认的大小。
|
|
||||||
; ① D=1表示默认情况下指令使用32位地址及32位或8位操作数,这样的代码段也称为32位代码段;
|
|
||||||
; ② D=0 表示默认情况下,使用16位地址及16位或8位操作数,这样的代码段也称为16位代码段,它与80286兼容。可以使用地址大小前缀和操作数大小前缀分别改变默认的地址或操作数的大小。
|
|
||||||
; ⑵ 在向下扩展数据段的描述符中,D位决定段的上部边界。
|
|
||||||
; ① D=1表示段的上部界限为4G;
|
|
||||||
; ② D=0表示段的上部界限为64K,这是为了与80286兼容。
|
|
||||||
; ⑶ 在描述由SS寄存器寻址的段描述符中,D位决定隐式的堆栈访问指令(如PUSH和POP指令)使用何种堆栈指针寄存器。
|
|
||||||
; ① D=1表示使用32位堆栈指针寄存器ESP;
|
|
||||||
; ② D=0表示使用16位堆栈指针寄存器SP,这与80286兼容。
|
|
||||||
;
|
|
||||||
; (7) AVL: 软件可利用位。80386对该位的使用未左规定,Intel公司也保证今后开发生产的处理器只要与80386兼容,就不会对该位的使用做任何定义或规定。
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 描述符类型值说明
|
|
||||||
; 其中:
|
|
||||||
; DA_ : Descriptor Attribute
|
|
||||||
; D : 数据段
|
|
||||||
; C : 代码段
|
|
||||||
; S : 系统段
|
|
||||||
; R : 只读
|
|
||||||
; RW : 读写
|
|
||||||
; A : 已访问
|
|
||||||
; 其它 : 可按照字面意思理解
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
DA_32 EQU 4000h ; 32 位段
|
|
||||||
DA_LIMIT_4K EQU 8000h ; 段界限粒度为 4K 字节
|
|
||||||
|
|
||||||
DA_DPL0 EQU 00h ; DPL = 0
|
|
||||||
DA_DPL1 EQU 20h ; DPL = 1
|
|
||||||
DA_DPL2 EQU 40h ; DPL = 2
|
|
||||||
DA_DPL3 EQU 60h ; DPL = 3
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 存储段描述符类型值说明
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
DA_DR EQU 90h ; 存在的只读数据段类型值
|
|
||||||
DA_DRW EQU 92h ; 存在的可读写数据段属性值
|
|
||||||
DA_DRWA EQU 93h ; 存在的已访问可读写数据段类型值
|
|
||||||
DA_C EQU 98h ; 存在的只执行代码段属性值
|
|
||||||
DA_CR EQU 9Ah ; 存在的可执行可读代码段属性值
|
|
||||||
DA_CCO EQU 9Ch ; 存在的只执行一致代码段属性值
|
|
||||||
DA_CCOR EQU 9Eh ; 存在的可执行可读一致代码段属性值
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 系统段描述符类型值说明
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
DA_LDT EQU 82h ; 局部描述符表段类型值
|
|
||||||
DA_TaskGate EQU 85h ; 任务门类型值
|
|
||||||
DA_386TSS EQU 89h ; 可用 386 任务状态段类型值
|
|
||||||
DA_386CGate EQU 8Ch ; 386 调用门类型值
|
|
||||||
DA_386IGate EQU 8Eh ; 386 中断门类型值
|
|
||||||
DA_386TGate EQU 8Fh ; 386 陷阱门类型值
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
; 选择子图示:
|
|
||||||
; ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
|
|
||||||
; ┃ 15 ┃ 14 ┃ 13 ┃ 12 ┃ 11 ┃ 10 ┃ 9 ┃ 8 ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃
|
|
||||||
; ┣━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━╋━━╋━━┻━━┫
|
|
||||||
; ┃ 描述符索引 ┃ TI ┃ RPL ┃
|
|
||||||
; ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━┻━━━━━┛
|
|
||||||
;
|
|
||||||
; RPL(Requested Privilege Level): 请求特权级,用于特权检查。
|
|
||||||
;
|
|
||||||
; TI(Table Indicator): 引用描述符表指示位
|
|
||||||
; TI=0 指示从全局描述符表GDT中读取描述符;
|
|
||||||
; TI=1 指示从局部描述符表LDT中读取描述符。
|
|
||||||
;
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 选择子类型值说明
|
|
||||||
; 其中:
|
|
||||||
; SA_ : Selector Attribute
|
|
||||||
|
|
||||||
SA_RPL0 EQU 0 ; ┓
|
|
||||||
SA_RPL1 EQU 1 ; ┣ RPL
|
|
||||||
SA_RPL2 EQU 2 ; ┃
|
|
||||||
SA_RPL3 EQU 3 ; ┛
|
|
||||||
|
|
||||||
SA_TIG EQU 0 ; ┓TI
|
|
||||||
SA_TIL EQU 4 ; ┛
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 分页机制使用的常量说明
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
PG_P EQU 1 ; 页存在属性位
|
|
||||||
PG_RWR EQU 0 ; R/W 属性位值, 读/执行
|
|
||||||
PG_RWW EQU 2 ; R/W 属性位值, 读/写/执行
|
|
||||||
PG_USS EQU 0 ; U/S 属性位值, 系统级
|
|
||||||
PG_USU EQU 4 ; U/S 属性位值, 用户级
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
; =========================================
|
|
||||||
; FLAGS - Intel 8086 Family Flags Register
|
|
||||||
; =========================================
|
|
||||||
;
|
|
||||||
; |11|10|F|E|D|C|B|A|9|8|7|6|5|4|3|2|1|0|
|
|
||||||
; | | | | | | | | | | | | | | | | | '--- CF……Carry Flag
|
|
||||||
; | | | | | | | | | | | | | | | | '--- 1
|
|
||||||
; | | | | | | | | | | | | | | | '--- PF……Parity Flag
|
|
||||||
; | | | | | | | | | | | | | | '--- 0
|
|
||||||
; | | | | | | | | | | | | | '--- AF……Auxiliary Flag
|
|
||||||
; | | | | | | | | | | | | '--- 0
|
|
||||||
; | | | | | | | | | | | '--- ZF……Zero Flag
|
|
||||||
; | | | | | | | | | | '--- SF……Sign Flag
|
|
||||||
; | | | | | | | | | '--- TF……Trap Flag (Single Step)
|
|
||||||
; | | | | | | | | '--- IF……Interrupt Flag
|
|
||||||
; | | | | | | | '--- DF……Direction Flag
|
|
||||||
; | | | | | | '--- OF……Overflow flag
|
|
||||||
; | | | | '----- IOPL……I/O Privilege Level (286+ only)
|
|
||||||
; | | | '----- NT……Nested Task Flag (286+ only)
|
|
||||||
; | | '----- 0
|
|
||||||
; | '----- RF……Resume Flag (386+ only)
|
|
||||||
; '------ VM……Virtual Mode Flag (386+ only)
|
|
||||||
;
|
|
||||||
; 注: see PUSHF POPF STI CLI STD CLD
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
; 宏 ------------------------------------------------------------------------------------------------------
|
|
||||||
;
|
|
||||||
; 描述符
|
|
||||||
; usage: Descriptor Base, Limit, Attr
|
|
||||||
; Base: dd
|
|
||||||
; Limit: dd (low 20 bits available)
|
|
||||||
; Attr: dw (lower 4 bits of higher byte are always 0)
|
|
||||||
%macro Descriptor 3
|
|
||||||
dw %2 & 0FFFFh ; 段界限 1 (2 字节)
|
|
||||||
dw %1 & 0FFFFh ; 段基址 1 (2 字节)
|
|
||||||
db (%1 >> 16) & 0FFh ; 段基址 2 (1 字节)
|
|
||||||
dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性 1 + 段界限 2 + 属性 2 (2 字节)
|
|
||||||
db (%1 >> 24) & 0FFh ; 段基址 3 (1 字节)
|
|
||||||
%endmacro ; 共 8 字节
|
|
||||||
;
|
|
||||||
; 门
|
|
||||||
; usage: Gate Selector, Offset, DCount, Attr
|
|
||||||
; Selector: dw
|
|
||||||
; Offset: dd
|
|
||||||
; DCount: db
|
|
||||||
; Attr: db
|
|
||||||
%macro Gate 4
|
|
||||||
dw (%2 & 0FFFFh) ; 偏移 1 (2 字节)
|
|
||||||
dw %1 ; 选择子 (2 字节)
|
|
||||||
dw (%3 & 1Fh) | ((%4 << 8) & 0FF00h) ; 属性 (2 字节)
|
|
||||||
dw ((%2 >> 16) & 0FFFFh) ; 偏移 2 (2 字节)
|
|
||||||
%endmacro ; 共 8 字节
|
|
||||||
; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,253 +0,0 @@
|
|||||||
;==============================================================================================================================
|
|
||||||
BaseOfStack equ 0x07c00 ; Boot状态下堆栈基地址
|
|
||||||
DATA_BUF_OFF equ 0x2000 ; 目录被加载的缓冲区地址
|
|
||||||
STACK_ADDR equ 0x7bea ; 堆栈栈顶
|
|
||||||
OSLOADER_SEG equ 0x09000 ; 起始段地址
|
|
||||||
OSLOADER_SEG_OFF equ 0x0100
|
|
||||||
|
|
||||||
FAT_START_SECTOR equ 0x820 ; FAT表的起始扇区号 DWORD
|
|
||||||
DATA_START_SECTOR equ 0xd6a ; 数据区起始扇区号 DWORD
|
|
||||||
DIR_PER_SECTOR equ 0x10 ; 每个扇区所容纳的目录 BYTE
|
|
||||||
|
|
||||||
; 扩展磁盘服务所使用的地址包
|
|
||||||
DAP_SECTOR_HIGH equ 4 ; 起始扇区号的高32位 ( 每次调用需要重置 ) DWORD
|
|
||||||
DAP_SECTOR_LOW equ 8 ; 起始扇区号的低32位 ( 每次调用需要重置 ) DWORD
|
|
||||||
DAP_BUFFER_SEG equ 10 ; 缓冲区段地址 ( 每次调用需要重置 ) WORD
|
|
||||||
DAP_BUFFER_OFF equ 12 ; 缓冲区偏移 ( 每次调用需要重置 ) WORD
|
|
||||||
DAP_RESERVED2 equ 13 ; 保留字节
|
|
||||||
DAP_READ_SECTORS equ 14 ; 要处理的扇区数(1 - 127 )
|
|
||||||
DAP_RESERVED1 equ 15 ; 保留字节
|
|
||||||
DAP_PACKET_SIZE equ 16 ; 包的大小为16字节
|
|
||||||
|
|
||||||
CURRENT_CLUSTER equ 20 ; 当前正在处理的簇号 DWORD
|
|
||||||
|
|
||||||
; 目录项结构
|
|
||||||
OFF_START_CLUSTER_HIGH equ 20 ; 起始簇号高位 WORD
|
|
||||||
OFF_START_CLUSTER_LOW equ 26 ; 起始簇号低位 WORD
|
|
||||||
|
|
||||||
; 相关常量
|
|
||||||
DIR_NAME_FREE equ 0x00 ; 该项是空闲的
|
|
||||||
DIR_ENTRY_SIZE equ 32 ; 每个目录项的尺寸
|
|
||||||
|
|
||||||
; 簇属性
|
|
||||||
CLUSTER_MASK equ 0FFFFFFFH ; 簇号掩码
|
|
||||||
CLUSTER_LAST equ 0FFFFFF8H ;0xFFFFFFF8-0xFFFFFFFF表示文件的最后一个簇
|
|
||||||
;==============================================================================================================================
|
|
||||||
org 07c00h
|
|
||||||
|
|
||||||
jmp START
|
|
||||||
nop
|
|
||||||
|
|
||||||
BS_OEM DB 'mkfs.fat' ;文件系统标志
|
|
||||||
BPB_BytesPerSec DW 0x200 ;每扇区字节数
|
|
||||||
BPB_SecPerClu DB 1 ;每簇扇区数
|
|
||||||
BPB_RsvdSecCnt DW 0x20 ;保留扇区数
|
|
||||||
BPB_NumFATs DB 2 ;FAT表数
|
|
||||||
BPB_RootEntCnt DW 0 ;FAT32不使用
|
|
||||||
BPB_TotSec16 DW 0 ;扇区总数
|
|
||||||
BPB_Media DB 0xf8 ;介质描述符
|
|
||||||
BPB_FATSz16 DW 0 ;每个FAT表的大小扇区数
|
|
||||||
BPB_SecPerTrk DW 0x3f ;每磁道扇区数
|
|
||||||
BPB_NumHeads DW 0xff ;磁头数
|
|
||||||
BPB_HiddSec DD 0 ;分区已使用扇区数
|
|
||||||
BPB_TotSec32 DD 0x015791 ;文件系统大小扇区数
|
|
||||||
BS_SecPerFAT DD 0x02a5 ;每个FAT表大小扇区数
|
|
||||||
BS_Flag DW 0 ;标记
|
|
||||||
BS_Version DW 0 ;版本号
|
|
||||||
BS_RootClus DD 2 ;根目录簇号
|
|
||||||
BS_FsInfoSec DW 1 ;FSINFO扇区号
|
|
||||||
BS_BackBootSec DW 6 ;备份引导扇区位置
|
|
||||||
BS_Unuse1 DD 0 ;未使用
|
|
||||||
BS_Unuse2 DD 0 ;未使用
|
|
||||||
BS_Unuse3 DD 0 ;未使用
|
|
||||||
BS_DriveNum DB 0x80 ;设备号
|
|
||||||
BS_Unuse4 DB 0x01 ;未使用
|
|
||||||
BS_ExtBootFlag DB 0x29 ;扩展引导标志
|
|
||||||
BS_VolNum DD 0xbe3a8ff5 ;卷序列号
|
|
||||||
BS_VolName DB 'MZY hd boot' ;卷标
|
|
||||||
|
|
||||||
START:
|
|
||||||
cld
|
|
||||||
xor ax, ax
|
|
||||||
mov ds, ax
|
|
||||||
mov es, ax
|
|
||||||
mov ss, ax
|
|
||||||
mov sp, STACK_ADDR
|
|
||||||
mov bp, BaseOfStack
|
|
||||||
|
|
||||||
mov dword [bp - DAP_SECTOR_HIGH ], 00h
|
|
||||||
mov byte [bp - DAP_RESERVED1 ], 00h
|
|
||||||
mov byte [bp - DAP_RESERVED2 ], 00h
|
|
||||||
mov byte [bp - DAP_PACKET_SIZE ], 10h
|
|
||||||
mov byte [bp - DAP_READ_SECTORS], 01h
|
|
||||||
mov byte [bp - DAP_BUFFER_SEG ], 00h
|
|
||||||
|
|
||||||
jmp _SEARCH_LOADER
|
|
||||||
|
|
||||||
_MISSING_LOADER: ; 显示没有装载程序
|
|
||||||
_DISK_ERROR: ; 显示磁盘错误信息
|
|
||||||
JMP $
|
|
||||||
|
|
||||||
ReadSector:
|
|
||||||
pusha
|
|
||||||
mov ah, 42h
|
|
||||||
lea si, [BP - DAP_PACKET_SIZE]
|
|
||||||
mov dl, [BS_DriveNum]
|
|
||||||
int 13h
|
|
||||||
jc _DISK_ERROR
|
|
||||||
popa
|
|
||||||
ret
|
|
||||||
|
|
||||||
_SEARCH_LOADER:
|
|
||||||
mov word [bp - DAP_BUFFER_OFF], DATA_BUF_OFF
|
|
||||||
mov eax, dword [BS_RootClus]
|
|
||||||
mov dword [bp - CURRENT_CLUSTER], eax
|
|
||||||
|
|
||||||
_NEXT_ROOT_CLUSTER:
|
|
||||||
dec eax
|
|
||||||
dec eax
|
|
||||||
xor ebx, ebx
|
|
||||||
mov bl, byte [BPB_SecPerClu]
|
|
||||||
mul ebx
|
|
||||||
add eax, DATA_START_SECTOR
|
|
||||||
mov dword [BP - DAP_SECTOR_LOW], eax
|
|
||||||
mov dl, [BPB_SecPerClu]
|
|
||||||
|
|
||||||
_NEXT_ROOT_SECTOR:
|
|
||||||
call ReadSector
|
|
||||||
|
|
||||||
mov di, DATA_BUF_OFF
|
|
||||||
mov bl, DIR_PER_SECTOR
|
|
||||||
|
|
||||||
_NEXT_ROOT_ENTRY:
|
|
||||||
cmp byte [di], DIR_NAME_FREE
|
|
||||||
jz _MISSING_LOADER
|
|
||||||
|
|
||||||
push di;
|
|
||||||
mov si, LoaderName
|
|
||||||
mov cx, 10
|
|
||||||
repe cmpsb
|
|
||||||
jcxz _FOUND_LOADER
|
|
||||||
|
|
||||||
pop di
|
|
||||||
add di, DIR_ENTRY_SIZE
|
|
||||||
dec bl
|
|
||||||
jnz _NEXT_ROOT_ENTRY
|
|
||||||
|
|
||||||
dec dl
|
|
||||||
jz _CHECK_NEXT_ROOT_CLUSTER
|
|
||||||
inc dword [bp - DAP_SECTOR_LOW]
|
|
||||||
jmp _NEXT_ROOT_SECTOR
|
|
||||||
|
|
||||||
_CHECK_NEXT_ROOT_CLUSTER:
|
|
||||||
|
|
||||||
; 计算FAT所在的簇号和偏移
|
|
||||||
; FatOffset = ClusterNum*4
|
|
||||||
XOR EDX,EDX
|
|
||||||
MOV EAX,DWORD[BP - CURRENT_CLUSTER]
|
|
||||||
SHL EAX,2
|
|
||||||
XOR ECX,ECX
|
|
||||||
MOV CX,WORD [ BPB_BytesPerSec ]
|
|
||||||
DIV ECX ; EAX = Sector EDX = OFFSET
|
|
||||||
ADD EAX, FAT_START_SECTOR
|
|
||||||
MOV DWORD [ BP - DAP_SECTOR_LOW ], EAX
|
|
||||||
|
|
||||||
call ReadSector
|
|
||||||
|
|
||||||
; 检查下一个簇
|
|
||||||
MOV DI,DX
|
|
||||||
ADD DI,DATA_BUF_OFF
|
|
||||||
MOV EAX,DWORD[DI] ; EAX = 下一个要读的簇号
|
|
||||||
AND EAX,CLUSTER_MASK
|
|
||||||
MOV DWORD[ BP - CURRENT_CLUSTER ],EAX
|
|
||||||
CMP EAX,CLUSTER_LAST ; CX >= 0FFFFFF8H,则意味着没有更多的簇了
|
|
||||||
JB _NEXT_ROOT_CLUSTER
|
|
||||||
JMP _MISSING_LOADER
|
|
||||||
|
|
||||||
_FOUND_LOADER:
|
|
||||||
; 目录结构地址放在DI中
|
|
||||||
pop di
|
|
||||||
xor eax, eax
|
|
||||||
mov ax, [di + OFF_START_CLUSTER_HIGH] ; 起始簇号高32位
|
|
||||||
shl ax, 16
|
|
||||||
mov ax, [di + OFF_START_CLUSTER_LOW] ; 起始簇号低32位
|
|
||||||
mov dword [ bp - CURRENT_CLUSTER ], eax
|
|
||||||
mov cx, OSLOADER_SEG ; CX = 缓冲区段地址
|
|
||||||
|
|
||||||
_NEXT_DATA_CLUSTER:
|
|
||||||
; 根据簇号计算扇区号
|
|
||||||
DEC EAX
|
|
||||||
DEC EAX
|
|
||||||
XOR EBX,EBX
|
|
||||||
MOV BL, BYTE [ BPB_SecPerClu ]
|
|
||||||
MUL EBX
|
|
||||||
ADD EAX, DATA_START_SECTOR
|
|
||||||
MOV DWORD[ BP - DAP_SECTOR_LOW ], EAX
|
|
||||||
MOV BL , BYTE [BPB_SecPerClu]
|
|
||||||
|
|
||||||
; 设置缓冲区
|
|
||||||
MOV WORD [ BP - DAP_BUFFER_SEG ], CX
|
|
||||||
MOV WORD [ BP - DAP_BUFFER_OFF ], OSLOADER_SEG_OFF
|
|
||||||
|
|
||||||
_NEXT_DATA_SECTOR:
|
|
||||||
; 读取簇中的每个扇区(内层循环)
|
|
||||||
; 注意 : 通过检查文件大小,可以避免读取最后一个不满簇的所有大小
|
|
||||||
call ReadSector
|
|
||||||
|
|
||||||
; 更新地址,继续读取
|
|
||||||
MOV AX, WORD [BPB_BytesPerSec]
|
|
||||||
ADD WORD [BP - DAP_BUFFER_OFF], ax
|
|
||||||
INC DWORD [BP - DAP_SECTOR_LOW] ; 递增扇区号
|
|
||||||
DEC BL ; 内层循环计数
|
|
||||||
JNZ _NEXT_DATA_SECTOR
|
|
||||||
|
|
||||||
; 更新读取下一个簇的缓冲区地址
|
|
||||||
MOV CL, BYTE [ BPB_SecPerClu ]
|
|
||||||
MOV AX, WORD [BPB_BytesPerSec]
|
|
||||||
SHR AX, 4
|
|
||||||
MUL CL
|
|
||||||
ADD AX, WORD [ BP - DAP_BUFFER_SEG ]
|
|
||||||
MOV CX, AX ; 保存下一个簇的缓冲区段地址
|
|
||||||
|
|
||||||
;====================================================================
|
|
||||||
; 检查是否还有下一个簇(读取FAT表的相关信息)
|
|
||||||
; LET N = 数据簇号
|
|
||||||
; THUS FAT_BYTES = N*4 (FAT32)
|
|
||||||
; FAT_SECTOR = FAT_BYTES / BPB_BytesPerSec
|
|
||||||
; FAT_OFFSET = FAT_BYTES % BPB_BytesPerSec
|
|
||||||
;====================================================================
|
|
||||||
|
|
||||||
; 计算FAT所在的簇号和偏移
|
|
||||||
MOV EAX,DWORD [BP - CURRENT_CLUSTER]
|
|
||||||
XOR EDX,EDX
|
|
||||||
SHL EAX,2
|
|
||||||
XOR EBX,EBX
|
|
||||||
MOV BX,WORD [ BPB_BytesPerSec ]
|
|
||||||
DIV EBX ; EAX = Sector EDX = Offset
|
|
||||||
|
|
||||||
; 设置缓冲区地址
|
|
||||||
ADD EAX, FAT_START_SECTOR
|
|
||||||
MOV DWORD [ BP - DAP_SECTOR_LOW ], EAX
|
|
||||||
MOV WORD [BP - DAP_BUFFER_SEG ], 00H
|
|
||||||
MOV WORD [BP - DAP_BUFFER_OFF ], DATA_BUF_OFF
|
|
||||||
|
|
||||||
; 读取扇区
|
|
||||||
CALL ReadSector
|
|
||||||
|
|
||||||
; 检查下一个簇
|
|
||||||
MOV DI,DX
|
|
||||||
ADD DI,DATA_BUF_OFF
|
|
||||||
MOV EAX,DWORD[DI] ; EAX = 下一个要读的簇号
|
|
||||||
AND EAX,CLUSTER_MASK
|
|
||||||
MOV DWORD[ BP - CURRENT_CLUSTER ],EAX
|
|
||||||
CMP EAX,CLUSTER_LAST ; CX >= 0FFFFFF8H,则意味着没有更多的簇了
|
|
||||||
JB _NEXT_DATA_CLUSTER
|
|
||||||
|
|
||||||
_RUN_LOADER:
|
|
||||||
mov dl, [BS_DriveNum]
|
|
||||||
jmp OSLOADER_SEG:OSLOADER_SEG_OFF
|
|
||||||
|
|
||||||
LoaderName db "LOADER BIN" ; 第二阶段启动程序 FDOSLDR.BIN
|
|
||||||
|
|
||||||
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
|
|
||||||
dw 0xaa55 ; 结束标志
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
set default=0
|
|
||||||
set timeout=5
|
|
||||||
|
|
||||||
menuentry "myboot" {
|
|
||||||
set root=(hd0,msdos1)
|
|
||||||
chainloader +1
|
|
||||||
boot
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
BS_OEM DB 'mkfs.fat'
|
|
||||||
BPB_BytesPerSec DW 0x200
|
|
||||||
BPB_SecPerClu DB 1
|
|
||||||
BPB_RsvdSecCnt DW 0x20
|
|
||||||
BPB_NumFATs DB 2
|
|
||||||
BPB_RootEntCnt DW 0
|
|
||||||
BPB_TotSec16 DW 0
|
|
||||||
BPB_Media DB 0xf8
|
|
||||||
BPB_FATSz16 DW 0
|
|
||||||
BPB_SecPerTrk DW 0x20
|
|
||||||
BPB_NumHeads DW 0x40
|
|
||||||
BPB_HiddSec DD 0
|
|
||||||
BPB_TotSec32 DD 0x015791
|
|
||||||
BS_SecPerFAT DD 0x02a5
|
|
||||||
BS_Flag DW 0
|
|
||||||
BS_Version DW 0
|
|
||||||
BS_RootClus DD 2
|
|
||||||
BS_FsInfoSec DW 1
|
|
||||||
BS_BackBootSec DW 6
|
|
||||||
BS_Unuse1 DD 0
|
|
||||||
BS_Unuse2 DD 0
|
|
||||||
BS_Unuse3 DD 0
|
|
||||||
BS_DriveNum DB 0x80
|
|
||||||
BS_Unuse4 DB 0
|
|
||||||
BS_ExtBootFlag DB 0x29
|
|
||||||
BS_VolNum DD 0xbe3a8ff5
|
|
||||||
BS_VolName DB 'MZY hd boot'
|
|
||||||
|
|
||||||
@ -1,170 +0,0 @@
|
|||||||
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
; 显示 AL 中的数字
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
DispAL:
|
|
||||||
push ecx
|
|
||||||
push edx
|
|
||||||
push edi
|
|
||||||
|
|
||||||
mov edi, [dwDispPos]
|
|
||||||
|
|
||||||
mov ah, 0Fh ; 0000b: 黑底 1111b: 白字
|
|
||||||
mov dl, al
|
|
||||||
shr al, 4
|
|
||||||
mov ecx, 2
|
|
||||||
.begin:
|
|
||||||
and al, 01111b
|
|
||||||
cmp al, 9
|
|
||||||
ja .1
|
|
||||||
add al, '0'
|
|
||||||
jmp .2
|
|
||||||
.1:
|
|
||||||
sub al, 0Ah
|
|
||||||
add al, 'A'
|
|
||||||
.2:
|
|
||||||
mov [gs:edi], ax
|
|
||||||
add edi, 2
|
|
||||||
|
|
||||||
mov al, dl
|
|
||||||
loop .begin
|
|
||||||
;add edi, 2
|
|
||||||
|
|
||||||
mov [dwDispPos], edi
|
|
||||||
|
|
||||||
pop edi
|
|
||||||
pop edx
|
|
||||||
pop ecx
|
|
||||||
|
|
||||||
ret
|
|
||||||
; DispAL 结束-------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
; 显示一个整形数
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
DispInt:
|
|
||||||
mov eax, [esp + 4]
|
|
||||||
shr eax, 24
|
|
||||||
call DispAL
|
|
||||||
|
|
||||||
mov eax, [esp + 4]
|
|
||||||
shr eax, 16
|
|
||||||
call DispAL
|
|
||||||
|
|
||||||
mov eax, [esp + 4]
|
|
||||||
shr eax, 8
|
|
||||||
call DispAL
|
|
||||||
|
|
||||||
mov eax, [esp + 4]
|
|
||||||
call DispAL
|
|
||||||
|
|
||||||
mov ah, 07h ; 0000b: 黑底 0111b: 灰字
|
|
||||||
mov al, 'h'
|
|
||||||
push edi
|
|
||||||
mov edi, [dwDispPos]
|
|
||||||
mov [gs:edi], ax
|
|
||||||
add edi, 4
|
|
||||||
mov [dwDispPos], edi
|
|
||||||
pop edi
|
|
||||||
|
|
||||||
ret
|
|
||||||
; DispInt 结束------------------------------------------------------------
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
; 显示一个字符串
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
DispStr:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
push ebx
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
|
|
||||||
mov esi, [ebp + 8] ; pszInfo
|
|
||||||
mov edi, [dwDispPos]
|
|
||||||
mov ah, 0Fh
|
|
||||||
.1:
|
|
||||||
lodsb
|
|
||||||
test al, al
|
|
||||||
jz .2
|
|
||||||
cmp al, 0Ah ; 是回车吗?
|
|
||||||
jnz .3
|
|
||||||
push eax
|
|
||||||
mov eax, edi
|
|
||||||
mov bl, 160
|
|
||||||
div bl
|
|
||||||
and eax, 0FFh
|
|
||||||
inc eax
|
|
||||||
mov bl, 160
|
|
||||||
mul bl
|
|
||||||
mov edi, eax
|
|
||||||
pop eax
|
|
||||||
jmp .1
|
|
||||||
.3:
|
|
||||||
mov [gs:edi], ax
|
|
||||||
add edi, 2
|
|
||||||
jmp .1
|
|
||||||
|
|
||||||
.2:
|
|
||||||
mov [dwDispPos], edi
|
|
||||||
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
pop ebx
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
||||||
; DispStr 结束------------------------------------------------------------
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
; 换行
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
DispReturn:
|
|
||||||
push szReturn
|
|
||||||
call DispStr ;printf("\n");
|
|
||||||
add esp, 4
|
|
||||||
|
|
||||||
ret
|
|
||||||
; DispReturn 结束---------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
; 内存拷贝,仿 memcpy
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
; void* MemCpy(void* es:pDest, void* ds:pSrc, int iSize);
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
MemCpy:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
push ecx
|
|
||||||
|
|
||||||
mov edi, [ebp + 8] ; Destination
|
|
||||||
mov esi, [ebp + 12] ; Source
|
|
||||||
mov ecx, [ebp + 16] ; Counter
|
|
||||||
.1:
|
|
||||||
cmp ecx, 0 ; 判断计数器
|
|
||||||
jz .2 ; 计数器为零时跳出
|
|
||||||
|
|
||||||
mov al, [ds:esi] ; ┓
|
|
||||||
inc esi ; ┃
|
|
||||||
; ┣ 逐字节移动
|
|
||||||
mov byte [es:edi], al ; ┃
|
|
||||||
inc edi ; ┛
|
|
||||||
|
|
||||||
dec ecx ; 计数器减一
|
|
||||||
jmp .1 ; 循环
|
|
||||||
.2:
|
|
||||||
mov eax, [ebp + 8] ; 返回值
|
|
||||||
|
|
||||||
pop ecx
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
mov esp, ebp
|
|
||||||
pop ebp
|
|
||||||
|
|
||||||
ret ; 函数结束,返回
|
|
||||||
; MemCpy 结束-------------------------------------------------------------
|
|
||||||
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
;==============================================================================================================================
|
|
||||||
BaseOfStack equ 0x0100
|
|
||||||
STACK_ADDR equ 0x0ea
|
|
||||||
SEG_ADDR equ 0x09000
|
|
||||||
DATA_BUF_OFF equ 0x09000
|
|
||||||
|
|
||||||
FAT_START_SECTOR equ 0x820 ; FAT表的起始扇区号 DWORD
|
|
||||||
DATA_START_SECTOR equ 0xd6a ; 数据区起始扇区号 DWORD
|
|
||||||
DIR_PER_SECTOR equ 0x10 ; 每个扇区所容纳的目录 BYTE
|
|
||||||
|
|
||||||
; 扩展磁盘服务所使用的地址包
|
|
||||||
DAP_SECTOR_HIGH equ 4 ; 起始扇区号的高32位 ( 每次调用需要重置 ) DWORD
|
|
||||||
DAP_SECTOR_LOW equ 8 ; 起始扇区号的低32位 ( 每次调用需要重置 ) DWORD
|
|
||||||
DAP_BUFFER_SEG equ 10 ; 缓冲区段地址 ( 每次调用需要重置 ) WORD
|
|
||||||
DAP_BUFFER_OFF equ 12 ; 缓冲区偏移 ( 每次调用需要重置 ) WORD
|
|
||||||
DAP_RESERVED2 equ 13 ; 保留字节
|
|
||||||
DAP_READ_SECTORS equ 14 ; 要处理的扇区数(1 - 127 )
|
|
||||||
DAP_RESERVED1 equ 15 ; 保留字节
|
|
||||||
DAP_PACKET_SIZE equ 16 ; 包的大小为16字节
|
|
||||||
|
|
||||||
CURRENT_CLUSTER equ 20 ; 当前正在处理的簇号 DWORD
|
|
||||||
|
|
||||||
; 目录项结构
|
|
||||||
OFF_START_CLUSTER_HIGH equ 20 ; 起始簇号高位 WORD
|
|
||||||
OFF_START_CLUSTER_LOW equ 26 ; 起始簇号低位 WORD
|
|
||||||
|
|
||||||
; 相关常量
|
|
||||||
DIR_NAME_FREE equ 0x00 ; 该项是空闲的
|
|
||||||
DIR_ENTRY_SIZE equ 32 ; 每个目录项的尺寸
|
|
||||||
|
|
||||||
; 簇属性
|
|
||||||
CLUSTER_MASK equ 0FFFFFFFH ; 簇号掩码
|
|
||||||
CLUSTER_LAST equ 0FFFFFF8H ;0xFFFFFFF8-0xFFFFFFFF表示文件的最后一个簇
|
|
||||||
|
|
||||||
BaseOfLoader equ 09000h ; LOADER.BIN 被加载到的位置 ---- 段地址
|
|
||||||
OffsetOfLoader equ 0100h ; LOADER.BIN 被加载到的位置 ---- 偏移地址
|
|
||||||
|
|
||||||
BaseOfLoaderPhyAddr equ BaseOfLoader * 10h ; LOADER.BIN 被加载到的位置 ---- 物理地址 (= BaseOfLoader * 10h)
|
|
||||||
|
|
||||||
BaseOfKernelFile equ 06000h ; KERNEL.BIN 被加载到的位置 ---- 段地址
|
|
||||||
OffsetOfKernelFile equ 0h ; KERNEL.BIN 被加载到的位置 ---- 偏移地址
|
|
||||||
|
|
||||||
BaseOfKernelFilePhyAddr equ BaseOfKernelFile * 10h
|
|
||||||
|
|
||||||
BaseOfEchoFile equ 07E0h ; KERNEL.BIN 被加载到的位置 ---- 段地址
|
|
||||||
OffsetOfEchoFile equ 0h ; KERNEL.BIN 被加载到的位置 ---- 偏移地址
|
|
||||||
|
|
||||||
BaseOfEchoFilePhyAddr equ BaseOfKernelFile * 10h
|
|
||||||
|
|
||||||
KernelEntryPointPhyAddr equ 0xC0030400 ; 注意:1、必须与 MAKEFILE 中参数 -Ttext 的值相等!!
|
|
||||||
; 2、这是个地址而非仅仅是个偏移
|
|
||||||
|
|
||||||
PageDirBase equ 200000h ; 页目录开始地址: 2M
|
|
||||||
PageTblBase equ 201000h ; 页表开始地址: 2M + 4K
|
|
||||||
|
|
||||||
PageTblNumAddr equ 500h;页表数量放在这个位置 delete by visual 2016.4.28
|
|
||||||
|
|
||||||
FMIBuff equ 007ff000h
|
|
||||||
|
|
||||||
;==============================================================================================================================
|
|
||||||
|
|
||||||
@ -1,318 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
; 描述符图示
|
|
||||||
|
|
||||||
; 图示一
|
|
||||||
;
|
|
||||||
; ------ ┏━━┳━━┓高地址
|
|
||||||
; ┃ 7 ┃ 段 ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; 基
|
|
||||||
; 字节 7 ┆ ┆ ┆
|
|
||||||
; 址
|
|
||||||
; ┣━━┫ ② ┃
|
|
||||||
; ┃ 0 ┃ ┃
|
|
||||||
; ------ ┣━━╋━━┫
|
|
||||||
; ┃ 7 ┃ G ┃
|
|
||||||
; ┣━━╉──┨
|
|
||||||
; ┃ 6 ┃ D ┃
|
|
||||||
; ┣━━╉──┨
|
|
||||||
; ┃ 5 ┃ 0 ┃
|
|
||||||
; ┣━━╉──┨
|
|
||||||
; ┃ 4 ┃ AVL┃
|
|
||||||
; 字节 6 ┣━━╉──┨
|
|
||||||
; ┃ 3 ┃ ┃
|
|
||||||
; ┣━━┫ 段 ┃
|
|
||||||
; ┃ 2 ┃ 界 ┃
|
|
||||||
; ┣━━┫ 限 ┃
|
|
||||||
; ┃ 1 ┃ ┃
|
|
||||||
; ┣━━┫ ② ┃
|
|
||||||
; ┃ 0 ┃ ┃
|
|
||||||
; ------ ┣━━╋━━┫
|
|
||||||
; ┃ 7 ┃ P ┃
|
|
||||||
; ┣━━╉──┨
|
|
||||||
; ┃ 6 ┃ ┃
|
|
||||||
; ┣━━┫ DPL┃
|
|
||||||
; ┃ 5 ┃ ┃
|
|
||||||
; ┣━━╉──┨
|
|
||||||
; ┃ 4 ┃ S ┃
|
|
||||||
; 字节 5 ┣━━╉──┨
|
|
||||||
; ┃ 3 ┃ ┃
|
|
||||||
; ┣━━┫ T ┃
|
|
||||||
; ┃ 2 ┃ Y ┃
|
|
||||||
; ┣━━┫ P ┃
|
|
||||||
; ┃ 1 ┃ E ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; ┃ 0 ┃ ┃
|
|
||||||
; ------ ┣━━╋━━┫
|
|
||||||
; ┃ 23 ┃ ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; ┃ 22 ┃ ┃
|
|
||||||
; ┣━━┫ 段 ┃
|
|
||||||
;
|
|
||||||
; 字节 ┆ ┆ 基 ┆
|
|
||||||
; 2, 3, 4
|
|
||||||
; ┣━━┫ 址 ┃
|
|
||||||
; ┃ 1 ┃ ① ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; ┃ 0 ┃ ┃
|
|
||||||
; ------ ┣━━╋━━┫
|
|
||||||
; ┃ 15 ┃ ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; ┃ 14 ┃ ┃
|
|
||||||
; ┣━━┫ 段 ┃
|
|
||||||
;
|
|
||||||
; 字节 0,1┆ ┆ 界 ┆
|
|
||||||
;
|
|
||||||
; ┣━━┫ 限 ┃
|
|
||||||
; ┃ 1 ┃ ① ┃
|
|
||||||
; ┣━━┫ ┃
|
|
||||||
; ┃ 0 ┃ ┃
|
|
||||||
; ------ ┗━━┻━━┛低地址
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
; 图示二
|
|
||||||
|
|
||||||
; 高地址………………………………………………………………………低地址
|
|
||||||
|
|
||||||
; | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
|
||||||
; |7654321076543210765432107654321076543210765432107654321076543210| <- 共 8 字节
|
|
||||||
; |--------========--------========--------========--------========|
|
|
||||||
; ┏━━━┳━━━━━━━┳━━━━━━━━━━━┳━━━━━━━┓
|
|
||||||
; ┃31..24┃ (见下图) ┃ 段基址(23..0) ┃ 段界限(15..0)┃
|
|
||||||
; ┃ ┃ ┃ ┃ ┃
|
|
||||||
; ┃ 基址2┃③│②│ ①┃基址1b│ 基址1a ┃ 段界限1 ┃
|
|
||||||
; ┣━━━╋━━━┳━━━╋━━━━━━━━━━━╋━━━━━━━┫
|
|
||||||
; ┃ %6 ┃ %5 ┃ %4 ┃ %3 ┃ %2 ┃ %1 ┃
|
|
||||||
; ┗━━━┻━━━┻━━━┻━━━┻━━━━━━━┻━━━━━━━┛
|
|
||||||
; │ \_________
|
|
||||||
; │ \__________________
|
|
||||||
; │ \________________________________________________
|
|
||||||
; │ \
|
|
||||||
; ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
|
|
||||||
; ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃
|
|
||||||
; ┣━━╋━━╋━━╋━━╋━━┻━━┻━━┻━━╋━━╋━━┻━━╋━━╋━━┻━━┻━━┻━━┫
|
|
||||||
; ┃ G ┃ D ┃ 0 ┃ AVL┃ 段界限 2 (19..16) ┃ P ┃ DPL ┃ S ┃ TYPE ┃
|
|
||||||
; ┣━━┻━━┻━━┻━━╋━━━━━━━━━━━╋━━┻━━━━━┻━━┻━━━━━━━━━━━┫
|
|
||||||
; ┃ ③: 属性 2 ┃ ②: 段界限 2 ┃ ①: 属性1 ┃
|
|
||||||
; ┗━━━━━━━━━━━┻━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
||||||
; 高地址 低地址
|
|
||||||
;
|
|
||||||
;
|
|
||||||
|
|
||||||
; 说明:
|
|
||||||
;
|
|
||||||
; (1) P: 存在(Present)位。
|
|
||||||
; P=1 表示描述符对地址转换是有效的,或者说该描述符所描述的段存在,即在内存中;
|
|
||||||
; P=0 表示描述符对地址转换无效,即该段不存在。使用该描述符进行内存访问时会引起异常。
|
|
||||||
;
|
|
||||||
; (2) DPL: 表示描述符特权级(Descriptor Privilege level),共2位。它规定了所描述段的特权级,用于特权检查,以决定对该段能否访问。
|
|
||||||
;
|
|
||||||
; (3) S: 说明描述符的类型。
|
|
||||||
; 对于存储段描述符而言,S=1,以区别与系统段描述符和门描述符(S=0)。
|
|
||||||
;
|
|
||||||
; (4) TYPE: 说明存储段描述符所描述的存储段的具体属性。
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; 数据段类型 类型值 说明
|
|
||||||
; ----------------------------------
|
|
||||||
; 0 只读
|
|
||||||
; 1 只读、已访问
|
|
||||||
; 2 读/写
|
|
||||||
; 3 读/写、已访问
|
|
||||||
; 4 只读、向下扩展
|
|
||||||
; 5 只读、向下扩展、已访问
|
|
||||||
; 6 读/写、向下扩展
|
|
||||||
; 7 读/写、向下扩展、已访问
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; 类型值 说明
|
|
||||||
; 代码段类型 ----------------------------------
|
|
||||||
; 8 只执行
|
|
||||||
; 9 只执行、已访问
|
|
||||||
; A 执行/读
|
|
||||||
; B 执行/读、已访问
|
|
||||||
; C 只执行、一致码段
|
|
||||||
; D 只执行、一致码段、已访问
|
|
||||||
; E 执行/读、一致码段
|
|
||||||
; F 执行/读、一致码段、已访问
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; 系统段类型 类型编码 说明
|
|
||||||
; ----------------------------------
|
|
||||||
; 0 <未定义>
|
|
||||||
; 1 可用286TSS
|
|
||||||
; 2 LDT
|
|
||||||
; 3 忙的286TSS
|
|
||||||
; 4 286调用门
|
|
||||||
; 5 任务门
|
|
||||||
; 6 286中断门
|
|
||||||
; 7 286陷阱门
|
|
||||||
; 8 未定义
|
|
||||||
; 9 可用386TSS
|
|
||||||
; A <未定义>
|
|
||||||
; B 忙的386TSS
|
|
||||||
; C 386调用门
|
|
||||||
; D <未定义>
|
|
||||||
; E 386中断门
|
|
||||||
; F 386陷阱门
|
|
||||||
;
|
|
||||||
; (5) G: 段界限粒度(Granularity)位。
|
|
||||||
; G=0 表示界限粒度为字节;
|
|
||||||
; G=1 表示界限粒度为4K 字节。
|
|
||||||
; 注意,界限粒度只对段界限有效,对段基地址无效,段基地址总是以字节为单位。
|
|
||||||
;
|
|
||||||
; (6) D: D位是一个很特殊的位,在描述可执行段、向下扩展数据段或由SS寄存器寻址的段(通常是堆栈段)的三种描述符中的意义各不相同。
|
|
||||||
; ⑴ 在描述可执行段的描述符中,D位决定了指令使用的地址及操作数所默认的大小。
|
|
||||||
; ① D=1表示默认情况下指令使用32位地址及32位或8位操作数,这样的代码段也称为32位代码段;
|
|
||||||
; ② D=0 表示默认情况下,使用16位地址及16位或8位操作数,这样的代码段也称为16位代码段,它与80286兼容。可以使用地址大小前缀和操作数大小前缀分别改变默认的地址或操作数的大小。
|
|
||||||
; ⑵ 在向下扩展数据段的描述符中,D位决定段的上部边界。
|
|
||||||
; ① D=1表示段的上部界限为4G;
|
|
||||||
; ② D=0表示段的上部界限为64K,这是为了与80286兼容。
|
|
||||||
; ⑶ 在描述由SS寄存器寻址的段描述符中,D位决定隐式的堆栈访问指令(如PUSH和POP指令)使用何种堆栈指针寄存器。
|
|
||||||
; ① D=1表示使用32位堆栈指针寄存器ESP;
|
|
||||||
; ② D=0表示使用16位堆栈指针寄存器SP,这与80286兼容。
|
|
||||||
;
|
|
||||||
; (7) AVL: 软件可利用位。80386对该位的使用未左规定,Intel公司也保证今后开发生产的处理器只要与80386兼容,就不会对该位的使用做任何定义或规定。
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 描述符类型值说明
|
|
||||||
; 其中:
|
|
||||||
; DA_ : Descriptor Attribute
|
|
||||||
; D : 数据段
|
|
||||||
; C : 代码段
|
|
||||||
; S : 系统段
|
|
||||||
; R : 只读
|
|
||||||
; RW : 读写
|
|
||||||
; A : 已访问
|
|
||||||
; 其它 : 可按照字面意思理解
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
DA_32 EQU 4000h ; 32 位段
|
|
||||||
DA_LIMIT_4K EQU 8000h ; 段界限粒度为 4K 字节
|
|
||||||
|
|
||||||
DA_DPL0 EQU 00h ; DPL = 0
|
|
||||||
DA_DPL1 EQU 20h ; DPL = 1
|
|
||||||
DA_DPL2 EQU 40h ; DPL = 2
|
|
||||||
DA_DPL3 EQU 60h ; DPL = 3
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 存储段描述符类型值说明
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
DA_DR EQU 90h ; 存在的只读数据段类型值
|
|
||||||
DA_DRW EQU 92h ; 存在的可读写数据段属性值
|
|
||||||
DA_DRWA EQU 93h ; 存在的已访问可读写数据段类型值
|
|
||||||
DA_C EQU 98h ; 存在的只执行代码段属性值
|
|
||||||
DA_CR EQU 9Ah ; 存在的可执行可读代码段属性值
|
|
||||||
DA_CCO EQU 9Ch ; 存在的只执行一致代码段属性值
|
|
||||||
DA_CCOR EQU 9Eh ; 存在的可执行可读一致代码段属性值
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 系统段描述符类型值说明
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
DA_LDT EQU 82h ; 局部描述符表段类型值
|
|
||||||
DA_TaskGate EQU 85h ; 任务门类型值
|
|
||||||
DA_386TSS EQU 89h ; 可用 386 任务状态段类型值
|
|
||||||
DA_386CGate EQU 8Ch ; 386 调用门类型值
|
|
||||||
DA_386IGate EQU 8Eh ; 386 中断门类型值
|
|
||||||
DA_386TGate EQU 8Fh ; 386 陷阱门类型值
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
; 选择子图示:
|
|
||||||
; ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
|
|
||||||
; ┃ 15 ┃ 14 ┃ 13 ┃ 12 ┃ 11 ┃ 10 ┃ 9 ┃ 8 ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃
|
|
||||||
; ┣━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━╋━━╋━━┻━━┫
|
|
||||||
; ┃ 描述符索引 ┃ TI ┃ RPL ┃
|
|
||||||
; ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━┻━━━━━┛
|
|
||||||
;
|
|
||||||
; RPL(Requested Privilege Level): 请求特权级,用于特权检查。
|
|
||||||
;
|
|
||||||
; TI(Table Indicator): 引用描述符表指示位
|
|
||||||
; TI=0 指示从全局描述符表GDT中读取描述符;
|
|
||||||
; TI=1 指示从局部描述符表LDT中读取描述符。
|
|
||||||
;
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 选择子类型值说明
|
|
||||||
; 其中:
|
|
||||||
; SA_ : Selector Attribute
|
|
||||||
|
|
||||||
SA_RPL0 EQU 0 ; ┓
|
|
||||||
SA_RPL1 EQU 1 ; ┣ RPL
|
|
||||||
SA_RPL2 EQU 2 ; ┃
|
|
||||||
SA_RPL3 EQU 3 ; ┛
|
|
||||||
|
|
||||||
SA_TIG EQU 0 ; ┓TI
|
|
||||||
SA_TIL EQU 4 ; ┛
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; 分页机制使用的常量说明
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
PG_P EQU 1 ; 页存在属性位
|
|
||||||
PG_RWR EQU 0 ; R/W 属性位值, 读/执行
|
|
||||||
PG_RWW EQU 2 ; R/W 属性位值, 读/写/执行
|
|
||||||
PG_USS EQU 0 ; U/S 属性位值, 系统级
|
|
||||||
PG_USU EQU 4 ; U/S 属性位值, 用户级
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; =========================================
|
|
||||||
; FLAGS - Intel 8086 Family Flags Register
|
|
||||||
; =========================================
|
|
||||||
;
|
|
||||||
; |11|10|F|E|D|C|B|A|9|8|7|6|5|4|3|2|1|0|
|
|
||||||
; | | | | | | | | | | | | | | | | | '--- CF……Carry Flag
|
|
||||||
; | | | | | | | | | | | | | | | | '--- 1
|
|
||||||
; | | | | | | | | | | | | | | | '--- PF……Parity Flag
|
|
||||||
; | | | | | | | | | | | | | | '--- 0
|
|
||||||
; | | | | | | | | | | | | | '--- AF……Auxiliary Flag
|
|
||||||
; | | | | | | | | | | | | '--- 0
|
|
||||||
; | | | | | | | | | | | '--- ZF……Zero Flag
|
|
||||||
; | | | | | | | | | | '--- SF……Sign Flag
|
|
||||||
; | | | | | | | | | '--- TF……Trap Flag (Single Step)
|
|
||||||
; | | | | | | | | '--- IF……Interrupt Flag
|
|
||||||
; | | | | | | | '--- DF……Direction Flag
|
|
||||||
; | | | | | | '--- OF……Overflow flag
|
|
||||||
; | | | | '----- IOPL……I/O Privilege Level (286+ only)
|
|
||||||
; | | | '----- NT……Nested Task Flag (286+ only)
|
|
||||||
; | | '----- 0
|
|
||||||
; | '----- RF……Resume Flag (386+ only)
|
|
||||||
; '------ VM……Virtual Mode Flag (386+ only)
|
|
||||||
;
|
|
||||||
; 注: see PUSHF POPF STI CLI STD CLD
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
; 宏 ------------------------------------------------------------------------------------------------------
|
|
||||||
;
|
|
||||||
; 描述符
|
|
||||||
; usage: Descriptor Base, Limit, Attr
|
|
||||||
; Base: dd
|
|
||||||
; Limit: dd (low 20 bits available)
|
|
||||||
; Attr: dw (lower 4 bits of higher byte are always 0)
|
|
||||||
%macro Descriptor 3
|
|
||||||
dw %2 & 0FFFFh ; 段界限 1 (2 字节)
|
|
||||||
dw %1 & 0FFFFh ; 段基址 1 (2 字节)
|
|
||||||
db (%1 >> 16) & 0FFh ; 段基址 2 (1 字节)
|
|
||||||
dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性 1 + 段界限 2 + 属性 2 (2 字节)
|
|
||||||
db (%1 >> 24) & 0FFh ; 段基址 3 (1 字节)
|
|
||||||
%endmacro ; 共 8 字节
|
|
||||||
;
|
|
||||||
; 门
|
|
||||||
; usage: Gate Selector, Offset, DCount, Attr
|
|
||||||
; Selector: dw
|
|
||||||
; Offset: dd
|
|
||||||
; DCount: db
|
|
||||||
; Attr: db
|
|
||||||
%macro Gate 4
|
|
||||||
dw (%2 & 0FFFFh) ; 偏移 1 (2 字节)
|
|
||||||
dw %1 ; 选择子 (2 字节)
|
|
||||||
dw (%3 & 1Fh) | ((%4 << 8) & 0FF00h) ; 属性 (2 字节)
|
|
||||||
dw ((%2 >> 16) & 0FFFFh) ; 偏移 2 (2 字节)
|
|
||||||
%endmacro ; 共 8 字节
|
|
||||||
; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
1064
boot/grub/loader.asm
1064
boot/grub/loader.asm
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user