前几节我们介绍了FAT12文件系统,制作了虚拟软盘文件a.img,并在Qt Creater中进行了文件内容的读取实验。那些读取都是使用外部的程序实现的,实际应用中,我们需要用主引导程序来实现文件的读写,主引导程序存在于主引导扇区MBR中,也就是说程序和文件是存在一张盘上的,而且这些主引导程序需要使用汇编语言实现。接下来,我们就来实现具有读取功能的主引导程序。

  为了验证文件读取的正确性,我们需要在主引导程序中先实现一个字符串打印函数。BIOS已经将中断向量写到了内存的指定位置处,这其中就有能实现字符串打印的函数,我们需要做的就是配置一些参数,需要配置的参数和配置步骤如下:

  1、指定打印参数(AX=0x1301 , BX = 0x0007)

  2、指定字符串的内存地址(ES:BP  = 字符串地址)

  3、指定字符串的长度(CX = 字符串长度)

  4、中断调用(int 0x10)

示例如下:

  需要用到的汇编语言的知识点如下:

                                

  下面直接给出打印字符串的汇编程序:

 1 org 0x7c00
 2 
 3 jmp short start
 4 nop
 5 
 6 define:
 7     BaseOfStack equ 0x7c00
 8 
 9 header:
10     BS_OEMName     db "D.T.Soft"
11     BPB_BytsPerSec dw 512
12     BPB_SecPerClus db 1
13     BPB_RsvdSecCnt dw 1
14     BPB_NumFATs    db 2
15     BPB_RootEntCnt dw 224
16     BPB_TotSec16   dw 2880
17     BPB_Media      db 0xF0
18     BPB_FATSz16    dw 9
19     BPB_SecPerTrk  dw 18
20     BPB_NumHeads   dw 2
21     BPB_HiddSec    dd 0
22     BPB_TotSec32   dd 0
23     BS_DrvNum      db 0
24     BS_Reserved1   db 0
25     BS_BootSig     db 0x29
26     BS_VolID       dd 0
27     BS_VolLab      db "D.T.OS-0.01"
28     BS_FileSysType db "FAT12   "
29 
30 start:
31     mov ax, cs
32     mov ss, ax
33     mov ds, ax
34     mov es, ax
35     mov sp, BaseOfStack
36    
37        mov ax, MsgStr
38        mov bp, ax
39        
40        mov ax, ds
41        mov es, ax
42        
43        mov cx, 6
44     call Print
45     
46 last:
47     hlt
48     jmp last    
49 
50 ; es:bp --> string address
51 ; cx    --> string length
52 Print:
53     mov ax, 0x1301
54     mov bx, 0x0007
55     int 0x10
56     ret
57 
58 MsgStr db  "Hello, DTOS!"    
59 MsgLen equ ($-MsgStr)
60 Buf:
61     times 510-($-$$) db 0x00
62     db 0x55, 0xaa

  我们的虚拟软盘文件a.img已经格式化好了,现在要修改的只是第一个扇区即主引导扇区,所以我们要按照FAT12的格式来填充第一个扇区,因此,上面的程序中,第10到28行是FAT12的引导扇区的信息,它前面还有三个字节,其中前两个字节是跳转指令jmp short start,第三个字节为空指令nop。从start开始是我们的可执行程序,BaseOfStack是定义的栈底地址。

  汇编程序我们需要编译成二进制可执行程序,然后写入a.img虚拟软盘的第一个扇区中,每次都执行这个过程很麻烦,我们将这个过程写成makefile,如下所示:

 

 1 .PHONY : all clean rebuild
 2 
 3 SRC := boot.asm
 4 OUT := boot.bin
 5 IMG := a.img
 6 
 7 RM := rm -fr
 8 
 9 all : $(OUT) $(IMG)
10     dd if=$(OUT) of=$(IMG) bs=512 count=1 conv=notrunc
11     @echo "Success!"
12 
13 $(IMG) :
14     bximage $@ -q -fd -size=1.44
15 
16 $(OUT) : $(SRC)
17     nasm $^ -o $@
18 
19 clean :
20     $(RM) $(IMG) $(OUT)
21 
22 rebuild :
23     @$(MAKE) clean
24     @$(MAKE) all
25     

 

 

bochs的启动文件修改成如下内容:

 1 ###############################################################
 2 # Configuration file for Bochs
 3 ###############################################################
 4 
 5 # how much memory the emulated machine will have
 6 megs: 32
 7 
 8 # filename of ROM images
 9 romimage: file=/usr/share/bochs/BIOS-bochs-latest
10 vgaromimage: file=/usr/share/vgabios/vgabios.bin
11 
12 # what disk images will be used
13 floppya: 1_44=a.img, status=inserted
14 # choose the boot disk.
15 boot: a
16 
17 # where do we send log messages?
18 # log: bochsout.txt
19 
20 # disable the mouse
21 mouse: enabled=0
22 
23 # enable key mapping, using US layout as default.
24 keyboard_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map

  

  启动bochs,即可得到运行结果,如下所示:

 

  可见,hello已经成功打印出来了。

   接下来,我们开始读取文件,假如我们知道了数据所在的扇区,那么怎么将它读出来呢?先来看一下软盘的构造,如下所示:

  3.5寸软盘的特性如下:

  根据逻辑扇区号计算磁头号、柱面号、物理扇区号的方法如下:

  软盘复位和软驱数据读取的参数如下:

 

  整体的读取流程如下:

  需要用到的汇编知识点如下:

  

 下面直接给出汇编程序:

  1 org 0x7c00
  2 
  3 jmp short start
  4 nop
  5 
  6 define:
  7     BaseOfStack equ 0x7c00
  8 
  9 header:
 10     BS_OEMName     db "D.T.Soft"
 11     BPB_BytsPerSec dw 512
 12     BPB_SecPerClus db 1
 13     BPB_RsvdSecCnt dw 1
 14     BPB_NumFATs    db 2
 15     BPB_RootEntCnt dw 224
 16     BPB_TotSec16   dw 2880
 17     BPB_Media      db 0xF0
 18     BPB_FATSz16    dw 9
 19     BPB_SecPerTrk  dw 18
 20     BPB_NumHeads   dw 2
 21     BPB_HiddSec    dd 0
 22     BPB_TotSec32   dd 0
 23     BS_DrvNum      db 0
 24     BS_Reserved1   db 0
 25     BS_BootSig     db 0x29
 26     BS_VolID       dd 0
 27     BS_VolLab      db "D.T.OS-0.01"
 28     BS_FileSysType db "FAT12   "
 29 
 30 start:
 31     mov ax, cs
 32     mov ss, ax
 33     mov ds, ax
 34     mov es, ax
 35     mov sp, BaseOfStack
 36     
 37     mov ax, 34
 38     mov cx, 1
 39     mov bx, Buf
 40     
 41     call ReadSector
 42     
 43     mov bp, Buf
 44     mov cx, 24
 45     
 46     call Print
 47     
 48 last:
 49     hlt
 50     jmp last    
 51 
 52 ; es:bp --> string address
 53 ; cx    --> string length
 54 Print:
 55     mov ax, 0x1301
 56     mov bx, 0x0007
 57     int 0x10
 58     ret
 59 
 60 ; no parameter
 61 ResetFloppy:
 62     push ax
 63     push dx
 64     
 65     mov ah, 0x00
 66     mov dl, [BS_DrvNum]
 67     int 0x13
 68     
 69     pop dx
 70     pop ax
 71     
 72     ret
 73 
 74 ; ax    --> logic sector number
 75 ; cx    --> number of sector
 76 ; es:bx --> target address
 77 ReadSector:
 78     push bx
 79     push cx
 80     push dx
 81     push ax
 82     
 83     call ResetFloppy
 84     
 85     push bx
 86     push cx
 87     
 88     mov bl, [BPB_SecPerTrk]
 89     div bl
 90     mov cl, ah
 91     add cl, 1
 92     mov ch, al
 93     shr ch, 1
 94     mov dh, al
 95     and dh, 1
 96     mov dl, [BS_DrvNum]
 97     
 98     pop ax
 99     pop bx
100     
101     mov ah, 0x02
102 
103 read:    
104     int 0x13
105     jc read
106     
107     pop ax
108     pop dx
109     pop cx
110     pop bx
111     
112     ret
113 
114 MsgStr db  "Hello, DTOS!"    
115 MsgLen equ ($-MsgStr)
116 Buf:
117     times 510-($-$$) db 0x00
118     db 0x55, 0xaa

  我们将虚拟软盘文件a.img用VS2013打开,查看其中的内容,截取片段如下:

  可以看到,a.txt文件的起始地址为0x4400,也就是第34个扇区开始,而内容的大小为24字节,这两个参数分别体现在汇编程序中的第37和44行。下面,启动bochs,运行结果如下:

  打印出了this is a floppy file.,我们成功读取了指定扇区的数据。

 

参考狄泰软件学院操作系统教程

 

  

posted on 2018-06-25 22:15  周伯通789  阅读(771)  评论(0编辑  收藏  举报