OSDev.org https://forum.osdev.org/ |
|
Trouble jumping to 32-bit code once in Protected Mode https://forum.osdev.org/viewtopic.php?f=1&t=32642 |
Page 1 of 1 |
Author: | safsom2 [ Tue Dec 19, 2017 10:17 pm ] |
Post subject: | Trouble jumping to 32-bit code once in Protected Mode |
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. |
Author: | MichaelPetch [ Wed Dec 20, 2017 2:43 am ] |
Post subject: | Re: Trouble jumping to 32-bit code once in Protected Mode |
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: Code: org 0x7c00 bits 16 start: 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 load_kernel: 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 .readsector: 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 kernel.asm: Code: org 0x7e00 ; Offset of this code is 0x7e00
; as we loaded it into memory at 0x0000:0x7e00 bits 16 section .text start: cli in al, 0x92 or al, 2 out 0x92, al lgdt[toc] mov eax, cr0 or eax, 1 mov cr0, eax jmp 0x08:start32 ; The FAR JMP is simplified since our segment is 0 section .rodata gdt32: 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 gdt_end: toc: dw gdt_end - gdt32 - 1 dd gdt32 ; The GDT base is simplified since our segment is now 0 bits 32 section .text start32: 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 $ |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |