Skip to content

Latest commit

 

History

History
263 lines (196 loc) · 5.85 KB

File metadata and controls

263 lines (196 loc) · 5.85 KB

Code: Bootloader that load OS and print messages

[ORG 0x00]
[BITS 16]

SECTION .text

; initialize code segment before running code
jmp 0x07C0:START

; env for MINT64OS
TOTALSECTORCOUNT: dw 1024 ; size of MINT64OS image is 1024 sectors

; code section
START:

    ; use ds for accessing variables such as MESSAGE1
    mov ax, 0x07C0
    mov ds, ax

    ; use es for accessing video memory
    mov ax, 0xB800
    mov es, ax

    ; set regs for a stack from 0x0000:0000 to 0x0000:FFFF (64KB)
    mov ax, 0x0000
    mov ss, ax
    mov sp, 0xFFFE ; 0xFFFE is not mistake! this is for alignment
    mov bp, 0xFFFE

    ;; start of .CLEARSCREENLOOP
    mov si, 0 ; video memory addr index

; clear all screen and change text color to green
; and print start message to the top of screen
.CLEARSCREENLOOP:

    mov byte [es:si], 0x00 ; delete all letters in screen
    mov byte [es:si+1], 0x0A ; black background/ green color

    add si, 2

    cmp si, 80 * 25 * 2 ; 80 columns, 25 rows, 2 bytes 
    jl .CLEARSCREENLOOP

    mov si, 0
    mov di, 0

    ; print welcome message
    push MESSAGE1     ; addr of message
    push 0            ; y coordinate
    push 0            ; x coordinate
    call PRINTMESSAGE
    add sp, 6         ; according to cdecl coordinate, remove params from stack

    ; print message for loading OS on the second line
    push IMAGELOADINGMESSAGE
    push 1
    push 0
    call PRINTMESSAGE
    add sp, 6

; Before loading OS, reset disk by using BIOS I/O service
RESETDISK:
    ; call BIOS reset function
    mov ax, 0 ; service num: 0 (reset)
    mov dl, 0 ; drive num: 0 (floppy)
    int 0x13

    jc HANDLEDISKERROR

    ;; start of READDATA

    ; 0x10000 is start addr of OS in memory
    ; regs for reading data: dest_addr
    mov si, 0x1000
    mov es, si
    mov bx, 0x0000

    ; reg for reading data: count
    mov di, word [TOTALSECTORCOUNT]

READDATA:
    ; check if there is no more sectors to read
    cmp di, 0
    je READEND

    sub di, 0x01

    ; call BIOS I/O service
    mov ah, 0x02                ; service number (read sector)
    mov al, 0x01                ; number of sectors to read
    mov ch, byte [TRACKNUMBER]
    mov cl, byte [SECTORNUMBER]
    mov dh, byte [HEADNUMBER]
    mov dl, 0x00                ; drive to read (0=Floppy)
    int 0x13                    ; interrupt to execute service

    jc HANDLEDISKERROR    

    ; set next dest_addr: after 512 byte from prev dest
    add si, 0x0020
    mov es, si

    ; set sector, head, track numbers to next src_addr
    ; floppy sector range: 1~18
    ; floppy head range: 0~1
    ; floppy track(cylinder) range: 0~79
    mov al, byte [SECTORNUMBER]
    add al, 0x01
    mov byte [SECTORNUMBER], al
    cmp al, 19
    jl READDATA

    xor byte [HEADNUMBER], 0x01
    mov byte [SECTORNUMBER], 0x01
    cmp byte [HEADNUMBER], 0x00
    jne READDATA

    add byte [TRACKNUMBER], 0x01
    jmp READDATA

READEND:

    ; print loading complete message at (1,20)
    push LOADINGCOMPLETEMESSAGE
    push 1
    push 20
    call PRINTMESSAGE
    add sp, 6

    ;; start of executing loaded OS
    jmp 0x1000:0x0000

;; From here, functions are defined except HANDLEDISKERROR

; print error message and run infinite loop
HANDLEDISKERROR:
    ; print error message at (1, 20)
    push DISKERRORMESSAGE
    push 1
    push 20
    call PRINTMESSAGE

    jmp $

; function signature in C: PrintMessage(iX, iY, pcString)
; follow cdecl calling convention
PRINTMESSAGE:
    ; set env for current function: new stack, empty regs
    ; all values will be restored at the end
    push bp
    mov bp, sp

    push es
    push si
    push di
    push ax
    push cx
    push dx
    ; end of setting env

    ; seg for video memory address
    mov ax, 0xB800
    mov es, ax

    ; calculate video address for x and y coordinates
    ; y coordinate
    mov ax, word [bp+6] ; short iY
    mov si, 160         ; 80 * 2 (row * char size of text mode)
    mul si              ; iY * 160
    mov di, ax

    ; x coordinate
    mov ax, word [bp+4] ; short iX
    mov si, 2           ; 2 (char size of text mode)
    mul si              ; iX * 2
    add di, ax          ; di == iY * 160 + iX * 2

    mov si, word [bp+8] ; char *pcString

.MESSAGELOOP:
    mov cl, byte [si]

    ; if string ends with 0, then get out of the loop
    ; I defined every string to ends with 0
    cmp cl, 0
    je .MESSAGEEND

    mov byte [es:di], cl

    add si, 1
    add di, 2

    jmp .MESSAGELOOP

.MESSAGEEND:
    ; pop in the reverse order of push because stack is Last-In, First-out
    pop dx
    pop cx
    pop ax
    pop di
    pop si
    pop es
    pop bp
    ret ; go back to calling address

;; Start of data section

MESSAGE1: db 'Mint64 OS Boot Loader Start~!!', 0 ; welcome message

; error message when failed to reset disk or to read data from disk
DISKERRORMESSAGE: db 'DISK Error~!!', 0

; message to print while loading
IMAGELOADINGMESSAGE: db 'OS Image Loading...', 0

; message to print when finished loading OS
LOADINGCOMPLETEMESSAGE: db 'Complete~!!', 0

; disk related variables
; vars for reading data: src_addr
SECTORNUMBER: db 0x02 ; os image starts from 0x02 sector
HEADNUMBER: db 0x00
TRACKNUMBER: db 0x00

; add padding between above code and MBR signature
times 510 - ($ - $$) db 0x00

; MBR signature
db 0x55
db 0xAA

Explanation

What does code do?

  1. initialize all segments

    • CS, DS, ES
  2. clear screen

  3. reset disk by using BIOS I/O service

  4. read OS image to memory by using BIOS I/O service

    • if 3 or 4 fails, go to disk error handler which is just inifinte loop
  5. jump to addr where OS image resides.

    • Currently, I made only bootloader

Assembly

  1. Difference between .label and label is that the leading dot is NASM's syntax for making local labels, which essentially nest on top of the last ordinary (non-local) label.

References

  1. Nasm dotted labels