How to access data I had before switching to protected mode?
Posted: Sun May 17, 2015 8:33 am
Hi again all.
So yesterday I got into protected mode for the first time, but now I'm not sure how to go about this.
Yesterday when jumping into protected mode, I was still within my 512 bootsector limit. Now I have moved the kernel code into it's own file which will be on the next sector of the disk. Thanks to a couple of you a couple of days ago I learned how to read sectors off the disk and jump to it.
In my current build, before switching to protected mode I load the second sector off the disk to 0x7E00, which should hopefully put me right next to my boot loader. But then after switching to protected mode... how do I jump to my kernel?
I will post the files I think relevant -
boot.asm - The bootsector
gdt.asm - The table and few macros ( TBH NOT FULLY UNDERSTOOD, I've been reading material but it's not soaking in )
Hope someone could give me some insight, sorry to be a bother if it's a silly question.
So yesterday I got into protected mode for the first time, but now I'm not sure how to go about this.
Yesterday when jumping into protected mode, I was still within my 512 bootsector limit. Now I have moved the kernel code into it's own file which will be on the next sector of the disk. Thanks to a couple of you a couple of days ago I learned how to read sectors off the disk and jump to it.
In my current build, before switching to protected mode I load the second sector off the disk to 0x7E00, which should hopefully put me right next to my boot loader. But then after switching to protected mode... how do I jump to my kernel?
I will post the files I think relevant -
boot.asm - The bootsector
Code: Select all
[bits 16]; We are in 16 bit Real Mode
org 0x7c00; We are loaded by BIOS at 0x7C00
start: jmp loader; jump to start
real_mode_msg db "Testing A20, ",0;
A20_on db "A20 is enabled.",0;
A20_off db "A20 is disabled. ",0;
bios_attempt db "Calling BIOS. ",0;
disk_load db "Loading kernel off disk..",0;
disk_loaded db "kernel loaded.",0;
start_drive db 0;
kernel_offset dw 0x7E00;
;*************************************************;
; Bootloader Entry Point
;*************************************************;
loader:
xor ax,ax;
mov ds,ax;
mov es,ax;
mov [start_drive], dl ; save drive number
cli ; Set up stack
mov ss,ax;
mov sp,0x7bff;
sti;
mov si, real_mode_msg;
call print_string;
call test_A20; Test if A20 gate is on
cmp ax, 1;
jne .Failed;
mov si, A20_on;
call print_string;
jmp .continue;
.Failed:
mov si, A20_off;
call print_string;
mov si, bios_attempt;
call print_string;
call enable_A20_bios; The bios call works on VirtualBox
mov si, real_mode_msg;
call print_string;
call test_A20;
cmp ax, 1;
jne .bios_failed;
mov si, A20_on;
call print_string;
jmp .continue;
.bios_failed:
mov si, A20_off;
call print_string;
.continue:
; Load the kernel off the disk to 0000:7E00h
mov si, disk_load;
call print_string;
xor ax, ax;
mov es, ax;
mov bx, [kernel_offset];
call reset_drive;
mov cl, 2;
mov al, 1;
mov dl, [start_drive];
call read_sector;
mov si, disk_loaded;
call print_string;
call switch; switch to protected mode
jmp $
%include "real_mode\print_string.asm";
%include "real_mode\read_sector.asm";
%include "real_mode\test_A20.asm";
%include "real_mode\gdt.asm";
; we get here after the switch to PM mode
pmode:
`` ; Now I need to jump to my kernel
cli;
hlt;
jmp $;
times 510 - ($-$$) db 0 ; We have to be 512 bytes. Clear the rest of the bytes with 0
dw 0xAA55 ; Boot Signature
gdt.asm - The table and few macros ( TBH NOT FULLY UNDERSTOOD, I've been reading material but it's not soaking in )
Code: Select all
; GDT Table
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 =0 xfffff ,
; 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
dd gdt_start ; of the true size
; 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
[bits 16]
switch:
cli;
lgdt [gdt_descriptor] ; Load our global descriptor table , which defines
sti ; 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 pmode ; Finally , call some well - known label
Hope someone could give me some insight, sorry to be a bother if it's a silly question.