16位装配不打印字符

时间:2013-12-03 20:28:10

标签: assembly x86 16-bit fat

我有一个基本的引导程序,应该从FAT12格式的软盘读取根扇区到内存中。 (该部分有效)但在实施之后它停止将字符写入屏幕。上次这样做是因为我忘记了POP寄存器。 但我已经三次检查了我是否已经将每个注册回归。

我还使用了BOCHS调试器,并根据它到达终点并执行打印字符命令。

我现在被困住了。如果有人能看一下我的代码,我真的很开心。

这是我的代码:

org 0x7c00
bits 16

start: jmp loader

;OEM
TIMES 0Bh-$+start DB 0
bpbBytesPerSector:      DW 512
bpbSectorsPerCluster:   DB 1
bpbReservedSectors:     DW 1
bpbNumberOfFATs:        DB 2
bpbRootEntries:         DW 224
bpbTotalSectors:        DW 2880
bpbMedia:               DB 0xF0
bpbSectorsPerFAT:       DW 9
bpbSectorsPerTrack:     DW 18
bpbHeadsPerCylinder:    DW 2
bpbHiddenSectors:       DD 0
bpbTotalSectorsBig:     DD 0
bsDriveNumber:          DB 0
bsUnused:               DB 0
bsExtBootSignature:     DB 0x29
bsSerialNumber:         DD 0xa0a1a2a3
bsVolumeLabel:          DB "MOS FLOPPY "
bsFileSystem:           DB "FAT12   "

;vars

absoluteSector db 0x00
absoluteHead   db 0x00
absoluteTrack  db 0x00

;functions

print:
    xor bx, bx
    lodsb
    cmp al, 00h
    je print_eof
    mov ah, 0eh
    int 10h
    jmp print
print_eof:
ret


;************************************************;
; Convert LBA to CHS
; AX=>LBA Address to convert
;
; absolute sector = (logical sector / sectors per track) + 1
; absolute head   = (logical sector / sectors per track) MOD number of heads
; absolute track  = logical sector / (sectors per track * number of heads)
;
;************************************************;

lbachs:
    xor     dx, dx                              ; prepare dx:ax for operation
    div     WORD [bpbSectorsPerTrack]           ; calculate
    inc     dl                                  ; adjust for sector 0
    mov     BYTE [absoluteSector], dl
    xor     dx, dx                              ; prepare dx:ax for operation
    div     WORD [bpbHeadsPerCylinder]          ; calculate
    mov     BYTE [absoluteHead], dl
    mov     BYTE [absoluteTrack], al
    ret

ReadSectors:
    push ax ;safety
    push bx ;safety
    push cx ;safety
    call lbachs ;change LBA to CHS (floppy)
    mov ah, 0x02 ;function to read sector from floppy
    mov al, 0x01 ;read only 1 sector
    mov ch, [absoluteTrack] ;at track X
    mov cl, [absoluteSector];at sector X
    mov dh, [absoluteHead] ;at had X
    mov dl, 0x00 ;on drive 00 (floppydrive
    int 0x13 ;execute
    jnc .succes ;if succeeded goto succes else:
    mov ah, 0x00 ;reset floppy drive
    mov bl, 0x00 ;drive 0
    int 0x13 ;execute
    pop cx ;pop
    pop bx
    pop ax
    jmp ReadSectors ;retry
.succes:
    pop cx ;pop
    pop bx
    pop ax
    add bx, WORD [bpbBytesPerSector] ;next 512 bytes in memory to write sector to
    inc ax ;next sector
    LOOP ReadSectors ;and keep looping till cx == 0
    ret ;return

;Bootloader

loader:

    mov si, msg
    call print

    xor cx, cx
    mov ax, 0x0020        ; 32 byte directory entry
    mul WORD [bpbRootEntries]  ; number of root entrys
    div WORD [bpbBytesPerSector] ; get sectors used by root directory
    xchg cx, ax ;;cx=LENGTH in sectors

    mov al, [bpbNumberOfFATs]  ; Get number of FATs (Useually 2)
    mul WORD [bpbSectorsPerFAT]  ; number of FATs * sectors per FAT; get number of sectors
    add ax, [bpbReservedSectors] ; add reserved sectors
    ;AX=START as sector in LBA (so needs conversion

    mov bx, 0x0200  ; load root directory to 7c00:0x0200
    call ReadSectors

    mov     cx, [bpbRootEntries]        ; the number of entrys. If we reach 0, file doesnt exist
    mov     di, 0x0200        ; Root directory was loaded here
    .LOOP:
      push    cx
      mov     cx, 11            ; eleven character name
      mov     si, imageName     ; compare the 11 bytes with the name of our file
      push    di
    rep  cmpsb                     ; test for entry match
      pop     di
      je      LOAD_FAT          ; they match, so begin loading FAT
      pop     cx
      add     di, 32            ; they dont match, so go to next entry (32 bytes)
      loop    .LOOP
      jmp     FAILURE           ; no more entrys left, file doesnt exist :(

    LOAD_FAT:

    mov bh, 00h ;page to wwrite to.
    mov ah, 0eh ;write character
    mov al, 'Y' ;write the Y character
    int 10h ;execute
    jmp EoF ;jump to end of file

    FAILURE:

    mov bh, 00h ;page to write to
    mov ah, 0eh ;write character
    mov al, 'N' ;write the N character
    int 10h ;execute

    EoF:

    mov bh, 00h ;see above :P
    mov ah, 0eh
    mov al, 'D'
    int 10h

    cli
    hlt

streof db 'DONE....',0x0A, 0x0D, 00h
msg db 'Hello!', 0x0D, 0x0A, 00h
msg2 db 'Done reading root directory!', 0x0D, 0x0A, 00h
succ db 'YES file is found!', 00h
fil db 'Failed no file found!', 00h
imageName   db "KRNLDR  SYS"

times 510 - ($-$$) db 0
dw 0xAA55

http://pastebin.com/rcX7bZLV

提前致谢。

-Tim

PS: (对于那些说我不应该复制代码的人) 我只复制了检查文件是否存在的问题'来自breaknthorn的代码,看看我是否正确加载了ROOT。

1 个答案:

答案 0 :(得分:0)

我修好了。

在搜索并询问irc后,我得出的结论是我没有正确设置堆栈寄存器。我将org 0x7c00更改为org 0,然后跳转到加载程序(loader:)后,我正确地输入了堆栈:

cli
mov     ax, 0x07c0
mov     ds, ax
mov     es, ax
mov     fs, ax
mov     gs, ax
mov     ax, 0x0000
mov     ss, ax
mov     sp, 0xFFFF
sti

我希望这可以帮助那些有同样问题的人!

-Tim