16 bit Assembly not printing character

862 views Asked by At

I've got a basic bootloader that should read the root sectors from a FAT12 formatted Floppy into the memory. (that part works) but after implementing that it stopped writing characters to the screen. Last time it did this was because I forgot to POP a register. But i've triple checked that I'm POPping every register back.

I've also used BOCHS Debugger and according to that it just reaches the end and executes the print character commands.

I'm stuck for now. I'd be really happy if anyone could take a look at my code.

This is my code:

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

Thanks in advance.

-Tim

PS: (for the ones going to say that I shouldn't copy code) I only copied the 'check if file exists' code from brokenthorn to see if I load the ROOT correct.

1

There are 1 answers

0
Tim van Osch On BEST ANSWER

I fixed it.

After searching around and asking in irc I came to the conclusion that I did not set my Stack registers correctly. I changed org 0x7c00 to org 0 and after jumping to the loader (loader:) I entered the stacks correctly like this:

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

I hope this helps the ones that have the same problem!

-Tim