PRINT TO BIOS
First Steps
Letβs continue with the previous code and print a message to the screen using the bootloader, the program is set up as follows:
org 0x7c00
bits 16
main:
mov ax, 0
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00
ax
is set to0
to establish a consistent starting point for the program;ds
(data segment),es
(extra segment), andss
(stack segment) are initialized to0
to clear them;sp
is set to0x7c00
, pointing to the bootloader address;
Print Function
Before execution, registers si
, ax
, and bx
are pushed onto the stack to preserve their values during the functionβs execution.
print:
push si
push ax
push bx
si
(source index) used to store the address of the message string (starting point);ax
utilized for passing parameters to BIOS interrupts;- These parameters include the function number
ah
and sometimes data to be printedal
; bx
is preserved by pushing it onto the stack but remains unused throughout the function;
Printing Loop
Within the print function, a loop is established to iterate over the characters of the message string.
print_loop:
lodsb
or al, al
jz print_done
mov ah, 0x0e
mov bh, 0
int 0x10
jmp print_loop
lodsb
loads a byte from the memory location specified by thesi
into theal
;- Additionally, it automatically increments the
si
register to point to the next byte in memory; or al, al
checks ifal
is zero, indicating the end of the string;jz print_done
if the zero flag is set, the program jumps to theprint_done
label;- The character stored in
al
is printed to the screen using BIOS interrupt0x10
with function0x0e
; jmp print_loop
jumps back to theprint_loop
label to continue iterating over the characters;
Running the Program
org 0x7c00 ; set origin to 0x7c00, default address where the BIOS loads the bootloader
bits 16 ; set the assembly to 16-bit mode, typical for bootloader code
main:
mov ax, 0 ; clear the ax register
mov ds, ax ; set the data segment to 0, effectively clearing it
mov es, ax ; set the extra segment to 0, effectively clearing it
mov ss, ax ; set the stack segment to 0, effectively clearing it
mov sp, 0x7c00 ; set the stack pointer to the bootloader address, where the bootloader is loaded
mov si, os_boot_msg ; load the address of the OS boot message into the source index register
call print ; call the print function to print the OS boot message
hlt ; Halt the processor, essentially doing nothing
halt:
jmp halt ; Infinite loop, jumping back to itself, effectively halting the processor indefinitely
print:
push si ; save the source index register on the stack
push ax ; save the ax register on the stack
push bx ; save the bx register on the stack
print_loop:
lodsb ; load the byte at the address in SI into AL and increment SI
or al, al ; check if AL is zero (end of string)
jz print_done ; if AL is zero, end of string, jump to print_done
mov ah, 0x0e ; set the BIOS teletype function to print the character in AL
mov bh, 0 ; set the page number to 0
int 0x10 ; call BIOS interrupt 0x10 to print the character in AL
jmp print_loop ; jump back to print_loop to continue printing characters
print_done:
pop bx
pop ax
pop si
ret
os_boot_msg:
db "OS Booting...", 0x0D, 0x0A, 0
times 510-($-$$) db 0 ; fill the rest of the bootloader space with zeros to ensure it's padded up to 510 bytes
dw 0xaa55 ; boot signature, indicating to the BIOS that this is a bootable device