Page 1 of 1

OS debugging

Posted: Fri Jan 23, 2009 1:59 pm
by sweetgum
I'd like to be able to step through my OS code from the bootloader and onward. Is there a way to do this? People suggested using emulators, although I'm having trouble with qemu, its strange, i get the error FATAL: INT 18: Boot Failure. The funny thing is this floppy disk Im using works on a regular computer. Anyone have any ideas? I appreciate any responses!

Re: OS debugging

Posted: Fri Jan 23, 2009 2:05 pm
by kmtdk
well
if it dont work on a emu, then it is not good.
but try using BOCSH, it also include a program to cracft a image ( floppy)
have you "pointed" currectly in qemu ?
and do you have the boot segniture ?

KMT dk

Re: OS debugging

Posted: Fri Jan 23, 2009 2:28 pm
by sweetgum
what do you mean by pointed? yes there is a boot signature. my boot loader will output Loading Boot Image and after that i receive the error

Re: OS debugging

Posted: Fri Jan 23, 2009 2:34 pm
by kmtdk
good,
pointer
well
i assume you have compiled the source code, to a flat binary.
then you might have placed the code on a VFD (virtuel floppy drive), or "pointed" at the file(source file)

KMT dk

Re: OS debugging

Posted: Fri Jan 23, 2009 2:38 pm
by Love4Boobies
QEMU gives that exact same error message when INT 18H is invoked. It's meant to return control to the BIOS when a device is unbootable, but it's a software interrupt. Are you using a custom boot loader? It may be that your boot loader does something wrong (like, if you have a MBR, it may not have the partition table set right - or not set at all).

Re: OS debugging

Posted: Fri Jan 23, 2009 2:40 pm
by sweetgum
heres the source to my bootloader

Code: Select all

 
;*************************************************************************

;the ultimate boot-strap loader

;to load a file from a DOS FAT12 floppy as the OS

;*************************************************************************

[BITS 16]

[ORG 0x0000]

jmp     START

     

     OEM_ID                db "QUASI-OS"

     BytesPerSector        dw 0x0200

     SectorsPerCluster     db 0x01

     ReservedSectors       dw 0x0001

     TotalFATs             db 0x02

     MaxRootEntries        dw 0x00E0

     TotalSectorsSmall     dw 0x0B40

     MediaDescriptor       db 0xF0

     SectorsPerFAT         dw 0x0009

     SectorsPerTrack       dw 0x0012

     NumHeads              dw 0x0002

     HiddenSectors         dd 0x00000000

     TotalSectorsLarge     dd 0x00000000

     DriveNumber           db 0x00

     Flags                 db 0x00

     Signature             db 0x29

     VolumeID              dd 0xFFFFFFFF

     VolumeLabel           db "QUASI  BOOT"

     SystemID              db "FAT12   "

     

     START:

     ; code located at 0000:7C00, adjust segment registers

          cli

          mov     ax, 0x07C0

          mov     ds, ax

          mov     es, ax

          mov     fs, ax

          mov     gs, ax

     ; create stack

          mov     ax, 0x0000

          mov     ss, ax

          mov     sp, 0xFFFF

          sti

     ; post message

          mov     si, msgLoading

          call    DisplayMessage

     LOAD_ROOT:

     ; compute size of root directory and store in ‘cx’

          xor     cx, cx

          xor     dx, dx

          mov     ax, 0x0020                          ; 32 byte directory entry

          mul     WORD [MaxRootEntries]               ; total size of directory

          div     WORD [BytesPerSector]               ; sectors used by directory

          xchg    ax, cx

     ; compute location of root directory and store in ‘ax’

          mov     al, BYTE [TotalFATs]                ; number of FATs

          mul     WORD [SectorsPerFAT]                ; sectors used by FATs

          add     ax, WORD [ReservedSectors]          ; adjust for bootsector

          mov     WORD [datasector], ax               ; base of root directory

          add     WORD [datasector], cx

     ; read root directory into memory (7C00:0200)

          mov     bx, 0x0200                          ; copy root dir above bootcode

          call    ReadSectors

     ; browse root directory for binary image

          mov     cx, WORD [MaxRootEntries]           ; load loop counter

          mov     di, 0x0200                          ; locate first root entry

     .LOOP:

          push    cx

          mov     cx, 0x000B                          ; eleven character name

          mov     si, ImageName                       ; image name to find

          push    di

     rep  cmpsb                                       ; test for entry match

          pop     di

          je      LOAD_FAT

          pop     cx

          add     di, 0x0020                          ; queue next directory entry

          loop    .LOOP

          jmp     FAILURE

     LOAD_FAT:

     ; save starting cluster of boot image

          mov     si, msgCRLF

          call    DisplayMessage

          mov     dx, WORD [di + 0x001A]

          mov     WORD [cluster], dx                  ; file’s first cluster

     ; compute size of FAT and store in ‘cx’

          xor     ax, ax

          mov     al, BYTE [TotalFATs]                ; number of FATs

          mul     WORD [SectorsPerFAT]                ; sectors used by FATs

          mov     cx, ax

     ; compute location of FAT and store in ‘ax’

          mov     ax, WORD [ReservedSectors]          ; adjust for bootsector

     ; read FAT into memory (7C00:0200)

          mov     bx, 0x0200                          ; copy FAT above bootcode

          call    ReadSectors

     ; read image file into memory (0100:0000)

          mov     si, msgCRLF

          call    DisplayMessage

          mov     ax, 0x0100                          ; destination of image CS

          mov     es, ax

          mov     bx, 0x0000                          ; destination for image IP

          push    bx

     LOAD_IMAGE:

          mov     ax, WORD [cluster]                  ; cluster to read

          pop     bx                                  ; buffer to read into

          call    ClusterLBA                          ; convert cluster to LBA

          xor     cx, cx

          mov     cl, BYTE [SectorsPerCluster]        ; sectors to read

          call    ReadSectors

          push    bx

     ; compute next cluster

          mov     ax, WORD [cluster]                  ; identify current cluster

          mov     cx, ax                              ; copy current cluster

          mov     dx, ax                              ; copy current cluster

          shr     dx, 0x0001                          ;

     ;divide by two

          add     cx, dx                              ; sum for (3/2)

          mov     bx, 0x0200                          ; location of FAT in memory

          add     bx, cx                              ; index into FAT

          mov     dx, WORD [bx]                       ; read two bytes from FAT

          test    ax, 0x0001

          jnz     .ODD_CLUSTER

     .EVEN_CLUSTER:

          and     dx, 0000111111111111b               ; take low twelve bits

         jmp     .DONE

     .ODD_CLUSTER:

          shr     dx, 0x0004                          ; take high twelve bits

     .DONE:

          mov     WORD [cluster], dx                  ; store new cluster

          cmp     dx, 0x0FF0                          ; test for end of file

          jb      LOAD_IMAGE

     DONE:

          mov     si, msgCRLF

          call    DisplayMessage

          push    WORD 0x0100

          push    WORD 0x0000

          retf

     FAILURE:

          mov     si, msgFailure

          call    DisplayMessage

          mov     ah, 0x00

          int     0x16                                ; await keypress

          int     0x19                                ; warm boot computer

     

     ;*************************************************************************

     ; PROCEDURE DisplayMessage

     ; display ASCIIZ string at ds:si via BIOS

     ;*************************************************************************

     DisplayMessage:

          lodsb                                       ; load next character

          or      al, al                              ; test for NUL character

          jz      .DONE

          mov     ah, 0x0E                            ; BIOS teletype

          mov     bh, 0x00                            ; display page 0

          mov     bl, 0x07                            ; text attribute

          int     0x10                                ; invoke BIOS

          jmp     DisplayMessage

     .DONE:

          ret

     

     ;*************************************************************************

     ; PROCEDURE ReadSectors

     ; reads ‘cx’ sectors from disk starting at ‘ax’ into

     ;memory location ‘es:bx’

     ;*************************************************************************

     ReadSectors:

     .MAIN

          mov     di, 0x0005                          ; five retries for error

     .SECTORLOOP

          push    ax

          push    bx

          push    cx

          call    LBACHS

          mov     ah, 0x02                            ; BIOS read sector

          mov     al, 0x01                            ; read one sector

          mov     ch, BYTE [absoluteTrack]            ; track

          mov     cl, BYTE [absoluteSector]           ; sector

          mov     dh, BYTE [absoluteHead]             ; head

          mov     dl, BYTE [DriveNumber]              ; drive

          int     0x13                                ; invoke BIOS

          jnc     .SUCCESS                            ; test for read error

          xor     ax, ax                              ; BIOS reset disk

          int     0x13                                ; invoke BIOS

          dec     di                                  ; decrement error counter

          pop     cx

          pop     bx

          pop     ax

          jnz     .SECTORLOOP                         ; attempt to read again

          int     0x18

     .SUCCESS

          mov     si, msgProgress

          call    DisplayMessage

          pop     cx

          pop     bx

          pop     ax

          add     bx, WORD [BytesPerSector]           ; queue next buffer

          inc     ax                                  ; queue next sector

          loop    .MAIN                               ; read next sector

          ret

     

     ;*************************************************************************

     ; PROCEDURE ClusterLBA

     ; convert FAT cluster into LBA addressing scheme

     ; LBA = (cluster - 2) * sectors per cluster

     ;*************************************************************************

     ClusterLBA:

          sub     ax, 0x0002                          ; zero base cluster number

          xor     cx, cx

          mov     cl, BYTE [SectorsPerCluster]        ; convert byte to word

          mul     cx

          add     ax, WORD [datasector]               ; base data sector

          ret

     

     ;*************************************************************************

     ; PROCEDURE LBACHS

     ; convert ‘ax’ LBA addressing scheme to CHS addressing scheme

     ; 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 [SectorsPerTrack]              ; calculate

          inc     dl                                  ; adjust for sector 0

          mov     BYTE [absoluteSector], dl

          xor     dx, dx                              ; prepare dx:ax for operation

          div     WORD [NumHeads]                     ; calculate

          mov     BYTE [absoluteHead], dl

          mov     BYTE [absoluteTrack], al

          ret



     absoluteSector db 0x00

     absoluteHead   db 0x00

     absoluteTrack  db 0x00

     

     datasector  dw 0x0000

     cluster     dw 0x0000

     ImageName   db "KERNEL  BIN"

     msgLoading  db 0x0D, 0x0A, "Loading Boot Image ", 0x0D, 0x0A, 0x00

     msgCRLF     db 0x0D, 0x0A, 0x00

     msgProgress db ".", 0x00

     msgFailure  db 0x0D, 0x0A, "ERROR : Press Any Key to Reboot", 0x00

     

          TIMES 510-($-$$) DB 0

          DW 0xAA55

     ;*************************************************************************

Re: OS debugging

Posted: Fri Jan 23, 2009 3:03 pm
by Love4Boobies
Things I've noticed not to be right:
  • Should have ORG 7C00H. You're mistaking segments with offsets. I also saw that you set all your segment registers to 7C00H later on, instead of 0000H. Besides, you don't even need all of them, you're just wasting precious bytes.
  • You don't actually need to CLI and STI. "MOV SS,..." and the instruction after it (whichever that is) are executed atomically. Just make sure the next one is "MOV SP,..." and you'll save couple of bytes there.
  • I also noticed you have JMPs to labels that have RETs. Something is terribly wrong there.
  • You're trying to use some black magic there, pushing things on the stack and returning to the kernel (I didn't bother checking to see if you've pushed the right values there). I can't see why you'd wanna do that. All you need is a long jump.
  • Why on earth is DriveNumber set to 00H (floppy). Besides the fact that this is what's causing your error, BIOS transfers control to the boot sector with the current drive passed in DL. Just be sure not to loose that value.
  • Check again to see how the BIOS expects the CHS to be passed to it for CHS calls.
I didn't look through the FAT parsing code and I've lost my patience on the way (I bet there are many more bugs there). I think you should start over.

Re: OS debugging

Posted: Fri Jan 23, 2009 5:35 pm
by Combuster
uhm, The ORG matches the loaded segments and is therefore correct (ds:0 points to start of the file, ds:7c00 points beyond)

Re: OS debugging

Posted: Fri Jan 23, 2009 5:52 pm
by Firestryke31
Love4Boobies wrote:Should have ORG 7C00H. You're mistaking segments with offsets. I also saw that you set all your segment registers to 7C00H later on, instead of 0000H. Besides, you don't even need all of them, you're just wasting precious bytes.
You seem to forget that 0x07C0:0x0000 and 0x0000:0x7C00 end up being the same address. This means that his ORG 0 indicates offsets from the segment 0x07C0, which is perfectly valid. (Although I do prefer 0x0000:0x7C00 myself...)

Re: OS debugging

Posted: Fri Jan 23, 2009 6:56 pm
by Love4Boobies
7C00H is defined by the BIOS Boot Specification. I'm sorry, I didn't see right, I thought it was 7C00:0000H, not 07C0:0000H. My bad!

Re: OS debugging

Posted: Sat Jan 24, 2009 9:13 am
by Dex
You could use the worlds best debug code:

Code: Select all

;*******************
          push    ax
          push    es
          xor     ax,ax
          mov     es,ax
          mov     byte [es:0xB89E], "1"
          int     0x16                                ; await keypress
          pop     es
          pop     ax
;******************
; Some code here
;*******************
          push    ax
          push    es
          xor     ax,ax
          mov     es,ax
          mov     byte [es:0xB89E], "2"
          int     0x16                                ; await keypress
          pop     es
          pop     ax
;******************
; Some code here
;*******************
          push    ax
          push    es
          xor     ax,ax
          mov     es,ax
          mov     byte [es:0xB89E], "3"
          int     0x16                                ; await keypress
          pop     es
          pop     ax
;******************
; Some code here
;*******************
          push    ax
          push    es
          xor     ax,ax
          mov     es,ax
          mov     byte [es:0xB89E], "4"
          int     0x16                                ; await keypress
          pop     es
          pop     ax
;******************
; Some code here
;*******************
          push    ax
          push    es
          xor     ax,ax
          mov     es,ax
          mov     byte [es:0xB89E], "5"
          int     0x16                                ; await keypress
          pop     es
          pop     ax
;******************
; Some code here
;*******************
          push    ax
          push    es
          xor     ax,ax
          mov     es,ax
          mov     byte [es:0xB89E], "6"
          int     0x16                                ; await keypress
          pop     es
          pop     ax
;******************
; Some code here
;AND SO NO

Re: OS debugging

Posted: Sat Jan 24, 2009 10:04 am
by ru2aqare
Shouldn't that write to the video memory be like this?

Code: Select all

;*******************
          push    ax
          push    es
          xor     ax,ax
          mov     es,ax
          mov     byte [es:0xB809E], "1"
          int     0x16                                ; await keypress
          pop     es
          pop     ax

Re: OS debugging

Posted: Sun Jan 25, 2009 12:51 pm
by Dex
ru2aqare wrote:Shouldn't that write to the video memory be like this?

Code: Select all

;*******************
        push  ax
        push  es
        xor   ax,ax
        mov   es,ax
        mov   byte [es:0xB809E], "1"
        int    0x16                                ; await keypress
        pop   es
        pop   ax
No it should be more like this:

Code: Select all

;*******************
        push  ax
        push  es
        mov   ax,0xB800
        mov   es,ax
        mov   byte [es:0x9E], "1"
        xor   ax,ax
        int   0x16                                ; await keypres
        pop   es
        pop   ax
As his boot sector is realmode.

Re: OS debugging

Posted: Sun Jan 25, 2009 1:17 pm
by djmauretto
kmtdk wrote:well
if it dont work on a emu, then it is not good.
Very Funny :lol: