zoukankan      html  css  js  c++  java
  • 第九课 主引导程序控制权的转移

      这一节,我们来真正的读取文件中的内容到内存中,首先来看一下内存布局是什么样的,如下所示:

      Boot占用了512字节,Fat Table占用了4KB,而真正的文件中的内容,我们把它存在0x9000开始的内存地址处。

      加载文件内容的过程如下:

      实验步骤如下:

      1、在虚拟软盘中创建体积较大的文本文件,使之内容大小超过一个扇区。

      2、将文件的内容加载到BaseOfLoader地址处。

      3、打印加载的内容,判断是否加载完全。

      1 org 0x7c00
      2 
      3 jmp short start
      4 nop
      5 
      6 define:
      7     BaseOfStack      equ 0x7c00
      8     BaseOfLoader     equ 0x9000
      9     RootEntryOffset  equ 19
     10     RootEntryLength  equ 14
     11     EntryItemLength  equ 32
     12     FatEntryOffset   equ 1
     13     FatEntryLength   equ 9
     14 
     15 header:
     16     BS_OEMName     db "D.T.Soft"
     17     BPB_BytsPerSec dw 512
     18     BPB_SecPerClus db 1
     19     BPB_RsvdSecCnt dw 1
     20     BPB_NumFATs    db 2
     21     BPB_RootEntCnt dw 224
     22     BPB_TotSec16   dw 2880
     23     BPB_Media      db 0xF0
     24     BPB_FATSz16    dw 9
     25     BPB_SecPerTrk  dw 18
     26     BPB_NumHeads   dw 2
     27     BPB_HiddSec    dd 0
     28     BPB_TotSec32   dd 0
     29     BS_DrvNum      db 0
     30     BS_Reserved1   db 0
     31     BS_BootSig     db 0x29
     32     BS_VolID       dd 0
     33     BS_VolLab      db "D.T.OS-0.01"
     34     BS_FileSysType db "FAT12   "
     35 
     36 start:
     37     mov ax, cs
     38     mov ss, ax
     39     mov ds, ax
     40     mov es, ax
     41     mov sp, BaseOfStack
     42     
     43     mov ax, RootEntryOffset
     44     mov cx, RootEntryLength
     45     mov bx, Buf
     46     
     47     call ReadSector
     48     
     49     mov si, Target
     50     mov cx, TarLen
     51     mov dx, 0
     52     
     53     call FindEntry
     54     
     55     cmp dx, 0
     56     jz output
     57     
     58     mov si, bx
     59     mov di, EntryItem
     60     mov cx, EntryItemLength
     61     
     62     call MemCpy
     63     
     64     mov ax, FatEntryLength
     65     mov cx, [BPB_BytsPerSec]
     66     mul cx
     67     mov bx, BaseOfLoader
     68     sub bx, ax
     69     
     70     mov ax, FatEntryOffset
     71     mov cx, FatEntryLength
     72     
     73     call ReadSector
     74     
     75     mov dx, [EntryItem + 0x1A]
     76     mov si, BaseOfLoader
     77     
     78 loading:
     79     mov ax, dx
     80     add ax, 31
     81     mov cx, 1
     82     push dx
     83     push bx
     84     mov bx, si
     85     call ReadSector
     86     pop bx
     87     pop cx
     88     call FatVec
     89     cmp dx, 0xFF7
     90     jnb output     
     91     add si, 512
     92     jmp loading
     93     
     94 output:    
     95     mov bp, BaseOfLoader
     96     mov cx, [EntryItem + 0x1C]
     97     call Print
     98     
     99 last:
    100     hlt
    101     jmp last    
    102 
    103 
    104 ; cx --> index
    105 ; bx --> fat table address
    106 ;
    107 ; return:
    108 ;     dx --> fat[index]
    109 FatVec:
    110     mov ax, cx
    111     mov cl, 2
    112     div cl
    113     
    114     push ax
    115     
    116     mov ah, 0
    117     mov cx, 3
    118     mul cx
    119     mov cx, ax
    120     
    121     pop ax
    122     
    123     cmp ah, 0
    124     jz even
    125     jmp odd
    126 
    127 even:    ; FatVec[j] = ( (Fat[i+1] & 0x0F) << 8 ) | Fat[i];
    128     mov dx, cx
    129     add dx, 1
    130     add dx, bx
    131     mov bp, dx
    132     mov dl, byte [bp]
    133     and dl, 0x0F
    134     shl dx, 8
    135     add cx, bx
    136     mov bp, cx
    137     or  dl, byte [bp]
    138     jmp return
    139     
    140 odd:     ; FatVec[j+1] = (Fat[i+2] << 4) | ( (Fat[i+1] >> 4) & 0x0F );
    141     mov dx, cx
    142     add dx, 2
    143     add dx, bx
    144     mov bp, dx
    145     mov dl, byte [bp]
    146     mov dh, 0
    147     shl dx, 4
    148     add cx, 1
    149     add cx, bx
    150     mov bp, cx
    151     mov cl, byte [bp]
    152     shr cl, 4
    153     and cl, 0x0F
    154     mov ch, 0
    155     or  dx, cx
    156 
    157 return: 
    158     ret
    159 
    160 ; ds:si --> source
    161 ; es:di --> destination
    162 ; cx    --> length
    163 MemCpy:
    164     
    165     cmp si, di
    166     
    167     ja btoe
    168     
    169     add si, cx
    170     add di, cx
    171     dec si
    172     dec di
    173     
    174     jmp etob
    175     
    176 btoe:
    177     cmp cx, 0
    178     jz done
    179     mov al, [si]
    180     mov byte [di], al
    181     inc si
    182     inc di
    183     dec cx
    184     jmp btoe
    185     
    186 etob: 
    187     cmp cx, 0
    188     jz done
    189     mov al, [si]
    190     mov byte [di], al
    191     dec si
    192     dec di
    193     dec cx
    194     jmp etob
    195 
    196 done:   
    197     ret
    198 
    199 ; es:bx --> root entry offset address
    200 ; ds:si --> target string
    201 ; cx    --> target length
    202 ;
    203 ; return:
    204 ;     (dx !=0 ) ? exist : noexist
    205 ;        exist --> bx is the target entry
    206 FindEntry:
    207     push cx
    208     
    209     mov dx, [BPB_RootEntCnt]
    210     mov bp, sp
    211     
    212 find:
    213     cmp dx, 0
    214     jz noexist
    215     mov di, bx
    216     mov cx, [bp]
    217     push si
    218     call MemCmp
    219     pop si
    220     cmp cx, 0
    221     jz exist
    222     add bx, 32
    223     dec dx
    224     jmp find
    225 
    226 exist:
    227 noexist: 
    228     pop cx
    229        
    230     ret
    231 
    232 ; ds:si --> source
    233 ; es:di --> destination
    234 ; cx    --> length
    235 ;
    236 ; return:
    237 ;        (cx == 0) ? equal : noequal
    238 MemCmp:
    239 
    240 compare:
    241     cmp cx, 0
    242     jz equal
    243     mov al, [si]
    244     cmp al, byte [di]
    245     jz goon
    246     jmp noequal
    247 goon:
    248     inc si
    249     inc di
    250     dec cx
    251     jmp compare
    252     
    253 equal: 
    254 noequal:   
    255 
    256     ret
    257 
    258 ; es:bp --> string address
    259 ; cx    --> string length
    260 Print:
    261     mov dx, 0
    262     mov ax, 0x1301
    263     mov bx, 0x0007
    264     int 0x10
    265     ret
    266 
    267 ; no parameter
    268 ResetFloppy:
    269     
    270     mov ah, 0x00
    271     mov dl, [BS_DrvNum]
    272     int 0x13
    273     
    274     ret
    275 
    276 ; ax    --> logic sector number
    277 ; cx    --> number of sector
    278 ; es:bx --> target address
    279 ReadSector:
    280     
    281     call ResetFloppy
    282     
    283     push bx
    284     push cx
    285     
    286     mov bl, [BPB_SecPerTrk]
    287     div bl
    288     mov cl, ah
    289     add cl, 1
    290     mov ch, al
    291     shr ch, 1
    292     mov dh, al
    293     and dh, 1
    294     mov dl, [BS_DrvNum]
    295     
    296     pop ax
    297     pop bx
    298     
    299     mov ah, 0x02
    300 
    301 read:    
    302     int 0x13
    303     jc read
    304     
    305     ret
    306 
    307 MsgStr db  "No LOADER ..."    
    308 MsgLen equ ($-MsgStr)
    309 Target db  "START      "
    310 TarLen equ ($-Target)
    311 EntryItem times EntryItemLength db 0x00
    312 Buf:
    313     times 510-($-$$) db 0x00
    314     db 0x55, 0xaa

      95行跳转到加载文件内容的地址处,96行为文件的长度。运行bochs,可以看到文件内容全部打印出来了,结果如下:

      

      以上我们加载的文件只是文本内容,下面我们在文件中写入程序,并编译成可执行程序,然后将这个可执行程序文件放到虚拟软盘中,并加载到指定地址,然后跳转到这个地址执行。

      待加载文件中的内容如下:

     1 org 0x9000
     2 
     3 begin:
     4     mov si, msg
     5 
     6 print:
     7     mov al, [si]
     8     add si, 1
     9     cmp al, 0x00
    10     je end
    11     mov ah, 0x0E
    12     mov bx, 0x0F
    13     int 0x10
    14     jmp print
    15 
    16 end:
    17     hlt
    18     jmp end
    19     
    20 msg:
    21     db 0x0a, 0x0a
    22     db "Hello, D.T.OS!"
    23     db 0x0a, 0x0a
    24     db 0x00

      为了方便起见,我们修改makefile,如下:

     1 .PHONY : all clean rebuild
     2 
     3 BOOT_SRC := boot.asm
     4 BOOT_OUT := boot
     5 
     6 LOADER_SRC := loader.asm
     7 LOADER_OUT := loader
     8 
     9 IMG := a.img
    10 IMG_PATH := /mnt/hgfs
    11 
    12 RM := rm -fr
    13 
    14 all : $(IMG) $(BOOT_OUT) $(LOADER_OUT)
    15     @echo "Build Success ==> D.T.OS!"
    16 
    17 $(IMG) :
    18     bximage $@ -q -fd -size=1.44
    19     
    20 $(BOOT_OUT) : $(BOOT_SRC)
    21     nasm $^ -o $@
    22     dd if=$@ of=$(IMG) bs=512 count=1 conv=notrunc
    23     
    24 $(LOADER_OUT) : $(LOADER_SRC)
    25     nasm $^ -o $@
    26     sudo mount -o loop $(IMG) $(IMG_PATH)
    27     sudo cp $@ $(IMG_PATH)/$@
    28     sudo umount $(IMG_PATH)
    29     
    30 clean :
    31     $(RM) $(IMG) $(BOOT_OUT) $(LOADER_OUT)
    32     
    33 rebuild :
    34     @$(MAKE) clean
    35     @$(MAKE) all

      makefile完成编译boot.asm,编译loader.asm,写入boot.bin到第一个扇区,挂载a.img到/mnt/hgfs目录,写入loader可执行文件,卸载a.img等。

      我们修改boot.asm,程序如下:

      1 org 0x7c00
      2 
      3 jmp short start
      4 nop
      5 
      6 define:
      7     BaseOfStack      equ 0x7c00
      8     BaseOfLoader     equ 0x9000
      9     RootEntryOffset  equ 19
     10     RootEntryLength  equ 14
     11     EntryItemLength  equ 32
     12     FatEntryOffset   equ 1
     13     FatEntryLength   equ 9
     14 
     15 header:
     16     BS_OEMName     db "D.T.Soft"
     17     BPB_BytsPerSec dw 512
     18     BPB_SecPerClus db 1
     19     BPB_RsvdSecCnt dw 1
     20     BPB_NumFATs    db 2
     21     BPB_RootEntCnt dw 224
     22     BPB_TotSec16   dw 2880
     23     BPB_Media      db 0xF0
     24     BPB_FATSz16    dw 9
     25     BPB_SecPerTrk  dw 18
     26     BPB_NumHeads   dw 2
     27     BPB_HiddSec    dd 0
     28     BPB_TotSec32   dd 0
     29     BS_DrvNum      db 0
     30     BS_Reserved1   db 0
     31     BS_BootSig     db 0x29
     32     BS_VolID       dd 0
     33     BS_VolLab      db "D.T.OS-0.01"
     34     BS_FileSysType db "FAT12   "
     35 
     36 start:
     37     mov ax, cs
     38     mov ss, ax
     39     mov ds, ax
     40     mov es, ax
     41     mov sp, BaseOfStack
     42     
     43     mov ax, RootEntryOffset
     44     mov cx, RootEntryLength
     45     mov bx, Buf
     46     
     47     call ReadSector
     48     
     49     mov si, Target
     50     mov cx, TarLen
     51     mov dx, 0
     52     
     53     call FindEntry
     54     
     55     cmp dx, 0
     56     jz output
     57     
     58     mov si, bx
     59     mov di, EntryItem
     60     mov cx, EntryItemLength
     61     
     62     call MemCpy
     63     
     64     mov ax, FatEntryLength
     65     mov cx, [BPB_BytsPerSec]
     66     mul cx
     67     mov bx, BaseOfLoader
     68     sub bx, ax
     69     
     70     mov ax, FatEntryOffset
     71     mov cx, FatEntryLength
     72     
     73     call ReadSector
     74     
     75     mov dx, [EntryItem + 0x1A]
     76     mov si, BaseOfLoader
     77     
     78 loading:
     79     mov ax, dx
     80     add ax, 31
     81     mov cx, 1
     82     push dx
     83     push bx
     84     mov bx, si
     85     call ReadSector
     86     pop bx
     87     pop cx
     88     call FatVec
     89     cmp dx, 0xFF7
     90     jnb BaseOfLoader     
     91     add si, 512
     92     jmp loading
     93     
     94 output:    
     95     mov bp, MsgStr
     96     mov cx, MsgLen
     97     call Print
     98     
     99 last:
    100     hlt
    101     jmp last    
    102 
    103 
    104 ; cx --> index
    105 ; bx --> fat table address
    106 ;
    107 ; return:
    108 ;     dx --> fat[index]
    109 FatVec:
    110     mov ax, cx
    111     mov cl, 2
    112     div cl
    113     
    114     push ax
    115     
    116     mov ah, 0
    117     mov cx, 3
    118     mul cx
    119     mov cx, ax
    120     
    121     pop ax
    122     
    123     cmp ah, 0
    124     jz even
    125     jmp odd
    126 
    127 even:    ; FatVec[j] = ( (Fat[i+1] & 0x0F) << 8 ) | Fat[i];
    128     mov dx, cx
    129     add dx, 1
    130     add dx, bx
    131     mov bp, dx
    132     mov dl, byte [bp]
    133     and dl, 0x0F
    134     shl dx, 8
    135     add cx, bx
    136     mov bp, cx
    137     or  dl, byte [bp]
    138     jmp return
    139     
    140 odd:     ; FatVec[j+1] = (Fat[i+2] << 4) | ( (Fat[i+1] >> 4) & 0x0F );
    141     mov dx, cx
    142     add dx, 2
    143     add dx, bx
    144     mov bp, dx
    145     mov dl, byte [bp]
    146     mov dh, 0
    147     shl dx, 4
    148     add cx, 1
    149     add cx, bx
    150     mov bp, cx
    151     mov cl, byte [bp]
    152     shr cl, 4
    153     and cl, 0x0F
    154     mov ch, 0
    155     or  dx, cx
    156 
    157 return: 
    158     ret
    159 
    160 ; ds:si --> source
    161 ; es:di --> destination
    162 ; cx    --> length
    163 MemCpy:
    164     
    165     cmp si, di
    166     
    167     ja btoe
    168     
    169     add si, cx
    170     add di, cx
    171     dec si
    172     dec di
    173     
    174     jmp etob
    175     
    176 btoe:
    177     cmp cx, 0
    178     jz done
    179     mov al, [si]
    180     mov byte [di], al
    181     inc si
    182     inc di
    183     dec cx
    184     jmp btoe
    185     
    186 etob: 
    187     cmp cx, 0
    188     jz done
    189     mov al, [si]
    190     mov byte [di], al
    191     dec si
    192     dec di
    193     dec cx
    194     jmp etob
    195 
    196 done:   
    197     ret
    198 
    199 ; es:bx --> root entry offset address
    200 ; ds:si --> target string
    201 ; cx    --> target length
    202 ;
    203 ; return:
    204 ;     (dx !=0 ) ? exist : noexist
    205 ;        exist --> bx is the target entry
    206 FindEntry:
    207     push cx
    208     
    209     mov dx, [BPB_RootEntCnt]
    210     mov bp, sp
    211     
    212 find:
    213     cmp dx, 0
    214     jz noexist
    215     mov di, bx
    216     mov cx, [bp]
    217     push si
    218     call MemCmp
    219     pop si
    220     cmp cx, 0
    221     jz exist
    222     add bx, 32
    223     dec dx
    224     jmp find
    225 
    226 exist:
    227 noexist: 
    228     pop cx
    229        
    230     ret
    231 
    232 ; ds:si --> source
    233 ; es:di --> destination
    234 ; cx    --> length
    235 ;
    236 ; return:
    237 ;        (cx == 0) ? equal : noequal
    238 MemCmp:
    239 
    240 compare:
    241     cmp cx, 0
    242     jz equal
    243     mov al, [si]
    244     cmp al, byte [di]
    245     jz goon
    246     jmp noequal
    247 goon:
    248     inc si
    249     inc di
    250     dec cx
    251     jmp compare
    252     
    253 equal: 
    254 noequal:   
    255 
    256     ret
    257 
    258 ; es:bp --> string address
    259 ; cx    --> string length
    260 Print:
    261     mov dx, 0
    262     mov ax, 0x1301
    263     mov bx, 0x0007
    264     int 0x10
    265     ret
    266 
    267 ; no parameter
    268 ResetFloppy:
    269     
    270     mov ah, 0x00
    271     mov dl, [BS_DrvNum]
    272     int 0x13
    273     
    274     ret
    275 
    276 ; ax    --> logic sector number
    277 ; cx    --> number of sector
    278 ; es:bx --> target address
    279 ReadSector:
    280     
    281     call ResetFloppy
    282     
    283     push bx
    284     push cx
    285     
    286     mov bl, [BPB_SecPerTrk]
    287     div bl
    288     mov cl, ah
    289     add cl, 1
    290     mov ch, al
    291     shr ch, 1
    292     mov dh, al
    293     and dh, 1
    294     mov dl, [BS_DrvNum]
    295     
    296     pop ax
    297     pop bx
    298     
    299     mov ah, 0x02
    300 
    301 read:    
    302     int 0x13
    303     jc read
    304     
    305     ret
    306 
    307 MsgStr db  "No LOADER ..."    
    308 MsgLen equ ($-MsgStr)
    309 Target db  "LOADER     "
    310 TarLen equ ($-Target)
    311 EntryItem times EntryItemLength db 0x00
    312 Buf:
    313     times 510-($-$$) db 0x00
    314     db 0x55, 0xaa

      第90行改为跳转到文件内容加载地址处,而不再跳转到output。第309行文件的名字也改为LOADER。

      执行make,然后运行bochs,结果如下:

      可以看到,文件中的可执行程序被加载并成功执行了,成功打印出字符串。此时的打印是文件中的可执行程序中print函数实现的,而不是我们的加载程序中的Print函数实现的。

      我们将a.img拷贝到windows下,在真正的机器上试一下,设置如下:

      启动虚拟机,我们看到了以下结果:

      我们的加载程序和可执行文件都成功运行了。

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

  • 相关阅读:
    大道至简第四章读后感
    JAVA类与对象
    大道至简第三章读后感
    JAVA语法基础 动手动脑及课后作业
    课程作业01
    大道至简第二章读后感
    大道至简第一章读后感
    swift学习笔记之-自动引用计数
    swift学习笔记之-继承
    swift学习笔记之-闭包
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9246078.html
Copyright © 2011-2022 走看看