unsigned char MEM48[6]; unsigned char GDT[]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //GDT entry 0 (null segment) 0xFF,0xFF,0x00,0x00,0x00,0x92,0xCF,0xFF}; //GDT entry 1 (seg 0, limit 4GB) void INITCPU32(void) { asm mov MEM48[0],16 asm mov eax,seg GDT asm shl eax,4 asm mov bx,offset GDT asm movzx ebx,bx asm add eax,ebx asm mov dword ptr MEM48[2],eax asm lgdt pword ptr MEM48 //Load global descriptor table address asm mov bx,08h //Load bx to point to GDT entry 1 asm push ds asm cli //Disable interrupts asm mov eax,cr0 //Switch to protected mode asm or eax,1 asm mov cr0,eax asm jmp PROTECTION_ENABLED //Clear executionpipe PROTECTION_ENABLED: asm mov gs,bx //Load segment shadow-registers asm mov fs,bx //with GDT entry 1 (4GB segment limit) asm mov es,bx asm mov ds,bx asm and al,0FEh //Switch back to real-mode without asm mov cr0,eax //resetting the CPU asm jmp PROTECTION_DISABLED //Clear executionpipe PROTECTION_DISABLED: asm sti //Enable interrupts asm pop ds } unsigned long XMSDRIVERADDRESS; unsigned int _virtual86(void) { asm mov eax,cr0 asm and ax,1 } #define XMScall(func,d)\ asm mov ah,func;\ asm mov dx,d;\ asm call dword ptr XMSDRIVERADDRESS; unsigned int XMSinit(void) { asm mov ax,0x4300 asm int 0x2F asm cmp al,0x80 asm je XMSOK1 return(1); XMSOK1: asm mov ax,0x4310 asm int 0x2F asm mov ax,es asm shl eax,16 asm mov ax,bx asm mov XMSDRIVERADDRESS[0],bx asm mov XMSDRIVERADDRESS[2],es XMScall(0,0); asm cmp ah,2 asm jae XMSOK2 return(1); XMSOK2: return(0); } unsigned int XMSlocal_enable_A20(void) { XMScall(0x05,0); } unsigned int XMSqueryfree(void) { XMScall(0x08,0); asm mov ax,dx } unsigned int XMSalloc(unsigned int kbytes) { XMScall(0x09,kbytes); asm cmp ax,0x0001 asm je ALLOCOK return(-1); ALLOCOK: asm mov ax,dx } unsigned int XMSfree(unsigned int handle) { XMScall(0x0A,handle); asm cmp ax,0x0001 asm je FREEOK return(1); FREEOK: asm mov ax,bx } unsigned long XMSlock(unsigned int handle) { XMScall(0x0C,handle); asm mov ax,bx } void XMSunlock(unsigned int handle) { XMScall(0x0D,handle); } void main(void) { unsigned int xmshandle; unsigned long xmsaddress; if(_virtual86()) {printf("Machine in virtual 8086 mode, remove QEMM and other such drivers.\n");exit(1);} INITCPU32(); if(XMSinit()) {printf("XMS-driver not found or too old\n");exit(1);} if(XMSqueryfree()<100) {printf("Not enough free XMS-memory\n");exit(1);} XMSlocal_enable_A20(); xmshandle=XMSalloc(100); xmsaddress=XMSlock(xmshandle); printf("Writing 100KB to XMS\n"); asm xor ax,ax asm mov es,ax asm xor edi,edi asm mov ebx,xmsaddress XFILL: asm mov dword ptr es:[ebx+edi],012345678h asm add edi,4 // Write 100000bytes to asm cmp edi,100000 // extended memory asm jb XFILL asm xor edi,edi printf("Checking the written data\n"); XCHK: asm cmp dword ptr es:[ebx+edi],012345678h asm jne READERR // Check, that data is asm add edi,4 // correct asm cmp edi,100000 asm jb XCHK asm jmp NOERRORS READERR: printf("Extended memory use failed\n"); asm jmp ERRORS NOERRORS: printf("Success\n"); ERRORS: XMSunlock(xmshandle); XMSfree(xmshandle); }