7678019e03
* Added bootloader files * Changed to spaces from tabs
103 lines
5 KiB
NASM
103 lines
5 KiB
NASM
; Print a null terminated string to the screen
|
|
; DS:SI is the location of the string
|
|
; Input:
|
|
; SI - pointer to the string to be printed in register SI
|
|
print_string_with_new_line:
|
|
pusha ; Push all registers onto the stack
|
|
mov ah, 0x0E ; Specify the teletype output function
|
|
xor bx, bx
|
|
.loop:
|
|
lodsb ; Load byte at address SI into AL and increment SI
|
|
cmp al, 0 ; If it the end of the null-terminated string
|
|
je .done ; Then exit
|
|
int 0x10 ; Else print the character in AL as an interrupt into the BIOS
|
|
jmp short .loop ; Repeat for next character
|
|
.done:
|
|
; Print the line feed and carriage return
|
|
mov al, 0x0A ; Teletype print sub function(0x0E), Line feed (0x0A)
|
|
int 0x10
|
|
mov al, 0x0D ; Carriage return
|
|
int 0x10
|
|
popa ; Pop the register of the stack
|
|
ret ; And return to caller
|
|
|
|
; Reboot the computer if there was an error
|
|
reboot:
|
|
m_write_line reboot_msg
|
|
|
|
xor ah, ah ; Sub function for reading a character
|
|
int 0x16 ; Wait for key press
|
|
int 0x19 ; Warm reboot
|
|
|
|
cli ; If failed to reboot, halt
|
|
hlt ; Halt
|
|
|
|
; Read a sector from the disk
|
|
; ES:BX is the location of the buffer that the data is read into
|
|
; As reads often fail, it will try 4 times to read from the disk. The counter is stored in CX.
|
|
; With the data buffer at ES:BX
|
|
; Input:
|
|
; AX - The logical block address (LBA)
|
|
; ES:BX - The buffer location which the sector will be read into
|
|
read_sector:
|
|
xor cx, cx ; Set the counter to 0
|
|
.read:
|
|
push ax ; Save the logical block address
|
|
push cx ; Save the counter
|
|
|
|
; Convert the logical block address into the head-cylinder/track-sector values
|
|
; The conversions are:
|
|
; (1) Sector = (LBA mod SectorsPerTrack) + 1
|
|
; (2) Cylinder = (LBA / SectorsPerTrack) / NumHeads
|
|
; (3) Head = (LBA / SectorsPerTrack) mod NumHeads
|
|
;
|
|
; Input:
|
|
; AX - the logical block address
|
|
; Output: These are used for the 0x13 BIOS interrupt to read from the disk along with ES:BX and ax
|
|
; CH - Lower 8 bits of cylinder
|
|
; CL - Upper 2 bits of cylinder and 6 bits for the sector
|
|
; DH - The head number
|
|
; DL - The drive number/ID
|
|
.lba_to_hcs:
|
|
push bx ; Save the buffer location
|
|
|
|
;mov bx, word [Sectors_per_track] ; Get the sectors per track
|
|
xor dx, dx ; Set DX to 0x0 (part of operand for DIV instruction and needs to be 0x00)
|
|
div word [Sectors_per_track] ; Divide (DX:AX / Sectors_per_track)
|
|
; Quotient (AX) - LBA / SectorsPerTrack
|
|
; Remainder (DX) - LBA mod SectorsPerTrack
|
|
|
|
inc dx ; (1) Sector = (LBA mod SectorsPerTrack) + 1
|
|
mov cl, dl ; Store sector in cl as defined for the output and for the 0x13 BIOS interrupt
|
|
|
|
;mov bx, word [Head_count] ; Get the number of heads
|
|
xor dx, dx
|
|
div word [Head_count] ; Quotient (AX) - Cylinder = (LBA / SectorsPerTrack) / NumHeads
|
|
; Remainder (DX) - Head = (LBA / SectorsPerTrack) mod NumHeads
|
|
|
|
mov ch, al ; Store cylinder in ch as defined for the output and for the 0x13 BIOS interrupt
|
|
mov dh, dl ; Store head in DH as defined for the output and for the 0x13 BIOS interrupt
|
|
|
|
mov dl, byte [Logical_drive_number] ; Store drive number in DL as defined for the output and for the 0x13 BIOS interrupt
|
|
|
|
pop bx ; Restore the buffer location
|
|
|
|
; Using the values above, read off the drive
|
|
|
|
mov ax, 0x0201 ; Sub function 2 to read from the disk, Read 1 (0x01) sector
|
|
int 0x13 ; Call BIOS interrupt 13h
|
|
jc short .read_fail ; If fails to read (carry bit set)
|
|
|
|
pop cx
|
|
pop ax ; Restore the logical block address
|
|
ret ; If read successful, then return to caller
|
|
.read_fail: ; If failed to read, try again, if tried 4 times, the reboot
|
|
pop cx ; Restore the counter
|
|
inc cx ; Increment the counter
|
|
cmp cx, 4 ; Compare if counter is equal to 4
|
|
je boot_error ; If equal, then error reading 4 times so reboot
|
|
xor ah, ah ; Reset the disk to try again
|
|
int 0x13
|
|
|
|
pop ax ; Restore the logical block address
|
|
jmp .read ; Try to read again
|