本文最后更新于 294 天前,其中的信息可能已经有所发展或是发生改变。
内容目录
0x01 验证1:内存比较函数 MemCmp
1.1 code
;@
;目的: 验证MemCmp函数
;参考此函数调用即可
org 0x7c00
jmp short start
nop
define:
BaseOfStack equ 0x7c00
;start from here
start:
mov ax, cs
mov ss, ax
mov ds, ax
mov es, ax
mov sp, BaseOfStack
; test MemCmp
mov si,MsgStr
mov di,Target
mov cx,MsgLen
call MemCmp
cmp cx,0
jz lable
jmp last
lable:
mov bp,MsgStr
mov cx,MsgLen
call Print
last:
hlt
jmp last
; ds:si --> source
; es:di --> destination
; cx --> length
;
; return:
; (cx == 0) ? equal : noequal
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
; es:bp --> string address
; cx --> string length
Print:
mov ax, 0x1301
mov bx, 0x0007
int 0x10
ret
;some str and length
MsgStr db "Magic!!"
MsgLen equ ($-MsgStr)
Target db "Magic!!"
TarLen equ ($-Target)
Buf:
times 510-($-$$) db 0x00
db 0x55, 0xaa
结果:
1.2 不相等字符串验证
代码中的字符串修改一下
;some str and length
MsgStr db "Magic!!"
MsgLen equ ($-MsgStr)
Target db "Magic!?"
TarLen equ ($-Target)
现象:
1.3 断点调试
断点调试:
反编译一下
找到下断点的地址
打印寄存器的值,发现cx为1,比较的两个内存不相等;
视频里错误纠正:"cx为1意味着比较最后一个字符失败了", 这句话是视频里讲错了,cx为1,是字符串比较之后的返回结果;
0x02 验证2: 根目录区查找函数
2.1 code
org 0x7c00
;补上三个字节
jmp short start
nop
;栈的起始地址(定义栈空间)
define:
BaseOfStack equ 0x7c00
RootEntryOffset equ 19 ;根目录区的逻辑扇区地址,是从逻辑第19扇区开始的
RootEntryLength equ 14 ;目录文件项占用了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
push cx
mov dx, [BPB_RootEntCnt];根目录区的最大项,最大查找次数
mov bp, sp ;栈顶元素不能通过sp直接访问,这里间接访问
find:
cmp dx, 0
jz noexist
mov di, bx ;初始化的di指向根目录区的第0项 si di cx
; 'mov cx, [bp]' 指令的作用是将bp寄存器当前指向的栈内存地址中的值赋给cx寄存器。
; 在这个上下文中,bp寄存器被用作一个间接的方式来访问栈顶的值,因为我们之前已经将sp(栈指针)的值赋给了bp。
; 这里的关键操作是将cx寄存器之前压栈的值(即目标字符串的长度)重新加载到cx寄存器中。
; 这一步是为了准备接下来的MemCmp函数调用,因为在MemCmp中,cx寄存器的值将被用作要比较的字节数。
; 简而言之,这条指令的目的是恢复cx寄存器的原始值,以便能够正确地进行内存比较操作。
mov cx, [bp]
call MemCmp
cmp cx, 0
jz exist
add bx, 32 ;查找下一项,每一项占用32字节
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:
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
; 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] ; BPB_SecPerTrk 每个柱面18个扇区
div bl ; =》 逻辑扇区号 / 柱面扇区数 =》ax / bl
mov cl, ah
add cl, 1 ; 余数+1 表示扇区号
mov ch, al
shr ch, 1 ; 柱面号
mov dh, al
and dh, 1 ;磁头号
mov dl, [BS_DrvNum] ; 驱动器号
pop ax ;扇区长度出栈,放到al里
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
输出结果: 没有输出对应的字符串,文件应该是存在的,那就看下文件中是否存在这个文件?dx是否为0?
2.2 调试验证文件名是否存在
如果证明这次的验证是正确的?查看dx是否为0
反编译
打断点,查看寄存器输出值,dx不为0,能够在内存中找到这个文件
如果证明这次的验证是正确的?查看img中是否存在这个文件
存在这个文件
2.3 文件名不存在的情况
这里把比较的文件名字符串修改,查找一个name不存在的现象:
MsgStr db "No LOADER ..."
MsgLen equ ($-MsgStr)
Target db "LOADER- "
TarLen equ ($-Target)
断点调试,查看dx的值是否为0
dx的值为0