My OS don't boot

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Minkizz
Posts: 4
Joined: Wed Jul 18, 2018 1:54 am
Libera.chat IRC: esi

My OS don't boot

Post by Minkizz »

Hello everyone, I need help. I watched a OS tutorial but it don't work. I use VirtualBox for testing purposes.
The tutorial link is https://www.cs.bham.ac.uk/~exr/lectures ... os-dev.pdf.

Now I will give you technical details :
Source code of BSECT.ASM (Bootsector):

Code: Select all

[org 0x7c00]
KERNEL_OFFSET equ 0x1000

mov [BOOT_DRIVE], dl	; BIOS stores our boot drive in DL , so it 's
						; best to remember this for later.

mov bp, 0x9000
mov sp, bp

mov si, MSG_REAL_MODE
call print_string

call load_kernel

call switch_to_pm

jmp $

%include "features/print_string.asm"
%include "features/disk_load.asm"
%include "features/gdt.asm"
%include "features/print_string_pm_OLD.asm"
%include "features/switch_to_pm.asm"

[bits 16]
load_kernel:
	mov si, MSG_LOAD_KERNEL
	call print_string

	mov bx, KERNEL_OFFSET
	mov dh, 30
	mov dl, [BOOT_DRIVE]
	call disk_load
	ret

[bits 32]
BEGIN_PM:
	mov ebx, MSG_PROT_MODE
	call print_string_pm

	call KERNEL_OFFSET

	jmp $

BOOT_DRIVE:
	db 0

MSG_REAL_MODE:
	db "Loading 16-bit mode...", 0

MSG_PROT_MODE:
	db "Switching to 32-bit mode...", 0

MSG_LOAD_KERNEL:
	db "Loading kernel into memory...", 0

times 510-($-$$) db 0
dw 0xaa55
The bootsector load a binary file named KERNEL.ASM:

Code: Select all

[bits 32]
	
jmp main
%include "features/print_string.asm"
%include "features/print_string_pm.asm"

main:
	mov bx, KERNEL_LOADED
	call print_string
	jmp loop
loop:

	; Stuff here


	jmp loop

KERNEL_LOADED:
	db "The kernel has been successfully loaded !", 0
I compile my files with a Makefile.

Code: Select all

BSECT.BIN: BSECT.ASM
	@echo off
	nasm -f bin -o BSECT.BIN BSECT.ASM
	cp BSECT.BIN C:\\Users\\LEO\\Desktop\\MinkizzOS\\versions\\1\\compiled
	rm BSECT.BIN
	nasm -f bin -o KERNEL.BIN KERNEL.ASM
	cp KERNEL.BIN C:\\Users\\LEO\\Desktop\\MinkizzOS\\versions\\1\\compiled
	rm KERNEL.BIN
Then I create a bootable ISO with ImgBurn.
I'm sure it is bootable because it print me this message :
"Loading 16-bit mode...Loading kernel into memory..."

That's strange because the 32-bit message don't print.

I will also give you the #include files :

print_string.asm :

Code: Select all

print_string:			; Routine: output string in SI to screen
	mov ah, 0Eh		; int 10h 'print char' function

.repeat:
	lodsb			; Get character from string
	cmp al, 0
	je .done		; If char is zero, end of string
	int 10h			; Otherwise, print it
	jmp .repeat

.done:
	ret
disk_load :

Code: Select all

; load DH sectors to ES:BX from drive DL

disk_load.asm :
	push dx ; Store DX on stack so later we can recall
	; how many sectors were request to be read ,
	; even if it is altered in the meantime
	mov ah, 0x02 ; BIOS read sector function
	mov al, dh ; Read DH sectors
	mov ch, 0x00 ; Select cylinder 0
	mov dh, 0x00 ; Select head 0
	mov cl, 0x02 ; Start reading from second sector ( i.e.
	; after the boot sector )
	int 0x13 ; BIOS interrupt
	jc disk_error ; Jump if error ( i.e. carry flag set )
	pop dx ; Restore DX from the stack
	cmp dh , al ; if AL ( sectors read ) != DH ( sectors expected )
	jne disk_error ; display error message
	ret
	disk_error :
	mov bx, DISK_ERROR_MSG
	call print_string
	jmp $
	; Variables
	DISK_ERROR_MSG db " Disk read error !" , 0
gdt.asm :

Code: Select all

; GDT
gdt_start :
gdt_null : ; the mandatory null descriptor
dd 0x0 ; ’dd ’ means define double word ( i.e. 4 bytes )
dd 0x0
gdt_code : ; the code segment descriptor
; base=0x0 , limit=0xfffff ,
; 1st flags : ( present )1 ( privilege )00 ( descriptor type )1 -> 1001 b
; type flags : ( code )1 ( conforming )0 ( readable )1 ( accessed )0 -> 1010 b
; 2nd flags : ( granularity )1 (32 - bit default )1 (64 - bit seg )0 ( AVL )0 -> 1100 b
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 : ; the data segment descriptor
; Same as code segment except for the type flags :
; type flags : ( code )0 ( expand down )0 ( writable )1 ( accessed )0 -> 0010 b
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 : ; The reason for putting a label at the end of the
; GDT is so we can have the assembler calculate
; the size of the GDT for the GDT decriptor ( below )
; GDT descriptior
gdt_descriptor :
dw gdt_end - gdt_start - 1 ; Size of our GDT , always less one
; of the true size
dd gdt_start ; Start address of our GDT
; Define some handy constants for the GDT segment descriptor offsets , which
; are what segment registers must contain when in protected mode. For example ,
; when we set DS = 0 x10 in PM , the CPU knows that we mean it to use the
; segment described at offset 0 x10 ( i.e. 16 bytes ) in our GDT , which in our
; case is the DATA segment (0 x0 -> NULL ; 0x08 -> CODE ; 0 x10 -> DATA )
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
print_string_pm.asm :

Code: Select all

[BITS 32]

print_string_pm:			; Routine: output string in SI to screen
	mov ah, 0Eh		; int 10h 'print char' function

.repeat:
	lodsb			; Get character from string
	cmp al, 0
	je .done		; If char is zero, end of string
	int 10h			; Otherwise, print it
	jmp .repeat

.done:
	ret
print_string_pm_OLD.asm :

Code: Select all

[bits 32]
; Define some constants
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
; prints a null - terminated string pointed to by EDX
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 ; Return from the function
switch_to_pm.asm :

Code: Select all

[bits 16]
; Switch to protected mode
switch_to_pm :
	cli ; We must switch of interrupts until we have
		; set -up the protected mode interrupt vector
		; otherwise interrupts will run riot.
	lgdt [ gdt_descriptor ] ; Load our global descriptor table , which defines
	; the protected mode segments ( e.g. for code and data )
	mov eax, cr0 ; To make the switch to protected mode , we set
	or eax, 0x1 ; the first bit of CR0 , a control register
	mov cr0, eax
	jmp CODE_SEG : init_pm ; Make a far jump ( i.e. to a new segment ) to our 32 - bit
	; code. This also forces the CPU to flush its cache of
	; pre - fetched and real - mode decoded instructions , which can
	; cause problems.
	[bits 32]
	; Initialise registers and the stack once in PM.
	init_pm :
		mov ax, DATA_SEG ; Now in PM , our old segments are meaningless ,
		mov ds, ax ; so we point our segment registers to the
		mov ss, ax ; data selector we defined in our GDT
		mov es, ax
		mov fs, ax
		mov gs, ax
		mov ebp, 0x90000 ; Update our stack position so it is right
		mov esp, ebp ; at the top of the free space.
		call BEGIN_PM ; Finally , call some well - known label
MDenham
Member
Member
Posts: 62
Joined: Sat Nov 10, 2012 1:16 pm

Re: My OS don't boot

Post by MDenham »

Your crash is happening when you int 10h in protected mode, because (1) you don't have a proper IDT yet and (2) BIOS calls aren't designed to be done from protected mode anyway.
Minkizz
Posts: 4
Joined: Wed Jul 18, 2018 1:54 am
Libera.chat IRC: esi

Re: My OS don't boot

Post by Minkizz »

So how I can fix it ? Do I need to load the kernel before I switch to 32-bit mode ?
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: My OS don't boot

Post by iansjack »

You have to write your own code to print to the screen, to get characters from the keyboard, to read and write storage, etc. You cannot use BIOS calls unless you want to work in real mode only, which is pretty restrictive.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: My OS don't boot

Post by Schol-R-LEA »

Would you mind checking the tutorial link, please? You said you 'watched' the tutorial (implying that it was a video), but the link is to a PDF - and one that is on a site whose cert has expired, apparently, at that (though that could just be my browser being a nuisance).
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
Minkizz
Posts: 4
Joined: Wed Jul 18, 2018 1:54 am
Libera.chat IRC: esi

Re: My OS don't boot

Post by Minkizz »

Yes sorry I'm not english but yes this is a PDF.
StudlyCaps
Member
Member
Posts: 232
Joined: Mon Jul 25, 2016 6:54 pm
Location: Adelaide, Australia

Re: My OS don't boot

Post by StudlyCaps »

Couple of things I saw :
KERNEL.asm includes two different versions of print_string - but both are real mode. The only one that will work in protected mode is the one defined in print_string_pm_OLD.asm because that's the only one that doesn't use int 10 (which you can't do in protected mode). Also you explicitly call print_string and not print_string_pm, so you're jumping into 16 bit code anyway.
Does the code crash (reset the emulator) or hang, or what? If it is a crash maybe try taking out the call KERNEL_OFFSET line and just jmp $ after print_string_pm? Just in case it's an issue with the kernel loading or memory mapping.
Also I'd get rid of print_string_pm.asm (keep print_string_pm_OLD.asm) - it can't possibly work and might be polluting the namespace by defining the label print_string_pm twice.

PS- I don't get a cert warning on Chrome, but now I'm paranoid... :shock:
Minkizz
Posts: 4
Joined: Wed Jul 18, 2018 1:54 am
Libera.chat IRC: esi

Re: My OS don't boot

Post by Minkizz »

Ok, I updated the print_string_pm to print_string_pm_OLD and I replaced all print_string in 32-bit to print_string_pm_OLD, but nothing change. The 32-bit message is not printed and the kernel is not loaded.
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: My OS don't boot

Post by MichaelPetch »

I got a chance to look through your code. I created a version of your code that has two versions of print_string, one for PM and one for real mode. You had 3 different versions and one that was incorrect (int 0x10 in protected mode). The beginning of your bootloader needed some tidying up. I explicitly set the segments to 0 in KERNEL.ASM since you are using an ORG of 0x7c00 (Don't rely on their values being what you expect when the CPU starts executing your bootloader). The big problem I noticed was in KERNEL.ASM. You never specified an ORG statement so it defaulted to 0x00000000. Your kernel was loaded into memory at physical address 0x1000 so you need to set ORG to 0x1000 as well.

A copy of your project with these minor changes can be found here: http://www.capp-sysware.com/misc/osdev/os1/
Post Reply