Following the VBE3 spec, I have set up the 100 or so 16 bit segment descriptors as specified.
I use a 16 bit call gate to call the PMInitialize procedure pointed to by the Protected Mode Info Block. The call works properly (as in it jumps into the bios procedure as expected) but on return it fails.
I know this is because the ret sees a 16bit memory address on the stack and it returns 'somewhere' but not to where the call was executed obviously.
According to the Intel docs (IA-32 & 64bit blah blah, vol 3A and Volume 2A), in order to return when using a 16 bit call gate the procedure's offset cannot be more than 0xFFFF bytes from the start of the 32 bit segment. Ok, fine, makes perfect sense. Maybe create a 32 bit segment with a base address closer to the 16 bit procedure and then call the 16 bit call gate that way?
So, what I tried to do next was create a 32 bit call gate which uses a 32 bit segment descriptor with the base address of a 32 bit procedure (just to make sure that would work!). I call it using the CALL 0x50:0 (as specified by the Intel docs - the 0x50 was selected arbitrarily here for my example and the 0 of course is ignored by the CPU for a call gate)
But, this one won't return either!! ?? It jumps into the procedure as expected, I tested it by just sending an int 3 to be caught by my interrupt handler and by calling my puts function to display a string but, when it hits the 'ret' instruction, it fails... what's going on??
For example:
Code: Select all
init_callgate(&gdt[10], 0, 0x60, SD_SEG_PRESENT | SD_DPL_RING0 | SD_SYS_CG16, 0);
/* 32 Bit Code Segment */
gdt_init_descriptor(&gdt[13], 0xFFFF, (uint32)test32,
SD_SEG_PRESENT | SD_DPL_RING0 | SD_DESC_TYPE_CD | SD_SEG_TYPE_CODE,
SD_GRAN_4KBYTE | SD_OP_SIZE_32 | 0x0F
);
Code: Select all
GLOBAL test32
test32:
; int 3 ; - Commented, this code is reached and executed fine
ret ; Fails
Any suggestions would be greatly appreciated..
I'm not using paging. Nor am I using Task Segments yet. Just a simple flat memory model for now.