您好,登錄后才能下訂單哦!
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
從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
打印的字符串的結果
但是在設置的時候并沒有打印函數,所以要在asm文件對匯編代碼進行改進
在這里要進行三步--1.首先對打印函數進行了定義2.然后對棧空間進行定義--定義起始地址3.最后將sp棧頂指針寄存器指向定義棧的起始地址處
A.軟盤的構造
1.一個軟盤有兩個盤面,每個盤面對應一個磁頭
2.每一個盤面被劃分為若干個圓圈,成為柱面
3.每一個柱面被劃分為若干個扇區,每個扇區512字節
軟盤數據的讀寫--軟盤數據一扇區512字節為單位進行讀取,指定數據所在位置的磁頭號,柱面號,扇區號。它的計算公式為
在BIOS中的軟盤數據讀取(int 0x13)
軟盤數據的讀寫流程
在這里我們需要注意的是,匯編中的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.對其進行驗證,看其打印結果
小結
1.當匯編代碼中定義了函數,那么需要定義棧空間
2.讀取數據前,邏輯扇區號需要轉化為磁盤的物理位置
3.物理軟盤上的數據位置由磁頭號,柱面號,扇區唯一確定
4.軟盤數據以扇區512為單位進行讀取
在這里我們要做的是
整體進行的思路是
Q:現在的問題是如何在根目錄中查找目標文件?
A.內存比較
1.指定源起始地址(DS:SI)
2.指定目標起始地址(ES:DI)
3.判斷在期望長度(CX)內每一個字節是否都相等
匯編中比較和跳轉命令
cmp cx,0--比較cx的值是否為0
jz equal--如果比較的結果為真,則跳轉到equal標簽處
B.需要一個內存比較函數,然后查找根目錄區是否存在目標文件
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
打印的結果
從打印結果可以知道調用了在前面的比較函數中的label下的print函數,由此可得cx寄存器為,可以得到兩個寄存器的地址是相等的
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。