You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
6.3 KiB
235 lines
6.3 KiB
BITS 16
|
|
;http://www.ousob.com/ng/bios/ng1223.php
|
|
start:
|
|
; Set up 4K stack after this bootloader
|
|
; [Remember: Effective Address = Segment*16 + Offset]
|
|
mov ax, 0x7C0 ; Set 'ax' equal to the location of this bootloader divided by 16
|
|
add ax, 0x20 ; Skip over the size of the bootloader divided by 16
|
|
mov ss, ax ; Set 'ss' to this location (the beginning of our stack region)
|
|
mov sp, 8192 ; Set 'ss:sp' to the top of our 8K stack
|
|
|
|
; Set data segment to where we're loaded so we can implicitly access all 64K from here
|
|
mov ax, 0x7C0 ; Set 'ax' equal to the location of this bootloader divided by 16
|
|
mov ds, ax ; Set 'ds' to the this location
|
|
|
|
mov [disk_identifier], dl
|
|
; Print our message and stop execution
|
|
mov si, message ; Put address of the null-terminated string to output into 'si'
|
|
call print ; Call our string-printing routine
|
|
mov si, enter_debug_mode
|
|
call print
|
|
call printCRLF
|
|
; here goes wait call, for the user to enter debug mode.
|
|
; Wating for 2 seconds:
|
|
mov ah, 0x86 ; code for waiting interupt call
|
|
mov cx, 0x001e ; high count of microseconds
|
|
mov dx, 0x8480 ; low count
|
|
int 0x15
|
|
|
|
.busy_wait_for_key:
|
|
xor ax, ax
|
|
mov ah, 0x01 ; BIOS call to wait for key
|
|
int 0x16
|
|
jnz debug_mode
|
|
|
|
; entering system check:
|
|
mov si, enter_system_check
|
|
|
|
mov si, sys_check_ok ; Put address of the null-terminated string to output into 'si'
|
|
call print ; Call our string-printing routine
|
|
|
|
mov si, boot_system ; Put address of the null-terminated string to output into 'si'
|
|
call print ; Call our string-printing routine
|
|
|
|
;This goes first as to now overwrite %ah and %al.
|
|
mov ax, 0x0
|
|
mov es, ax ;Section to write into
|
|
mov ah, 0x2 ;Read sectors from drive
|
|
mov al, 0xf ;Number of sectors to read (15 * 512 = 7680 bytes)
|
|
mov ch, 0x0 ;Low 8 bits of cylinder
|
|
mov cl, 0x11 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
|
mov dh, 0x0 ;Head number
|
|
mov dl, [disk_identifier] ;0x0 ;Drive number
|
|
mov bx, 0x7e00 ;Offset into section
|
|
int 0x13 ;Low level disk services
|
|
;mov [0x7000], es ; saving retult of read
|
|
;
|
|
;Debug dump of loaded memory
|
|
;mov si, 500
|
|
;mov cx, 512
|
|
;call b_dumpmem
|
|
|
|
jnc notcarry
|
|
mov si, error_str
|
|
call print
|
|
jmp endcarrycheck
|
|
;
|
|
notcarry:
|
|
mov si, success_str
|
|
call print
|
|
call printCRLF
|
|
call printCRLF
|
|
|
|
; xor ax, ax
|
|
; mov al, [disk_identifier]
|
|
; call dumpax
|
|
mov dl, [disk_identifier]
|
|
|
|
mov ax, 0x7e0
|
|
mov ds, ax
|
|
jmp 0x7e0:0x00
|
|
|
|
endcarrycheck:
|
|
cli ; Clear the Interrupt Flag (disable external interrupts)
|
|
hlt ; Halt the CPU (until the next external interrupt)
|
|
|
|
debug_mode:
|
|
mov si, .welcome_debug
|
|
call print
|
|
cli ; Clear the Interrupt Flag (disable external interrupts)
|
|
hlt
|
|
|
|
.welcome_debug db 'This is debug mode', 0
|
|
data:
|
|
message db 'Bootloader for SingOS! v0.0.3',13,10,0
|
|
enter_debug_mode db 'Press d to enter bootloader debug mode',13,10,0
|
|
enter_system_check db 'Performing system check:',13,10,0
|
|
sys_check_ok db 'System check ok', 13, 10, 0
|
|
boot_system db 'Read SingOS from disk', 13, 10, 0
|
|
error_str db 'Error', 0
|
|
success_str db 'Success', 0
|
|
disk_identifier db 0
|
|
|
|
; Routine for printing a 'ax' as hex
|
|
dumpax:
|
|
pusha ; save registers
|
|
mov bx, ax
|
|
mov ah, 0xE ; Teletype output
|
|
|
|
mov cx, 4 ; 4 nipples in a 16 bit word
|
|
.loop:
|
|
rol bx, 4 ; rotate to next nipple
|
|
mov al, bl ; we copy to al because we need to mask only the low 4 bits
|
|
and al, 1111b ; Do the masking
|
|
add al, '0' ; convert to ASCII
|
|
cmp al, '9' ; If we are greater than 9 ascii, we add 7 to make digit 10 be represented as 'A'
|
|
jbe .skip ; -|-
|
|
add al, 7 ; -|-
|
|
.skip: ; -|-
|
|
int 0x10 ; BIOS call 'output'
|
|
loop .loop
|
|
|
|
popa ; restore registers
|
|
ret
|
|
|
|
dumpax10: ; Prints ax as 16-bit decimal number
|
|
pusha
|
|
|
|
mov bx, 10 ; Divisor
|
|
|
|
mov cx, 5 ; Loop 5 times
|
|
.loop1: ; finds digits and pushes them to stack
|
|
xor dx, dx
|
|
div bx
|
|
add dl, '0'
|
|
push dx
|
|
loop .loop1
|
|
|
|
|
|
mov ah, 0xE
|
|
mov cx, 5 ; Loop 5 times
|
|
mov bl, '0'
|
|
|
|
.loop2: ; Pops from stack until it hits a non-'0' value. It then jumps to nonzero_nopop to print it.
|
|
pop dx
|
|
mov al, dl
|
|
cmp al, bl
|
|
jne .nonzero_nopop
|
|
loop .loop2
|
|
|
|
.nonzero_loop: ; Pops values from the stack and prints them.
|
|
pop dx
|
|
mov al, dl
|
|
.nonzero_nopop: ; Part of the loop that prints the value. Jump to here to print without popping on first iteration.
|
|
int 0x10
|
|
loop .nonzero_loop
|
|
|
|
popa
|
|
ret
|
|
|
|
dumpax10_rev: ; Prints ax as 16-bit decimal number in reverse
|
|
pusha
|
|
|
|
mov cx, 10 ; Divisor
|
|
.loop:
|
|
xor dx, dx ; zero dx
|
|
div cx ; Divide dx:ax by 10 -> quotient in ax, remainder in dx
|
|
|
|
mov bx, ax ; save quotient in bx
|
|
|
|
mov al, dl ; put remainder in al
|
|
add al, '0' ; Make ASCII
|
|
|
|
mov ah, 0xE ; Set teletype output
|
|
int 0x10 ; BIOS: write one char
|
|
|
|
mov ax, bx
|
|
;test ax, ax
|
|
cmp ax, 0
|
|
jnz .loop
|
|
|
|
popa
|
|
ret
|
|
|
|
printCRLF:
|
|
mov ah, 0xE
|
|
mov al, 13
|
|
int 0x10
|
|
mov al, 10
|
|
int 0x10
|
|
ret
|
|
|
|
; Routine for outputting string in 'si' register to screen
|
|
print:
|
|
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function
|
|
; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)]
|
|
.printchar:
|
|
lodsb ; Load byte at address SI into AL, and increment SI
|
|
cmp al, 0
|
|
je .done ; If the character is zero (NUL), stop writing the string
|
|
int 0x10 ; Otherwise, print the character via 'int 0x10'
|
|
jmp .printchar ; Repeat for the next character
|
|
.done:
|
|
ret
|
|
|
|
; b_dumpmem:
|
|
; push ax
|
|
; push dx
|
|
; call printCRLF
|
|
; shr cx, 1
|
|
; xor dx, dx ; zero dx
|
|
; .loop:
|
|
; cmp dx, cx
|
|
; jae .end
|
|
; mov ax, word [esi + 2*edx]
|
|
; call dumpax
|
|
; mov ax, 0xe20
|
|
; int 0x10
|
|
; inc dx
|
|
; jmp .loop
|
|
; .end:
|
|
; pop dx
|
|
; pop ax
|
|
; ret
|
|
; Pad to 510 bytes (boot sector size minus 2) with 0s, and finish with the two-byte standard boot signature
|
|
times 510-($-$$) db 0
|
|
dw 0xAA55 ; => 0x55 0xAA (little endian byte order)
|
|
; bootloder debug_mode goes here
|
|
|
|
times 8192-($-$$) db 0
|
|
|
|
; From Version 0.0.3 we are concatinate the bootloader and the kernel after compile time
|
|
;%include "kernel.nasm"
|
|
|
|
;times 8192-($-$$) db 0
|
|
|
|
|