The Place to Start for Operating System Developers
It is currently Tue Jan 16, 2018 9:04 am

All times are UTC - 6 hours

Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: Trouble jumping to 32-bit code once in Protected Mode
PostPosted: Tue Dec 19, 2017 10:17 pm 

Joined: Thu Oct 12, 2017 8:23 pm
Posts: 2
After much debate with myself, I have finally decided to move my OS to Protected Mode. However, I am having a few issues executing Protected Mode code. The first step on the OSDev wiki was to enable the A20 line, something I had little trouble with because of the fast gate. The second part was loading the Global Descriptor Table. I followed the BrokenThorn Entertainment tutorial and used it as a rough base for my GDT, and translated some of the long binary values to nice and short hex values. Finally, I set the lowest bit of the cr0 register to 1 to enter protected mode. I then made the far jump to 0x08:start32. Upon executing my code, however, and monitoring the registers using qemu's monitor -stdio flag, I see unexpected results. My main protected mode routine, start32, is simple. It moves the value 0xDEADBABA into the eax register. This however does not seem to take effect, as on QEMU, the value is shown to be 00000100. The cr0 register is 00000010, which seems to be correct, but once again makes me skeptical as it is not the lowest bit that is one. The worst one by far is the GDT register, which is equal to precisely 00000000 00000000. What is the problem here? I have provided code for both my bootsector and my part of the kernel that switches to Protected Mode below.
P.S: The bootsector clears the screen and loads the kernel. That is its only purpose.
start.asm (bootsector) - https://gist.github.com/safsom/54a9c653 ... 8f8a12b62b
kernel.asm (problematic file) - https://gist.github.com/safsom/bc887816 ... 05de670d1c
Any help would be greatly appreciated.

 Post subject: Re: Trouble jumping to 32-bit code once in Protected Mode
PostPosted: Wed Dec 20, 2017 2:43 am 

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 124
This was resolved on SO in the comment area. But the main problem is that he's using real mode segments that aren't zero (ie: 0x7c0, 0x2000 eyc) base on BrokenThorne tutorial. Unfortunately this meant that the base in the GDT was a real mode offset and had to be converted to a linear address. The FAR JMP into protected mode also suffered the same kind of issue. Once in protected mode the offsets the code were running at were not relative to linear address 0x00000. I suggested a simplification of the code to have the jump to protected mode and the GDT in the first 64k and using a segment of 0x0000. This means a 16-bit offset in real mode in the first 64kb is the same as the offset in protected mode. No monkeying around by doing real mode offset to linear address conversions in protected mode. The drive number was hard coded to 0 instead of the one passed in by the BIOS (via DL register) when doing a disk read. A quick fix was to simplify the code he posted to something like the code below. start.asm:
org 0x7c00
bits 16

    xor ax, ax                  ; Set DS to 0. xor register to itselfzeroes register
    mov ds, ax
    mov ss, ax                  ; Stack just below bootloader SS:SP=0x0000:0x7c00
    mov sp, 0x7c00

    mov ah, 0x00
    mov al, 0x03
    int 0x10
    mov ah, 0x02                ; call function 0x02 of int 13h (read sectors)
    mov al, 0x01                ; read one sector (512 bytes)
    mov ch, 0x00                ; track 0
    mov cl, 0x02                ; sector 2
    mov dh, 0x00                ; head 0
;    mov dl, 0x00               ; drive 0, floppy 1. Comment out DL passed to bootloader
    xor bx, bx                  ; segment 0x0000
    mov es, bx                  ; segments must be loaded from non immediate data
    mov bx, 0x7E00              ; load the kernel right after the bootloader in memory
    int 13h                     ; call int 13h
    jc .readsector              ; error? try again

    jmp 0x0000:0x7E00           ; jump to the kernel at 0x0000:0x7e00

times 510-($-$$) db 0
dw 0xAA55

org 0x7e00                ; Offset of this code is 0x7e00
                          ;    as we loaded it into memory at 0x0000:0x7e00

bits 16

section .text
    in al, 0x92
    or al, 2
    out 0x92, al

    mov eax, cr0
    or eax, 1
    mov cr0, eax
    jmp 0x08:start32     ; The FAR JMP is simplified since our segment is 0
section .rodata
    dd 0
    dd 0

    dw 0x0FFFF
    dw 0
    db 0
    db 0x9A
    db 0xCF
    db 0

    dw 0x0FFFF
    dw 0
    db 0
    db 0x92
    db 0xCF
    db 0
    dw gdt_end - gdt32 - 1
    dd gdt32             ; The GDT base is simplified since our segment is now 0

bits 32
section .text
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov esp, 0x9c000    ; Set the stack to grow down from area under BDA/Video memory

    mov dword [0xB8000], 0x2f4b2f4f

    jmp $

Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 6 hours

Who is online

Users browsing this forum: No registered users and 18 guests

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group