EDIT: My problem solved when I move everything after BITS 32 to disk_double_error but now it is still broken yesy it displays the message but then when i hit Y it just restarts/reboots the system What may be the reason for that ?
(sry for bad english) Hello I am trying to write a simple os just for fun I made my bootloader and I displayed some messages and read the disk but when it comes to switching to 32 bit protected mode all of the things I did doesnt work It normally displayed
`> `
`>succesfully loaded = if loaded succesfully > failed = if not `
`>Do you want to boot kernel mode Y/N then gets input`
`>Booting in kernel mode = if Y null = if no`
But after i added lgdt and other switches to 32 bit it just doesnt display anything at all so I thought that switching is somehow clearing the screen so i tried to print things in pm with print_string_pm function but still nothing I am using
nasm -fbin bootload.asm -o bootload.bin
to compile the bootloader
What may be wrong with my code please help ?
here is the code:
BITS 16
[ORG 0x7c00]
global _boot_start
_boot_start:
cli
mov bx,0x9000
mov bp,bx
mov sp,bx
sti
pusha
mov ax, 0x0000
mov ds, ax
mov es, ax
popa
mov [bootdev], dl
mov bx, MSG_START
call print_string
mov dl, [bootdev]
mov dh, 1
mov bx, 0x1000
call disk_load
mov bx, MSG_YESNO
call print_string
call get_yes_no
mov bx, MSG_BOOT_KERNEL
call print_string
lgdt [gdt_descriptor]
mov eax , cr0
or eax , 0x1
mov cr0 , eax
jmp CODE_SEG:pm
BITS 32
pm:
mov ax , DATA_SEG
mov ds , ax
mov ss , ax
mov es , ax
mov fs , ax
mov gs , ax
mov ebp , 0x90000
mov esp , ebp
call beg_pm
beg_pm:
mov ebx,MSG_BOOT_32
call print_string_pm
call KERNEL_OFFSET
jmp $
;******************************************************************
print_string:
.loop:
mov al,[bx]
cmp al,0
je return
push bx
mov ah,0Eh
int 10h
pop bx
inc bx
jmp .loop
return:
ret
;******************************************************************
get_yes_no:
pusha
.loop:
mov ah, 00h
int 16h
cmp ah, 15h
je .yes
cmp ah, 31h
je .no
jmp .loop
ret
.no:
mov bx, No
call print_string
mov ah, 00h
int 13h
jmp $
.yes:
mov bx, Yes
call print_string
jmp .done
.done:
popa
ret
;******************************************************************
disk_load:
push dx
mov ah, 02h
mov al, dh
mov ch, 0x00
mov dh, 0x00
mov cl, 0x02
int 0x13
pop dx
jc disk_error
cmp dh, al
jne disk_error_double
mov bx,MSG_LOAD_SUCC
call print_string
ret
disk_error:
mov bx,MSG_LOAD_FAIL
call print_string
jmp $
disk_error_double:
mov bx,MSG_LOAD_FAIL_C
call print_string
jmp $
;******************************************************************
print_string_pm :
pusha
mov edx , VIDEO_MEMORY ; Set edx to the start of vid mem.
.print_string_pm_loop :
mov al , [ ebx ] ; Store the char at EBX in AL
mov ah , WHITE_ON_BLACK ; Store the attributes in AH
cmp al , 0 ; if (al == 0), at end of string , so
je .print_string_pm_done ; jump to done
mov [edx], ax ; Store char and attributes at current
; character cell.
add ebx , 1 ; Increment EBX to the next char in string.
add edx , 2 ; Move to next character cell in vid mem.
jmp .print_string_pm_loop ; loop around to print the next char.
.print_string_pm_done :
popa
ret
; Global Descriptor table
; GDT
gdt_start :
gdt_null : ; the mandatory null descriptor
dd 0x0 ; 'dd ' means define double word ( i.e. 4 bytes )
dd 0x0
gdt_code :
dw 0xffff ; Limit ( bits 0 -15)
dw 0x0 ; Base ( bits 0 -15)
db 0x0 ; Base ( bits 16 -23)
db 10011010b ; 1st flags , type flags
db 11001111b ; 2nd flags , Limit ( bits 16 -19)
db 0x0 ; Base ( bits 24 -31)
gdt_data :
dw 0xffff ; Limit ( bits 0 -15)
dw 0x0 ; Base ( bits 0 -15)
db 0x0 ; Base ( bits 16 -23)
db 10010010b ; 1st flags , type flags
db 11001111b ; 2nd flags , Limit ( bits 16 -19)
db 0x0 ; Base ( bits 24 -31)
gdt_end :
gdt_descriptor :
dw gdt_end - gdt_start - 1
dd gdt_start
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
MSG_START DB ">",13,10,0
MSG_LOAD_SUCC DB "> Succesfully loaded",13,10,0
MSG_LOAD_FAIL DB "> Failed to load Please try to restart the system",13,10,0
MSG_LOAD_FAIL_C DB "> Error while loading",13,10,0
MSG_YESNO DB "> Do you want to boot up in kernel mode Y/N :",0
MSG_BOOT_KERNEL DB 13,10,"> Booting in kernel mode",0
MSG_BOOT_32 DB "32 bit pm",13,10,0
Yes db "Y",0
No db "N",0
bootdev: db 0
KERNEL_OFFSET equ 0x1000
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
times 510-($-$$) db 0
dw 0xaa55
And here is my kernel code:
int kmain()
{
char* vm = 0xb8000;
*vm = 'X';
}
and my kernel entry
[BITS 32]
[extern _kmain]
call _kmain
jmp $
I use follwing lines to build my disk image:
nasm -fbin bootload.asm -o bootload.bin
gcc -ffreestanding -c kernel.c -o kernel.o
nasm kernel_entry.asm -f elf -o k_entry.o
ld -T NUL -o kernel.tmp -Ttext 0x1000 k_entry.o kernel.o
objcopy -O binary -j .text kernel.tmp kernel.bin
copy /b bootload.bin+kernel.bin os-image.bin
I'm going to ignore issues with setting SP without SS and other issues. See the comments under the question for things you can do to clean up the code.
Your primary problem is in switching to 32-bit instruction encoding with bits 32
. Once you set encoding to 32-bit all the instructions after it will be encoded as 32-bit until you change (with bits 16
). The easiest thing you can do is move the code for label pm
to a point past all your 16-bit code. Move all these lines (deleting the original):
BITS 32
pm:
mov ax , DATA_SEG
mov ds , ax
mov ss , ax
mov es , ax
mov fs , ax
mov gs , ax
mov ebp , 0x90000
mov esp , ebp
call beg_pm
beg_pm:
mov ebx,MSG_BOOT_32
call print_string_pm
call KERNEL_OFFSET
jmp $
to the beginning of the 32-bit code you have. That appears to be the print_string_pm
label. So when moved it would look like:
[snip]
disk_error_double:
mov bx,MSG_LOAD_FAIL_C
call print_string
jmp $
BITS 32
pm:
mov ax , DATA_SEG
mov ds , ax
mov ss , ax
mov es , ax
mov fs , ax
mov gs , ax
mov ebp , 0x90000
mov esp , ebp
call beg_pm
beg_pm:
mov ebx,MSG_BOOT_32
call print_string_pm
call KERNEL_OFFSET
jmp $
;******************************************************************
print_string_pm :
pusha
[snip]
The code for disk_error_double
was the last of your 16-bit code, print_string_pm
was the beginning of the 32-bit code. We simply place the pm
code after disk_error_double
and before print_string_pm
.
Before entering protected mode you will need to turn off interrupts until you set up an Interrupt Descriptor Table (IDT). Place a cli
instruction before mov cr0 , eax
. Failure to do this will cause a triple fault and reboot when the first interrupt occurs while in protected mode.