学习自狄泰软件
1 cmp比较、相等的话jz跳转
2 不能使用sp直接访问栈顶数据,需要通过其它寄存器间接访问栈顶数据
回忆前面的知识,我们知道 文件系统中存在根目录区,根目录区由目录项组成,每个目录项代表根目录中的一个文件索引
所以我们可以根据目录项的前 11 个字节判断文件属性(名字等等),具体方法就是逐个比较这11个字节的空间,内存比较
[si] 将si 寄存器中存储的 地址所代表的空间出 取一个字节数据
[di] 同理
实验代码:
org 0x7c00
jmp short start
nop
define:
BaseOfStack equ 0x7c00
;根目录区起始扇区位置 第19扇区
RootEntryOffset equ 19
;根目录区占用14个扇区
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
; es:bx --> root entry offset address 根目录区的起始地址
; ds:si --> target string 目标字符串
; cx --> target length 字符串长度
;
; return:
; (dx != 0) ? exist : noexist
; exist --> bx is the target entry
FindEntry:
push di
push bp
;由于需要反复调用 MemCmp() 所以先将 cx寄存器值入栈保存
push cx
;根目录区最大查找次数 即 多少个目录项 224
mov dx, [BPB_RootEntCnt]
;此时 cx寄存器值在栈顶,所以此时是获取 cx寄存器的值,即获取目标字符串长度
mov bp, sp
find:
cmp dx, 0
jz noexist
;bx 根目录区中每一项的入口地址
mov di, bx
mov cx, [bp]
call MemCmp
;注意 查找结果放在cx寄存器中,这个查看查找结果
cmp cx, 0
;如果cx寄存器值是0 则查找成功 直接跳转到 exit 退出
jz exist
;如果查找不成功 则继续查找下一项。改变bx 寄存器值(每一项占用32字节,移动32字节到下一项入口)
add bx, 32
;dx减1
dec dx
jmp find
exist:
noexist:
pop cx
pop bp
pop di
ret
; ds:si --> source
; es:di --> destination
; cx --> length
;
; return:
; (cx == 0) ? equal : noequal
MemCmp:
;备份寄存器 进栈保存, 这里没有保存cx寄存器值 是因为 cx寄存器是作为返回值使用的,没必要保存
push si
push di
push ax
;循环
compare:
;比较cx寄存器值是否为0 如果是的话 比较相等,则跳转到 equal标签
cmp cx, 0
jz equal
;如果不相等 则继续字节比较,将si 寄存器中存储的 地址所代表的空间出 取一个字节数据,给al 寄存器
mov al, [si]
;用 al 寄存器中的值 和 di 寄存器中存储的 地址所代表的空间的一个字节 比较
cmp al, byte [di]
;比较相等 则继续比较下一个字节,即跳转到 goon标签处继续比较
jz goon
;如果不相等 则跳转到 noequal 标签
jmp noequal
goon:
; == si++ 理解为指针移位
inc si
inc di
; cx 自减 cx--
dec cx
;继续比较 跳转到compare标签
jmp compare
equal:
noequal:
;还原寄存器 出栈还原
pop ax
pop di
pop si
ret
; 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 bx
mov ah, 0x02
read:
int 0x13
jc read
pop ax
pop dx
pop cx
pop bx
ret
MsgStr db "No LOADER ..."
MsgLen equ ($-MsgStr)
Target db "LOADER "
TarLen equ ($-Target)
Buf:
times 510-($-$$) db 0x00
db 0x55, 0xaa