突破512字节限制

主引导程序中如何进行字符串打印?

汇编中的常量定义
Const equ 0x7c00 == c语言 #define Const 0x7c00
主引导程序
org 0x7c00 ; IP = 0x7c00 jmp short start ;占用两字节 nop ;占用一字节 define: ;自己定义栈空间 BaseOfStack equ 0x7c00 ;#define BaseOfStack 0x7c00 栈从高地址向低地址增长,与代码段无影响 ;主引导区(0扇区)的必要信息 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 bp, MsgStr ;指定字符串地址 mov cx, MsgLen ;指定字符串长度 call Print last: hlt jmp last ;打印字符串函数 ; es:bp --> string address ; cx --> string length Print: mov ax, 0x1301 ;指定打印参数 mov bx, 0x0007 ;指定打印参数 int 0x10 ;执行0x10号中断 ret MsgStr db "Hello, DTOS!" MsgLen equ ($-MsgStr) Buf: times 510-($-$$) db 0x00 db 0x55, 0xaa
编程实验 打印print
 
调用print
mov bp, MsgStr mov cx, 29 call Print
有函数调用,就要考虑栈
define: BaseOfStack equ 0x7c00 //定义栈空间起始地址
start:
    mov ax, cs
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov sp, BaseOfStack   ;将sp指针指向栈的起始地址处
 
0x7c00作为栈的地址是可以的

在这里要进行三步–1.首先对打印函数进行了定义2.然后对栈空间进行定义–定义起始地址3.最后将sp栈顶指针寄存器指向定义栈的起始地址处

问题:读取软盘上的数据
3.5寸软盘
我们通常说的扇区号是逻辑扇区号,然而在真正的软盘物理结构上面,不是线性编号的
将逻辑扇区号进行拆分
软盘数据的读写–软盘数据一扇区512字节为单位进行读取,指定数据所在位置的磁头号,柱面号,扇区号。它的计算公式为

使用BIOS中断
 
读取数据流程

在这里我们需要注意的是,汇编中的16为除法操作(div)–被除数放到AX寄存器,除数放到通用寄存器或内存单元(8位),结果是商位于AL,余数位于AH
实验-磁盘数据读取
 mov ch, al
    shr ch, 1    将商右移一位
read: 
    int 0x13
    jc read       出错之后就跳转重读
这里的进栈操作是为了保存寄存器原有的值

org 0x7c00
jmp short start   //短跳转    跳转到start    占用了两个字节(jmp占一个字节,目标占一个字节)
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  读取的为34扇区的原因是将data.img以二进制进行查看时 它是在34扇区 有29个字节
    mov cx, 1   ;连续读取一个扇区
    mov bx, Buf  ;指定目标内存的地址,读取到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   ;将扇区数量弹出到ax
    pop bx
    
    mov ah, 0x02   ;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
                    
                

                
            
        
浙公网安备 33010602011771号