操作系统--突破512字节的限制

一.在突破512字节

操作系统--突破512字节的限制
Q:主引导程序中如何进行字符串打印?--直接打印
A.BIOS中的字符串打印

1.指定打印参数(AX=0x1301,BX=0x0007)--不借助循环
2.指定字符串的内存地址(ES:BP=串地址)--通过段地址与段偏移来确定
3.指定字符串的长度(CX=串长度)
4.中断调用(int 0x10)

B.汇编小贴士
1.汇编中可以定义函数--函数名使用标签定义
call function;函数体的最后一条指令为ret
2.如果代码中定义了函数,那么需要定义栈空间
主要用于保存关键寄存器的值;栈顶地址通过sp寄存器保存
3.汇编中的"常量定义"--equ
用法是-Const equ 0x7c00;它同时与dx(db,dw,dd)有区别,区别主要在dx定义占用相应的内存空间,equ定义不会占用任何内存空间
C.实验-定义打印函数
a.首先可以利用makefile将主引导程序的创建以及二进制编译文件的创建过程简单化

.PHONY : all clean rebuild

SRC := boot.asm
OUT := boot.bin
IMG := data.img

RM := rm -fr

all : $(OUT) $(IMG)
    dd if=$(OUT) of=$(IMG) bs=512 count=1 conv=notrunc
    @echo "Success!"

$(IMG) :
    bximage $@ -q -fd -size=1.44

$(OUT) : $(SRC)
    nasm $^ -o $@

clean :
    $(RM) $(IMG) $(OUT)

rebuild :
    @$(MAKE) clean
    @$(MAKE) all

操作系统--突破512字节的限制
从make的结果可以看出,运行成功,这样使得之后的修改编译过程变的简便
对boot.asm 文件进行设置

org 0x7c00

jmp short start
nop

start:
    mov ax, cs
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov sp, ax

    mov ax, MsgStr//打印的汇编实现
    mov cx, 6

    mov bp, ax
    mov ax, ds
    mov es, ax
    mov ax, 0x1301
    mov bx, 0x0007 

    int 0x10

last:
    hlt
    jmp last    

MsgStr db  "MyDTOS ..."  //打印的字符串
Buf:
    times 510-($-$$) db 0x00
    db 0x55, 0xaa

打印的字符串的结果
操作系统--突破512字节的限制
但是在设置的时候并没有打印函数,所以要在asm文件对汇编代码进行改进操作系统--突破512字节的限制
在这里要进行三步--1.首先对打印函数进行了定义2.然后对栈空间进行定义--定义起始地址3.最后将sp栈顶指针寄存器指向定义栈的起始地址处

二.主引导程序中如何读取指定扇区处的数据?

A.软盘的构造
1.一个软盘有两个盘面,每个盘面对应一个磁头
2.每一个盘面被划分为若干个圆圈,成为柱面
3.每一个柱面被划分为若干个扇区,每个扇区512字节
操作系统--突破512字节的限制
软盘数据的读写--软盘数据一扇区512字节为单位进行读取,指定数据所在位置的磁头号,柱面号,扇区号。它的计算公式为
操作系统--突破512字节的限制
在BIOS中的软盘数据读取(int 0x13)
操作系统--突破512字节的限制
软盘数据的读写流程
操作系统--突破512字节的限制
在这里我们需要注意的是,汇编中的16为除法操作(div)--被除数放到AX寄存器,除数放到通用寄存器或内存单元(8位),结果是商位于AL,余数位于AH
1.先根据上面提到的知识对asm文件进行修改,以及对虚拟软盘进行查看

org 0x7c00

jmp short start
nop

define:
    BaseOfStack equ 0x7c00

header:
    BS_OEMName     db "D.T.Soft"
    BPB_BytsPerSec dw 512
    BPB_SecPerClus db 1
    BPB_RsvdSecCnt dw 1
    BPB_NumFATs    db 2
    BPB_RootEntCnt dw 224
    BPB_TotSec16   dw 2880
    BPB_Media      db 0xF0
    BPB_FATSz16    dw 9
    BPB_SecPerTrk  dw 18
    BPB_NumHeads   dw 2
    BPB_HiddSec    dd 0
    BPB_TotSec32   dd 0
    BS_DrvNum      db 0
    BS_Reserved1   db 0
    BS_BootSig     db 0x29
    BS_VolID       dd 0
    BS_VolLab      db "D.T.OS-0.01"
    BS_FileSysType db "FAT12   "

start:
    mov ax, cs
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov sp, BaseOfStack

    mov ax, 34//读取的为34扇区的原因是将data.img以二进制进行查看时 它是在34扇区 有29个字节
    mov cx, 1
    mov bx, Buf

    call ReadSector

    mov bp, Buf
    mov cx, 29

    call Print

last:
    hlt
    jmp last    

; es:bp --> string address
; cx    --> string length
Print:
    mov ax, 0x1301
    mov bx, 0x0007
    int 0x10
    ret

; no parameter
ResetFloppy://写入软驱
    push ax
    push dx//入栈

    mov ah, 0x00
    mov dl, [BS_DrvNum]
    int 0x13

    pop dx
    pop ax//出栈

    ret

; ax    --> logic sector number
; cx    --> number of sector
; es:bx --> target address
ReadSector://读取软驱
    push bx
    push cx
    push dx
    push ax

    call ResetFloppy

    push bx
    push cx

    mov bl, [BPB_SecPerTrk]
    div bl
    mov cl, ah//余数
    add cl, 1//计算扇区号
    mov ch, al//商
    shr ch, 1//商右移以为  柱面号
    mov dh, al
    and dh, 1//磁头号
    mov dl, [BS_DrvNum]

    pop ax
    pop bxa

    mov ah, 0x02

read:    
    int 0x13
    jc read//读取失败  再进行读取

    pop ax
    pop dx
    pop cx
    pop bx

    ret

MsgStr db  "MyDTOS!"    
MsgLen equ ($-MsgStr)
Buf:
    times 510-($-$$) db 0x00
    db 0x55, 0xaa

2.对其进行验证,看其打印结果
操作系统--突破512字节的限制
小结
1.当汇编代码中定义了函数,那么需要定义栈空间
2.读取数据前,逻辑扇区号需要转化为磁盘的物理位置
3.物理软盘上的数据位置由磁头号,柱面号,扇区唯一确定
4.软盘数据以扇区512为单位进行读取

三.突破512字节下

在这里我们要做的是
操作系统--突破512字节的限制
整体进行的思路是
操作系统--突破512字节的限制
Q:现在的问题是如何在根目录中查找目标文件?
A.内存比较

1.指定源起始地址(DS:SI)
2.指定目标起始地址(ES:DI)
3.判断在期望长度(CX)内每一个字节是否都相等
操作系统--突破512字节的限制
汇编中比较和跳转命令
cmp cx,0--比较cx的值是否为0
jz equal--如果比较的结果为真,则跳转到equal标签处
B.需要一个内存比较函数,然后查找根目录区是否存在目标文件
操作系统--突破512字节的限制

org 0x7c00

jmp short start
nop

define:
    BaseOfStack      equ 0x7c00
    RootEntryOffset  equ 19
    RootEntryLength  equ 14

header:
    BS_OEMName     db "D.T.Soft"
    BPB_BytsPerSec dw 512
    BPB_SecPerClus db 1
    BPB_RsvdSecCnt dw 1
    BPB_NumFATs    db 2
    BPB_RootEntCnt dw 224
    BPB_TotSec16   dw 2880
    BPB_Media      db 0xF0
    BPB_FATSz16    dw 9
    BPB_SecPerTrk  dw 18
    BPB_NumHeads   dw 2
    BPB_HiddSec    dd 0
    BPB_TotSec32   dd 0
    BS_DrvNum      db 0
    BS_Reserved1   db 0
    BS_BootSig     db 0x29
    BS_VolID       dd 0
    BS_VolLab      db "D.T.OS-0.01"
    BS_FileSysType db "FAT12   "

start:
    mov ax, cs
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov sp, BaseOfStack

    mov ax, RootEntryOffset
    mov cx, RootEntryLength
    mov bx, Buf

    call ReadSector

    mov si, Target
    mov cx, TarLen
    mov dx, 0

    call FindEntry

    cmp dx, 0
    jz output
    jmp last

output:    
    mov bp, MsgStr
    mov cx, MsgLen
    call Print

last:
    hlt
    jmp last    

exist:
noexist:
    pop cx
    pop bp
    pop di

    ret

MemCmp:
    push si
    push di
    push ax

compare://比较函数的实现
    cmp cx, 0
    jz equal
    mov al, [si]
    cmp al, byte [di]
    jz goon
    jmp noequal
goon:
    inc si
    inc di
    dec cx
    jmp compare

equal:
noequal:   //不相等时
    pop ax
    pop di
    pop si

    ret

Print:
    mov ax, 0x1301
    mov bx, 0x0007
    int 0x10
    ret

; no parameter
ResetFloppy:
    push ax
    push dx

    mov ah, 0x00
    mov dl, [BS_DrvNum]
    int 0x13

    pop dx
    pop ax

    ret

ReadSector:
    push bx
    push cx
    push dx
    push ax

    call ResetFloppy

    push bx
    push cx

    mov bl, [BPB_SecPerTrk]
    div bl
    mov cl, ah
    add cl, 1
    mov ch, al
    shr ch, 1
    mov dh, al
    and dh, 1
    mov dl, [BS_DrvNum]

    pop ax
    pop bx

    mov ah, 0x02

read:    
    int 0x13
    jc read

    pop ax
    pop dx
    pop cx
    pop bx

    ret

MsgStr db  "MyDTOS!"    
MsgLen equ ($-MsgStr)
Target db  "MyDTOS!"
TarLen equ ($-Target)
Buf:
    times 510-($-$$) db 0x00
    db 0x55, 0xaa

操作系统--突破512字节的限制
打印的结果
操作系统--突破512字节的限制
从打印结果可以知道调用了在前面的比较函数中的label下的print函数,由此可得cx寄存器为,可以得到两个寄存器的地址是相等的

猜你喜欢

转载自blog.51cto.com/13475106/2445861