I currently have a bootloader and a very basic assembly file that I can use for debugging. But when I was trying to print in qemu the stirng doesn't print, and but the cursor does move. My print_int function does output the base 10 integer. Another issue that I have found is that the screen width from address [0x44A] is set to 0.
Boot.s
[org 0x7C00]
[bits 16]
KERNEL_OFFSET equ 0x1000
BDB_SKIP: db 0xEB, 0x3C, 0x90 ; JMP SHORT 3C NOP 3B
BDB_OEM_IDN: db 0x29, 0x3A, 0x63, 0x7E, 0x2D, 0x49, 0x48, 0x43 ; OEM identifier 8B
BDB_BYTES_PER_SECTOR: db 0x00, 0x20 ; Bytes per Sector 2B
BDB_N_SECTORS: db 0x01 ; Sectors per Cluster 1B
BDB_RESERVED_SECTORS: db 0x01, 0x00 ; Reserved Sectors 2B
BDB_N_FATS: db 0x02 ; # of FAT's 1B
BDB_ROOT_DIRECTORY: db 0xE0, 0x00 ; Root Directory 2B
BDB_TOTAL_SECTORS: db 0x40, 0xB0 ; Total Sectors 2B
BDB_MDT: db 0xF0 ; Media Descriptor 1B
BDB_N_SECTORS_PER_FAT: db 0x09, 0x00 ; Sectors per Fat 2B
BDB_N_SECTORS_PER_TRACK: db 0x12, 0x00 ; Sectors per Track 2B
BDB_N_HEADS: db 0x02, 0x00 ; # of Heads 2B
BDB_HIDDEN_SECTORS: db 0x00, 0x00, 0x00, 0x00 ; # of Hidden Sectors 4B
BDB_LARGE_SECTORS: db 0x00, 0x00, 0x00, 0x00 ; Large Sector Count 4B
EBR_DRIVE_NUMBER: db 0x00 ; Drive Number 1B
EBR_RESERVED: db 0x00 ; Reserved 1B
EBR_SIGNATURE: db 0x29 ; Signature 1B
EBR_ID: db 0x00, 0x00, 0x00, 0x00 ; Volume ID 4B
EBR_LABEL: db ' OS' ; Volume Label 11B
EBR_SYS_ID_STR: db 'FAT12 ' ; System ID String 8B
start:
mov [BOOT_DRIVE], dl
cld
mov ah, 0x42
int 0x13
mov ax, 0x03
int 0x10
call load_kernel
cli
in al, 0x92
or al, 0x02
out 0x92, al
lgdt [gdt]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp CODE_SEG:init_pm
load_kernel:
mov bx, KERNEL_OFFSET
mov dh, 0x0F
mov dl, [BOOT_DRIVE]
call disk_load
ret
disk_load:
push dx
mov ah, 0x02
mov al, dh
mov ch, 0x00
mov cl, 0x02
mov dh, 0x00
int 0x13
jc .disk_error
pop dx
cmp dh, al
jne .disk_error
ret
.disk_error:
mov ah, 0x0E
mov al, '!'
mov bh, 0x00
int 0x10
hlt
gdt_start:
null_segment:
dd 0x00000000
dd 0x00000000
code_segment:
c_limit: dw 0xFFFF
c_base_low: dw 0x0000
c_base_middle: db 0x00
c_access: db 0x9A
c_granularity: db 0xCF
c_base_high: db 0x00
data_segment:
d_limit: dw 0xFFFF
d_base_low: dw 0x0000
d_base_middle: db 0x00
d_access: db 0x92
d_granularity: db 0xCF
d_base_high: db 0x00
gdt_end:
gdt:
dw gdt_end - gdt_start - 1
dd gdt_start
CODE_SEG equ code_segment - gdt_start
DATA_SEG equ data_segment - gdt_start
[bits 32]
init_pm:
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov ebp, 0x9C000
mov esp, ebp
.done:
call KERNEL_OFFSET
jmp $
BOOT_DRIVE: db 0x00
times 510-($-$$) db 0x00
dw 0xAA55
Debug.s
[org 0x1000]
[bits 32]
VGA_MEM_BASE equ 0xB8000
kernel_entry:
push esi
xor eax, eax
mov al, byte [0x450]
mov byte [X_POS], al
mov al, byte [0x451]
mov byte [Y_POS], al
mov ax, word [0x44A]
mov word [SCREEN_WIDTH], ax
mov esi, dword [SCREEN_WIDTH]
call print_int
mov eax, dword [Y_POS]
mov ebx, dword [X_POS]
call set_cursor
mov esi, message
call puts
; call puts
; call puts
; call puts
pop esi
ret
;
; Prints a integer onto the screen
; - Params:
; - ESI - Integer that you want to print.
; - No Return
;
print_int:
push eax
push ebx
push ecx
push edx
mov eax, esi
mov ecx, 0x0A
mov ebx, 0x00
.num_loop:
test eax, eax
jz .end_num_loop
xor edx, edx
div ecx
add dl, 0x30
mov dh, byte [VGA_LETTER_COLOR]
push dx
inc ebx
jmp .num_loop
.print_zero:
xor edx, edx
mov dh, byte [VGA_LETTER_COLOR]
mov dl, 0x30
push dx
inc ebx
jmp .print_loop
.end_num_loop:
mov ecx, VGA_MEM_BASE
test ebx, ebx
jz .print_zero
.print_loop:
test ebx, ebx
jz .done
pop ax
mov [ecx], ax
add ecx, 0x02
dec ebx
jmp .print_loop
.done:
pop edx
pop ecx
pop ebx
pop eax
ret
;
; Sets the cursor to the current row and column.
; - Params:
; AL - Y_POS
; BL - X_POS
; - No Return
;
set_cursor:
push edx
mov dx, word [SCREEN_WIDTH]
mul dx
add bx, ax
mov dx, 0x03D4
mov al, 0x0F
out dx, al
inc dl
mov al, bl
out dx, al
dec dl
mov al, 0x0E
out dx, al
inc dl
mov al, bh
out dx, al
pop edx
ret
;
; Gets the position of the cursor
; - No Params
; - Return:
; EAX - The position of the Cursor
; Y_POS * SCREEN_WIDTH + X_POS
;
get_cursor_position:
push edx
xor dx, dx
xor ax, ax
mov dx, 0x03D4
mov al, 0x0E
out dx, al
inc dx
in al, dx
shl ax, 0x08
dec dx
mov al, 0x0F
out dx, al
inc dx
in al, dx
pop edx
ret
;
; Prints a string onto the screen
; - Params:
; - ESI - String that you want to print.
; Always ending in '\0'.
; - No Return
;
puts:
push eax
push ebx
push edx
push edi
push esi
xor eax, eax
xor ebx, ebx
mov al, byte [Y_POS]
mul dword [SCREEN_WIDTH]
mov bl, byte [X_POS]
mov dx, ax
add ax, bx
mov edi, [VGA_MEM_BASE + eax * 2]
mov ah, byte [VGA_LETTER_COLOR]
.loop:
lodsb
cmp al, 0x20
jl .special_char
inc dword [X_POS]
stosw
jmp .loop
.special_char:
test al, al
jz .done
cmp al, 0x0D
je .carriage_return
cmp al, 0x0A
je .newline
jmp .loop
.carriage_return:
lea edi, [ebx + edx * 2]
mov dword [X_POS], 0x00
jmp .loop
.newline:
mov eax, dword [SCREEN_WIDTH]
lea edi, [edi + eax * 2]
inc dword [Y_POS]
inc edx
mov ah, byte [VGA_LETTER_COLOR]
jmp .loop
.done:
mov eax, [Y_POS]
mov ebx, [X_POS]
call set_cursor
pop esi
pop edi
pop edx
pop ebx
pop eax
ret
VGA_LETTER_COLOR: db 0x07
SCREEN_WIDTH: dw 0x00
X_POS: db 0x00
Y_POS: db 0x00
message: db "Hello, World!", 0x0A, 0x00
I looked at this question, Assembly 32-bit print to display code runs on qemu, fails to work on real hardware but it did not help me mcuh at all.