【OS】07 – 突破512字节的限制(中)【主要内容:内存比较函数 MemCmp 和根目录区查找函数 FindEntry 】

原理参考:【OS】07 – 突破512字节的限制(中)

 

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

 

结果:

file

 

1.2 不相等字符串验证

代码中的字符串修改一下
;some str and length
MsgStr db  "Magic!!"    
MsgLen equ ($-MsgStr)
Target db  "Magic!?"
TarLen equ ($-Target)

 
现象:

file

 

1.3 断点调试

断点调试:

反编译一下

file

 

找到下断点的地址

file

 

打印寄存器的值,发现cx为1,比较的两个内存不相等;

视频里错误纠正:"cx为1意味着比较最后一个字符失败了", 这句话是视频里讲错了,cx为1,是字符串比较之后的返回结果;

file

 

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?

file

 

2.2 调试验证文件名是否存在

如果证明这次的验证是正确的?查看dx是否为0

反编译

file

 
打断点,查看寄存器输出值,dx不为0,能够在内存中找到这个文件

file

 

如果证明这次的验证是正确的?查看img中是否存在这个文件

存在这个文件

file

 

2.3 文件名不存在的情况

这里把比较的文件名字符串修改,查找一个name不存在的现象:

MsgStr db  "No LOADER ..."    
MsgLen equ ($-MsgStr)
Target db  "LOADER-    "
TarLen equ ($-Target)

file

 

断点调试,查看dx的值是否为0

dx的值为0

file

 
 

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇