Long transition after switching from real to protected mode

According to this tutorial, it’s enough to create a simple operating system with switching to protected mode as easy as the following code without the need for other well-known actions, such as turning on the A20 ...

In any case, I am new to this domain, I wrote the following code, as they exactly mentioned, with a modification inspired by this https://stackoverflow.com/a/360960/

Code structure: This simple operating system should boot briefly as follows:

  • Download / read 15 sectors
  • Enable GDT
  • Switch to protected mode (And print "Successfully landed in 32-bit protected mode").
  • Download the kernel and print "X"

However, the emulator is still rebooting. Please attach all code.

bootloader.asm

[bits 16] [org 0x7C00] KERNEL_OFFSET equ 0x1000 xor ax, ax mov ds, ax mov es, ax mov [BOOT_DRIVE], dl mov ax, 0x07E0 ; End of stack cli mov ss, ax mov sp, 0x1200 ; Size of Stack. By this, we assume that stack starts at 9000h ; of size 1200h and ends at 7E00h to avoid being overwritten. sti call load_kernel call switch_to_pm jmp $ %include "src/functions/disk_load.asm" load_kernel: mov bx, KERNEL_OFFSET mov dh, 15 mov dl, [BOOT_DRIVE] call disk_load ret ; Global variables BOOT_DRIVE db 0 SECTORS db 0 MSG_PROT_MODE db "Successfully landed in 32-bit Protected Mode" , 0 %include "src/functions/gdt.asm" %include "src/functions/switch_to_pm.asm" [ bits 32] ; This is where we arrive after switching to and initialising protected mode. BEGIN_PM: mov ebx , MSG_PROT_MODE call print_string_pm ; Use our 32 - bit print routine. ;call KERNEL_OFFSET ; Now jump to the address of our loaded ; kernel code , assume the brace position , ; and cross your fingers. Here we go ! jmp $ ; Hang. %include "src/functions/writing_video_mode.asm" ; Bootsector padding times 510-($-$$) db 0 dw 0xAA55 ; 15 sector padding times 15*256 dw 0xDADA 

disk_load.asm

 disk_load: mov [SECTORS], dh mov ch, 0x00 ;C=0 mov dh, 0x00 ;H=0 mov cl, 0x02 ;S=2 next_group: mov di, 5 ;Max 5 tries again: mov ah, 0x02 ;Read sectors mov al, [SECTORS] int 0x13 jc maybe_retry sub [SECTORS], al ;Remaining sectors jz ready mov cl, 0x01 ;Always sector 1 xor dh, 1 ;Next head on diskette! jnz next_group inc ch ;Next cylinder jmp next_group maybe_retry: mov ah, 0x00 ;Reset diskdrive int 0x13 dec di jnz again jmp disk_error ready: ret disk_error: mov ah, 0x0e mov al, 'Y' int 0x10 jmp $ DISK_ERROR_MSG db "Disk read error!", 0 

gdt.asm

 gdt_start: gdt_null: dd 0x0 ; ' dd ' means define double word ( ie 4 bytes ) dd 0x0 gdt_code: dw 0xffff dw 0x0 db 0x0 db 10011010b ; 1 st flags , type flags db 11001111b ; 2 nd flags , Limit ( bits 16 -19) db 0x0 gdt_data: dw 0xffff dw 0x0 db 0x0 db 10010010b ; 1 st flags , type flags db 11001111b ; 2 nd flags , Limit ( bits 16 -19) db 0x0 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 

switch_to_pm.asm

 [ bits 16 ] switch_to_pm: cli lgdt [ gdt_descriptor ] mov eax , cr0 or eax , 0x1 mov cr0 , eax jmp CODE_SEG:init_pm [ bits 32 ] init_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 BEGIN_PM 

And to make sure that we land in protected mode:

writing_video_mode.asm

 [ bits 32] VIDEO_MEMORY equ 0xb8000 WHITE_ON_BLACK equ 0x0f print_string_pm: push eax push ebx push edx mov edx , VIDEO_MEMORY ; Set edx to the start of vid mem. print_string_pm_loop: mov al, [ebx] mov ah, WHITE_ON_BLACK cmp al, 0 je print_string_pm_done mov [edx], ax add ebx, 1 add edx, 2 jmp print_string_pm_loop print_string_pm_done: pop edx pop ebx pop eax ret 

kernel.c

 void main () { char * video_memory = (char *) 0xb8000; *video_memory = 'X'; } 

By the way, I use this Makefile :

 all: bootloader.bin kernel.bin bootloader.bin: src/bootloader.asm nasm src/bootloader.asm -f bin -o output/bootloader.bin kernel.o: src/kernel/kernel.c gcc -ffreestanding -c src/kernel/kernel.c -o output/kernel.o -m32 kernel.bin: kernel.o ld -o output/kernel.bin -Ttext 0x1000 --oformat binary output/kernel.o -melf_i386 clean: rm -f output/*.* output/* 

and to move it to flash, I use the following commands:

 cat output/bootloader.bin output/kernel.bin > os-image sudo dd if=os-image of=/dev/sdb bs=512 conv=notrunc && sync 

To run it, I use qemu with this command:

 qemu-system-i386 -hda /dev/sdb 

Noting that / dev / sdb is my flash drive.

Problem: In fact, the code lands in protected mode (Ie Print “Successfully landed in 32-bit protected mode”) only when disconnecting / commenting call KERNEL_OFFSET in bootloader.asm . However, when you enable this line, it starts loading and rebooting.

I hope I have provided all the necessary information. It seems to me that the future path should not be so. Any comments are welcome.

+7
c assembly intel operating-system bootloader
source share
1 answer

Just uninstall

times 15 * 256 dw 0xDADA

(By the way, why DADA?)
then compile your kernel, after that

output cat / bootloader.bin output / kernel.bin> os-image

and somehow make your image 8192 os long (16 sectors, bootloader + 15). I'm not a Linux / Unix fan (I can't even use them), but I think the dd command (something like dd if = dev \ zero of = temp_file count = (8192 is the file is the actual size) , and then cat os- image temp-file> os-image ) should complete the task. I'm also not sure if this compilation command is correct (just not sure). I would remove "-melf_i386" from the linker command, but idk, I only used MinGW on Windows (it only looks like GCC).

Sorry for my bad english, hope I helped.

0
source share

All Articles