【OS】06 – 突破512字节的限制(上)

参考: 【OS】06 – 突破512字节的限制(上)

 

0x01 定义栈空间

sp寄存器的值

为什么要用0x7c00用作栈的起始地址?

程序执行从0x7c00从低地址到高地址执行;栈的增长方向是高地址到低地址(和程序执行方向相反);

用0x7c00作为栈的起始地址是可以的,函数调用的操作(栈增长)不会影响程序的执行;

file

 

0x02 读取数据

需要的文件

bochsrc

###############################################################
# Configuration file for Bochs
###############################################################

# how much memory the emulated machine will have
megs: 32

# filename of ROM images
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/vgabios/vgabios.bin

# what disk images will be used
floppya: 1_44=data.img, status=inserted

# choose the boot disk.
boot: a

# where do we send log messages?
# log: bochsout.txt

# disable the mouse
mouse: enabled=0

# enable key mapping, using US layout as default.
keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/x11-pc-us.map

 
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

 
boot.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 ;sp指向栈的起始地址,这样就有栈空间了

    mov ax, 34  ; 读取自己计算出来的扇区号
    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]  ; 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    ;扇区长度出栈,放到ax里
    pop bx

    mov ah, 0x02 ; 规定值

read:   ;读取失败就继续读
    int 0x13
    jc read

    pop ax
    pop dx
    pop cx
    pop bx

    ret

MsgStr db  "Hello, DTOS!"    
MsgLen equ ($-MsgStr) ; 地址差就是长度了
Buf:
    times 510-($-$$) db 0x00
    db 0x55, 0xaa

 

2.1 测试方法:

在windows上用vs2019打开img文件,搜到自己写的文件内容,接下来就要读取这个字符串;

确定这个字符串位于那个扇区 : 0x4400转换为十进制17408, 17408 / 512 = 34 位于34扇区(逻辑扇区号)第0字节处; 字符串长度:29

打印出来,看是否是这个字符串

file

 

2.2 结果分析

发现一个问题: 这个数据长度无论设置为多大,都可以完整读取整个字符串,每次读取一个扇区的原因吗?

那这个字符串的长度就没有必要设置了,后来发现不设置也是可以的;

file

 

0x03 调试

反编译出bin文件,再通过bin文件反编译出函数地址信息出来,通过调试 查看寄存器和内存的状态是否是期望的状态;

反编译命令: ndisasm -o 0x7c00 boot.bin > boot.txt

从0x7c00处开始,在 boot.txt中可以查找到函数对应的地址,进一步就可以调试了

file

暂无评论

发送评论 编辑评论


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