Boot: Data Calculations | Index | Basics: Output

Write Your Own OS from Scratch - Chapter 1. Boot

Boot: Final Touch Ups

Add a file name string to check if the file exists in the root directory

filename:       db      'DEMOOS  BIN'			; 11 byte file name
		

Load boot sector and compare first filename

    mov     bx, 00500h                                  ; Address 00000h:00500h
    mov     ax,[root]                                   ; Root LBA
    mov     dx,[rootmod]                                ; Root LBA modulous
    call    calcchs                                     ; Calculate CHS
    jc      loaderror
    call    readsec                                     ; Read root sector
    jc      loaderror

    mov     di, bx					; String pointer pointing at 00500h
    mov     cx, 11                                      ; Count 11 bytes
    mov     si, filename                                ; String pointer pointing at filename
    repe    cmpsb                                       ; Repeat if equal compare string at 500
    jnz     loaderror                                   ;   to string at filename
		

Calculate start location of first file.

    mov     ax,[bx+01Ah]				; Get first cluster of our file
    dec     ax						; Decriment it by two
    dec     ax
    mov     bl, [secperclust]				; Multiply cluster by sectors per cluster
    xor     bh, bh
    mul     bx
		

Change the following lines:

    mov     ax, [data]                                  ; Set AX to data
    mov     dx, [datamod]                               ; Set DX to datamod
		

to

    add     ax, [data]                                  ; Set AX to data
    adc     dx, [datamod]                               ; Set DX to datamod
		

boot.asm

;=======================================================
; Boot Sector - boot.asm
; -----------------------------------------------------
; Written in NASM
; Written by Marcus Kelly
;=======================================================

    org     07C00h                                      ; Assemble code for this offset

    jmp     short start                                 ; Jump to boot sector start
    nop                                                 ; place holder

oemname:        db      "DEMO OS "                      ; Operating system name
bytespersec:    dw      512                             ; Bytes per sector
secperclust:    db      1                               ; Sectors per cluster
ressectors:     dw      1                               ; Reserved Sectors
fats:           db      2                               ; Number of FATs on disk
rootdirents:    dw      224                             ; Number of directory entries
sectors:        dw      2880                            ; Sectors per disk
media:          db      0F0h                            ; Always F0 hex for floppy
fatsecs:        dw      9                               ; Sectors per FAT
secpertrack:    dw      18                              ; Sectors per track
heads:          dw      2                               ; Number of heads
hiddensecs:     dd      0                               ; Hidden sectors
hugesectors:    dd      0                               ; Huge sectors
drivenumber:    db      000h                            ; Drive number 000h for floppy
currenthead:    db      0                               ; Reserved byte we are using for disk read
bootsignature:  db      029h                            ; Boot signature
volumeid:       dd      02394C726h                      ; Serial Number
vlumelabel:     db      "DEMO OS DSK"                   ; Disk label
filesystype:    db      "FAT12   "                      ; File system
track:          dw      0                               ; Track for disk read
sector:         db      0                               ; Sector for disk read
root:           dw      0                               ; lba for root
rootmod:        dw      0                               ; lba modulous for root
data:           dw      0                               ; lba for data
datamod:        dw      0                               ; lba modulous for data

start:
    cli                                                 ; Turn off interrupts
    cld							; Make sure we are going forward
    xor     ax, ax                                      ; Zero the ax register
    mov     ds, ax                                      ; Make sure data segment is zero
    mov     es, ax                                      ; Make sure extra segment is zero
    mov     ss, ax                                      ; Make sure stack segment is zero
    mov     sp, 07C00h                                  ; Place stack ptr before boot sector
    sti                                                 ; Turn on interrupts

    int     013h                                        ; AH = 0, Reset disk system

    mov     al, [fats]                                  ; fats * fatsecs + hiddensecs + ressectors
    mul     word [fatsecs]
    add     ax, [hiddensecs]
    adc     dx, [hiddensecs+2]
    add     ax, [ressectors]
    adc     dx, byte 0                                  ; if carry increment modulous
    mov     [root], ax                                  ; Save result in root
    mov     [rootmod], dx                               ; Save modulous in rootmod
    mov     [data], ax                                  ; Seve result in data we will just add
    mov     [datamod], dx                               ; Save modulous in datamod

    mov     ax, 32					; 32 * rootdirents + bytespersec - 1 / 512
    mul     word [rootdirents]
    mov     bx,[bytespersec]
    add     ax, bx
    dec     ax
    div     bx
    add     [data], ax					; save result in data
    adc     word [datamod], byte 0                      ; save modulous in datamod

    mov     bx, 00500h                                  ; Address 00000h:00500h
    mov     ax,[root]                                   ; Root LBA
    mov     dx,[rootmod]                                ; Root LBA modulous
    call    calcchs                                     ; Calculate CHS
    jc      loaderror
    call    readsec                                     ; Read root sector
    jc      loaderror

    mov     di, bx					; String pointer pointing at 00500h
    mov     cx, 11                                      ; Count 11 bytes
    mov     si, filename                                ; String pointer pointing at filename
    repe    cmpsb                                       ; Repeat if equal compare string at 500
    jnz     loaderror                                   ;   to string at filename

    mov     ax,[bx+01Ah]				; Get first cluster of our file
    dec     ax						; Decriment it by two
    dec     ax
    mov     bl, [secperclust]				; Multiply cluster by sectors per cluster
    xor     bh, bh
    mul     bx

    mov     bx, 00700h                                  ; Load second sector at 00000h:00700h

    add     ax, [data]                                  ; Set AX to data
    adc     dx, [datamod]                               ; Set DX to datamod

    mov     cx, 3                                       ; Set count to 3
loadnext:
    push    ax						; Save LBA
    push    cx						; Save count
    push    dx						; Save LBA modulous
    call    calcchs                                     ; Calculate CHS
    jc      loaderrorpop                                ; If there is an issue show load error
    call    readsec                                     ; Read Sector
    jc      loaderrorpop
    pop     dx                                          ; Restore LBA modulous
    pop     cx                                          ; Restore count
    pop     ax                                          ; Restore LBA
    inc     ax                                          ; Increment LBA
    adc     dx, 0                                       ; Add carry to modulous
    add     bx, word [bytespersec]                      ; Add bytespersec to load location
    loop    loadnext                                    ; Load next sector

    jmp     00070h:00000h                               ; Jump to code

loaderrorpop:
    pop    dx                                           ; Clean up
    pop    cx
    pop    ax
loaderror:
    mov     si, message                                 ; si is set to offset Message
    call    strout                                      ; call our string output routine
    xor     ax, ax                                      ; BIOS Routine to Wait for Key
    int     016h
    int     019h                                        ; BIOS Bootstrap (Restart Computer)

;-------------------------------------------------------
; String Output
; Input:
;    DS:SI = Message offset
; Output:
;    AX, BX, SI are destroyed
;-------------------------------------------------------
strout:
    lodsb                                               ; Get character from string
    or      al, al                                      ; Check if our character is zero
    jz      stroutdone                                  ; if it is zero we have finished
    mov     ah, 0Eh                                     ; BIOS print call
    mov     bx, 00007h                                  ; Character attribute
    int     010h                                        ; Call the video BIOS
    jmp     strout                                      ; Get next character
stroutdone:
    ret                                                 ; Return from subroutine

;-------------------------------------------------------
; Calculate CHS
; Input:
;     AX:DX = Logical Sector
; Output:
;     sector
;     head
;     track/cylinder
;-------------------------------------------------------
; sector = (lba % sectors per track) + 1
; head = lba / sectors per track % number of heads
; track = lba / sectors per track / number of heads
calcchs:
    cmp     dx, [secpertrack]                           ; Check within track
    jnc     calcchsfail                                 ; if not fail
    div     word [secpertrack]                          ; LBA / secpertrack
    inc     dl                                          ; LBA % secpertrack + 1
    mov     [sector], dl                                ; Save in sector
    xor     dx, dx                                      ; Clear the modulous
    div     word [heads]                                ; lba / secpertrack / heads
    mov     [currenthead], dl                           ; lba / secpertrack % heads
    mov     [track], ax                                 ; lba / secpertrack / heads
    clc                                                 ; Clear carry to report success
    ret                                                 ; Return from subroutine
calcchsfail:
    stc                                                 ; Set carry to report failure
    ret                                                 ; Return from subroutine

;-------------------------------------------------------
; Read Sector
; Input:
;    bsTrack = Track
;    bsSector = Sector
;    bsHead = Head
;    ES:BX = Location to load sector at
; Output:
;       AX, BX, CX, DX are destroyed
;-------------------------------------------------------
readsec:
    mov     dx, [track]	                                ; Get the track
    mov     cl, 006h                                    ; Rotate the bits 8 and 9 into position
    shl     dh, cl
    or      dh, [sector]                                ; Get the sector with out changing high bits
    mov     cx, dx                                      ; Place in the correct register
    xchg    ch, cl                                      ; Swap bytes to complete the process
    mov     dl, [drivenumber]                           ; Drive number
    mov     dh, [currenthead]                           ; Current Head
    mov     ax, 00201h                                  ; BIOS Disk Read 1 Sector
    int     013h
    ret                                                 ; Return from subroutine

;-------------------------------------------------------
; Data Area
;-------------------------------------------------------

message:        db      00Dh, 00Ah, "Error Loading"     ; Message to be printed
                db      00Dh, 00Ah, 000h

filename:       db      'DEMOOS  BIN'			; 11 byte file name

                times   510-($-$$) db 0                 ; inserts zeros from this address
                                                        ;   to address 510
                dw      0AA55h                          ; Boot signature at 510 / 511
		

Modify the disk image

First we need a way to get the size of our demoos.bin file. Before incbin "demoos.bin" add:

demoosstart:
		

and after add:

demoosend:
		

Now we create a directory structer at the root location. Replace the following:

incbin "rootdir.bin"                                    ; root = fats(2) * fatsecs(9) + ressecs(1)
                                                        ; 9728 = 19 * 512
		

with

                db      "DEMOOS  BIN"                   ; Filename
                db      021h				; Attributes
                db      0                               ; Reserved
                db      0, 0, 0, 0, 0                   ; Reserved
                db      0, 0                            ; Access Date
                dw      0                               ; First Cluster Address High
                db      0C0h, 032h, 0BFh, 01Ch          ; Written Date/Time
                dw      00002h                          ; First Cluster Address Low
                dd      demoosend-demoosstart           ; File Size
		

osdisk.asm

;=======================================================
; Disk Image - osdisk.asm
; -----------------------------------------------------
; Written in NASM
; Written by Marcus Kelly
;=======================================================
incbin "boot.bin"                                       ; include our boot.bin file as binary
incbin "demoos2.bin"                                    ; include our demoos2.bin file as binary

                times 9728-($-$$) db 0                  ; Place our file at 9728
                db      "DEMOOS  BIN"                   ; Filename
                db      021h				; Attributes
                db      0                               ; Reserved
                db      0, 0, 0, 0, 0                   ; Reserved
                db      0, 0                            ; Access Date
                dw      0                               ; First Cluster Address High
                db      0C0h, 032h, 0BFh, 01Ch          ; Written Date/Time
                dw      00002h                          ; First Cluster Address Low
                dd      demoosend-demoosstart           ; File Size

                times 16896-($-$$) db 0                 ; (32 * 224 + 512 - 1) / 512 = 14
demoosstart:
incbin "demoos.bin"                                     ; 14 * 512 + 9728 = 16896
demoosend:

                times 1474560-($-$$) db 0               ; Make file size 1,474,560 bytes long
                                                        ;   This is the size of a floppy disk

		

Now lets build our disk. If you are running the previous tutorial in VirtualBox Remember to remove the disk or close virtual box before assembling the disk image.

> nasm boot.asm -o boot.bin
> nasm osdisk.asm -o osdisk.img
		

Your osdisk.img can now be loaded with VirtualBox. The result should be as follows:


DEMO OS V0.01
		
Boot: Data Calculations | Index | Basics: Output

Support This Project On Patreon

Copyright © 2021 Marcus Kelly