Page 1 of 1

problem in gdt setup for bigrealmode

Posted: Tue Jun 19, 2012 7:44 pm
by sawdust
Hi,
I'm trying to setup gdt for the CS, DS, SS and video so that we could read/write the memory mapped registers of a pci card.
On switching back, we have to restore all the segments. Any pointers will be very helpful.

I wrote 0x11223344 at location 0x200000 and get some garbage values on reading back.
Tools used: MSVC1.5 and MASM6.5.
environment: option bios

Code: Select all

// -- 'C' file --

void	SetUpGdtTbl(void)
{
	//ProcSaveSegs()
	//===============	
	__asm{
        mov ax, cs
		mov	gPrevCS, ax
        mov ax, ds
		mov	gPrevDS, ax
        mov ax, ss
		mov	gPrevSS, ax
	};
	
	PrepareGdtDescp (&gGdtDesc[0], 0, 0, 0, 0);                                 // 0x00 -- NullDescriptor 
    PrepareGdtDescp (&gGdtDesc[1],((unsigned long)gPrevCS)<<4, 0xFFFF, 0x9A, 0);   // 0x08 -- CurCodeSegment Descriptor for ProtectedMode 
    PrepareGdtDescp (&gGdtDesc[2],((unsigned long)gPrevDS)<<4, 0xFFFF, 0x92, 0);   // 0x10 -- CurDataSegment Descriptor for ProtectedMode
    PrepareGdtDescp (&gGdtDesc[3],((unsigned long)gPrevSS)<<4, 0xFFFF, 0x92, 0);   // 0x18 -- CurStackSegment Descriptor for ProtectedMode
    PrepareGdtDescp (&gGdtDesc[4], 0xB8000L, 0xFFFF, 0x92, 0);                  // 0x20 -- VideoModeSegment Descriptor is used as scratch pad for Memory Movement
    PrepareGdtDescp (&gGdtDesc[5], 0L, 0xFFFF, 0x92, 0x8F);                     // 0x28 -- Segment Descriptor for 4GB segment

    gGdtRegs.base = ((unsigned long)gPrevDS)<<4;
    gGdtRegs.base += (unsigned int)&gGdtDesc;
    gGdtRegs.limit = sizeof(gGdtDesc)-1;
}

void	setBigRealMode(void)
{
	KeyboardA20(1);
	SetUpGdtTbl();
	UnrealCode();
}


// ASM file
;//-=========================
//MASM6.5
@UnrealCode proc

    pushad
    push ds
    push ds
    mov ax,cs	;code16
    mov ds,ax
    xor eax,eax             ; point gdt_ptr to gdt
    mov ax,ds
    shl eax,4
    add ax,offset gdt         ; EAX=linear address of gdt
    mov dword ptr _gGdtRegs + 2,eax
    cli                     ; Interrupts off
    mov bx,offset _gGdtRegs
	jmp flush1
	    
flush1:
    lgdt fword ptr[bx]
    mov eax,cr0
    or al,1
    mov cr0,eax             ; partial switch to 32-bit pmode
	jmp flush2
	
flush2:
    mov bx,8				; selector to segment w/ 4G limit
    mov ds,bx
    mov es,bx               ; set seg limits in descriptor caches
    dec al
    mov cr0,eax             ; back to (un)real mode
    pop es                  ; segment regs back to old values,
    pop ds                   ; but now 32-bit addresses are OK
    popad
    sti
    ret
@UnrealCode endp


Re: problem in gdt setup for bigrealmode

Posted: Tue Jun 19, 2012 9:32 pm
by bluemoon

Code: Select all

    pop es                  ; segment regs back to old values,
    pop ds                   ; but now 32-bit addresses are OK
Wrong. By setting segment registers in real mode (CR1.PE=0) the base and limit are restored to value*16 and 64K.

Re: problem in gdt setup for bigrealmode

Posted: Wed Jun 20, 2012 12:14 am
by Combuster
Wrong, only the base is restored to value * 16; limit is kept.

You're not restoring ES to its original value however.