home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-05-15 | 21.2 KB | 1,076 lines |
- ;║ A FLAT REAL MODE INITIALIZER EXAMPLE
- ;║ ────────────────────────────────────
- ;║
- ;║ Compliant with RAW, XMS or EMS environments
- ;║
- ;║ Documentation used :
- ;║ microsoft eXtended Memory Specification (XMS) ver 3.0
- ;║ lotus/intel/microsoft Expanded Memory Specification (EMS) ver 4.0
- ;║ microsoft undocumented Global EMM Import Specification (GEMMIS) ver 1.11
- ;║
- ;║ Documentation needed :
- ;║ standard method for detecting drivers which use the VDISK allocation scheme
- ;║ (this is an official publication by microsoft but I don't have it)
- ;║
- ;║ (c) Walken / IMPACT Studios in 1995 - for publication in Imphobia #10
- ;╚════════════════════════════════════════════════════════════════════════════
-
- ;│ Legal stuff :
- ;│ This document can be copyed only when unmodified and in its entirety.
- ;│ Commercial use - including commercial distribution or use in commercial
- ;│ software - is strictly prohibited without the written permission
- ;│ of the author.
- ;│ The author excludes any and all implied warranties, including warranties
- ;│ of merchantability and fitness for a particular purpose. The author
- ;│ should have no liability for special, incidental, or consequential
- ;│ damages arising out or resulting from the use or modification of this
- ;│ source code.
- ;└────────────────────────────────────────────────────────────────────────────
-
- ;║ You can contact the author at the following address :
- ;║ Walken / IMPACT Studios
- ;║ Michel LESPINASSE - 18 rue Jean Giono - 80090 Amiens - FRANCE
- ;╚════════════════════════════════════════════════════════════════════════════
-
- .data
- import_buffer df 1
- device_EMMXXXX0 db 'EMMXXXX0',0 ;EMM device driver name
- EMS_handle_name db '■WaLKeN■'
- nb_XMS_handle dw 0
- nb_available_memory dw 0
- native_V86 db 0 ;system mode 0=real 1=V86
- local_A20 db 0 ;A20 line touched by XMS 0=no 1=yes
- EMS_alloc db 0 ;EMS handle allocated 0=no 1=yes
- no_native db 0 ;running with CPU mode <> system mode 0=no 1=yes
- flat_enabled db 0 ;running in FRM 0=no 1=yes
- NMI_state_touched db 0 ;touched NMI state 0=no 1=yes
- int15_hook db 0 ;hooked int 15 0=no 1=yes
-
- ptr_GDT label fword
- dw 39,o dgroup:GDT,0,0
- GDT dw 4 dup(0) ;NULL selector
- dw 0ffffh,0,9a00h,0 ;_text selector
- dw 0ffffh,0,9200h,0 ;data16 selector
- dw 4 dup(0) ;unused
- dw 0ffffh,0,9200h,8fh ;data32 selector
- _text_selector=8
-
- ptr_IDT_native label fword
- dw 3ffh,0,0,0
- ptr_IDT_flatreal label fword
- dw 3ffh,offset ds:IDT_flatreal,0,0
-
- ext_mem_move dd 1024
- dw 0
- dd buffer_mem_move
- dw ?
- dd ?
-
- msg_GEMMIS db "GEMMIS protocol denyes access to the real mode$"
- msg_no_GEMMIS db "GEMMIS protocol not available$"
- msg_bad_GEMMIS db "GEMMIS data anomaly$"
- msg_EMM4 db "Your EMM is too old, you'll need EMS 4.0 or higher$"
- msg_XMS3 db "Your XMS is too old, you'll need XMS 3.0 or higher$"
- msg_hook db "XMS driver hook does not follow XMS 3.0 standard$"
- msg_a20 db "Cannot enable the A20 gate$"
- msg_XMS_alloc db "XMS memory allocation error$"
- msg_EMS_alloc db "EMS memory allocation error$"
- msg_fragment db "High memory is fragmented in more than 256 blocks$"
- msg_nomem db "Not enough free memory$"
- msg_badmem db "Memory allocation error$"
- msg_verify_pages db "Cannot verify allocated pages$"
- msg_error_pages db "Error in allocated pages$"
- msg_CPU db "You'll need a 386 or better to run this program$"
- msg_V86_no_XMS db "V86 mode with RAW environment is not supported$"
- msg_v86 db "unable to switch to V86 mode for interrupts$"
-
- memory_manager_name db 40 dup(' '),'$'
-
- .data?
- buffer_mem_move db 1024 dup(?)
- available_memory_table dd 257 dup(?,?)
- XMS_handle dw 256 dup(?)
- EMS_handle dw ?
- EMS_size dw ?
- modeswitch dd ?
- himem_driver dd ?
- XMS_hook_base dd ?
- XMS_hook_addr dd ?
- old_int15 dd ?
- exit_msg dw ?
- XMS_hook_jmpval db ?
- NMI_state db ?
-
- .code
- .486p
-
- ;****************************************;
- ;* memory manager init / alloc function *;
- ;****************************************;
-
- mem32_init:
- push cs
- pop ds
-
- ;* test proc >= 386
- mov dx,o msg_CPU
- pushf
- pop ax
- or ah,0f0h
- push ax
- popf
- pushf
- pop ax
- and ah,0f0h
- jnz no_immediate_exit ;long jz instruct not supported on the 286
- jmp immediate_exit
- no_immediate_exit:
-
- ;* test proc >= 486, include it if your proggy does not support 386 processor
- ; pushfd
- ; pop eax
- ; mov ebx,eax
- ; xor eax,40000h
- ; push eax
- ; popfd
- ; pushfd
- ; pop eax
- ; xor eax,ebx
- ; jz immediate_exit ;it's a 386
- ; push ebx
- ; popfd
-
- ;* test V86 mode
- smsw ax
- test al,1
- jz no_V86
- inc native_V86
-
- ;* windows fake init
- mov exit_msg,o msg_GEMMIS
- call open_ouinedoze
-
- ;* test EMS driver
- mov exit_msg,o msg_no_GEMMIS
- mov ax,3d00h
- mov dx,o device_EMMXXXX0
- int 21h ;open handle
- jc exitmsg
- mov bx,ax
- mov ax,4400h
- int 21h ;get device information
- jc exitmsg
- not dx
- test dx,4080h
- jnz exitmsg
- mov ax,4407h
- int 21h ;get output status
- jc exitmsg
- inc al
- jnz exitmsg
- mov ah,3eh
- int 21h ;close handle
-
- ;* test EMS version >= 4.0
- mov ah,46h
- int 67h ;get EMM version
- mov dx,o msg_EMM4
- or ah,ah
- jnz exit
- cmp al,40h
- jb exit
-
- no_V86:
- ;* test XMS driver
- mov ax,4300h
- int 2fh ;XMS install test
- cmp al,80h
- jne no_xms
- mov ax,4310h ;get XMS call adress
- int 2fh
- mov w himem_driver,bx
- mov w himem_driver+2,es
-
- ;* test XMS version >= 3.0
- push bx
- xor ax,ax
- call himem_driver ;get XMS version
- mov dx,o msg_XMS3
- cmp ah,3
- jb exit
- pop bx
-
- ;* XMS hook locate (code from XMS 3.0 specification)
- locate_xms_hook:
- mov dx,o msg_hook
- mov cx,w es:[bx]
- cmp cl,0ebh ;short jump
- je found_xms_hook
- cmp cl,0eah ;far jump
- jne exit
- les bx,d es:[bx+1]
- jmp locate_xms_hook
- found_xms_hook:
- mov eax,d es:[bx+2]
- and eax,0ffffffh
- xor eax,909090h ;3x nop
- jnz exit
- mov al,ch
- mov XMS_hook_jmpval,al
- add al,2
- add ax,bx
- mov w XMS_hook_base,bx
- mov w XMS_hook_base+2,es
- mov w XMS_hook_addr,ax
- mov w XMS_hook_addr+2,es
-
- ;* enable A20 gate (XMS)
- push bx
- mov ah,5
- call himem_driver ;local enable A20
- mov dx,o msg_a20
- dec ax
- jnz exit
- pop bx
- inc local_A20
-
- ;* XMS hook install
- cli
- mov b es:[bx],0eah ;far jump
- mov w es:[bx+1],o cs:XMS_hook
- mov w es:[bx+3],cs
- sti
-
- ;* init check pages buffer
- push cs
- pop es
- mov di,o cs:buffer_mem_move
- mov cx,64
- call fill_check_page
-
- ;* XMS allocate
- xor edi,edi
- XMS_alloc:
- mov exit_msg,o msg_XMS_alloc
- xor bl,bl ;grumbl
- mov ah,8
- call himem_driver ;query free XMS memory
- or ax,ax ;grumbl
- jz XMS_allocated
- or bl,bl ;grumbl
- jnz XMS_allocated
- add ax,64
- mov dx,ax
- XMS_alloc_block:
- push dx
- mov ah,9
- call himem_driver ;allocate XMS block
- dec ax
- jz XMS_block_allocated
- pop dx
- sub dx,64
- jbe XMS_allocated
- jmp XMS_alloc_block
- XMS_block_allocated:
- mov XMS_handle[edi*2],dx
- mov d ext_mem_move[12],0
- mov w ext_mem_move[10],dx
- inc di
- mov nb_XMS_handle,di
- mov ah,0ch
- call himem_driver ;lock XMS block
- dec ax
- jnz exitmsg
-
- ;* write to the XMS block for further check of allocated pages
- mov exit_msg,o msg_verify_pages
- pop cx
- push cx
- push bx
- test_XMS_block:
- mov ah,0bh
- mov si,o ext_mem_move
- call himem_driver ;copy to XMS block
- dec ax
- jnz exitmsg
- add d ext_mem_move[12],1024
- loop test_XMS_block
- pop bx
-
- ;* save adress of the XMS block
- xor eax,eax
- pop ax
- shl eax,10
- shl edx,16
- mov dx,bx
- add eax,edx
- mov available_memory_table[edi*8-8],edx
- mov available_memory_table[edi*8-4],eax
- cmp di,256
- jb XMS_alloc
- XMS_allocated:
- mov nb_available_memory,di
-
- ;* if not native V86 mode skip EMS & GEMMIS
- cmp native_V86,0
- jz flat
-
- ;* EMS allocate & set handle name
- mov exit_msg,o msg_EMS_alloc
- mov ah,42h
- int 67h ;get unallocated page count
- or ah,ah
- jnz exitmsg
- or bx,bx
- jz EMS_allocated
- mov EMS_size,bx
- mov ah,43h
- int 67h ;allocate pages
- or ah,ah
- jnz exitmsg
- inc EMS_alloc
- mov EMS_handle,dx
- mov ax,5301h
- mov si,o ds:EMS_handle_name
- int 67h ;set handle name
- or ah,ah
- jnz exitmsg
-
- ;* write to the EMS block for further check of allocated pages
- mov exit_msg,o msg_verify_pages
- xor ecx,ecx
- mov cx,bx
- mov ah,47h
- int 67h ;save page map
- or ah,ah
- jnz exitmsg
- mov ah,41h
- int 67h ;get page frame address
- or ah,ah
- jnz exitmsg
- mov es,bx
- check_EMS_page:
- mov ax,4400h
- lea bx,[ecx-1]
- int 67h ;map handle page
- or ah,ah
- jnz exitmsg
- xor di,di
- push cx
- mov cx,1024
- call fill_check_page
- pop cx
- loop check_EMS_page
- mov ah,48h
- int 67h ;restore page map
- or ah,ah
- jnz exitmsg
- EMS_allocated:
-
- ;* GEMMIS IOCTL
- mov exit_msg,o ds:msg_no_GEMMIS
- mov ax,3d00h
- mov dx,offset cs:device_EMMXXXX0
- int 21h ;open device
- jc exitmsg ;device does not exist
- mov bx,ax
- mov ax,4402h
- mov cx,6
- mov dx,offset ds:import_buffer
- int 21h ;IOCTL read
- jc exitmsg ;cannot read device
- cmp ax,cx
- jne exitmsg ;cannot read device
- mov ah,3eh
- int 21h ;close device
-
- ;* test GEMMIS version >= 1.0
- cmp b import_buffer+4,1
- jb exitmsg
-
- ;* real mode switch
- mov exit_msg,o ds:msg_GEMMIS
- call switch_to_real
-
- ;* flat mode switch
- call first_enable_flat
-
- ;* GEMMIS data decode : find physical addresses allocated to the EMS block
- mov exit_msg,o msg_bad_GEMMIS
- xor ax,ax
- mov es,ax
- mov esi,d import_buffer
- add esi,397
- movzx ecx,b es:[esi-2]
- shl cx,4
- add esi,ecx ;skip UMB frame descriptors
- push esi ;here es:esi points to first EMS handle info record
- cmp EMS_alloc,0
- jz no_EMS_handle
- xor ecx,ecx
- mov cl,es:[esi-1]
- inc cx ;number of EMS handle info records
- sub esi,16
- find_EMS_handle:
- dec cx
- jz exitmsg
- add esi,16
- cmp d es:[esi+2],'LaW■'
- jne find_EMS_handle
- cmp d es:[esi+6],'■NeK'
- jne find_EMS_handle
- mov cx,es:[esi+10]
- mov esi,es:[esi+12] ;page map for allocated EMS block
- cmp EMS_size,cx
- jne exitmsg
- shl cx,2
- xor edi,edi
- mov di,nb_available_memory
- lods d es:[esi]
- and ax,0f000h
- mov ebx,eax
- jmp contiguous
- find_contiguous:
- lods d es:[esi]
- and ax,0f000h
- cmp eax,edx
- je contiguous
- mov available_memory_table[edi*8],ebx
- mov available_memory_table[edi*8+4],edx
- mov dx,o msg_fragment
- inc di
- cmp di,256
- je exit
- mov ebx,eax
- contiguous:
- lea edx,[eax+1000h]
- loop find_contiguous
- mov available_memory_table[edi*8],ebx
- mov available_memory_table[edi*8+4],edx
- inc di
- mov nb_available_memory,di
- no_EMS_handle:
- pop esi
-
- ;* GEMMIS data decode : save memory manager name if version >= 1.11
- mov ax,w import_buffer[4]
- xchg al,ah
- cmp ax,10ah
- jb dont_save_name
- push ax
- movzx cx,b es:[esi-1] ;number of EMS handle info records to skip
- shl cx,4
- add esi,ecx
- xor cx,cx
- mov cl,b es:[esi+8]
- lea esi,[esi+ecx*8] ;skip free page entryes
- mov cl,b es:[esi+9]
- lea ecx,[ecx*2+ecx]
- lea esi,[esi+ecx*4] ;skip XMS handle info records
- xor cx,cx
- mov cl,b es:[esi+10]
- lea esi,[esi+ecx*4+11] ;skip free UMB info records
- pop ax
- cmp ax,10bh
- ja dont_check_size
- mov edi,d import_buffer
- mov cx,es:[edi+2]
- lea edi,[edi+ecx]
- jb version_110
- sub edi,40
- version_110:
- cmp esi,edi
- jne exitmsg
- cmp ax,10ah
- je dont_save_name
- dont_check_size:
- mov di,o ds:memory_manager_name
- mov cx,10
- copy_name:
- lods d es:[esi]
- mov [di],eax
- add di,4
- loop copy_name
- dont_save_name:
-
- ;* goto init_return
- jmp init_return
-
- no_xms:
- ;* exit if native V86 mode and no XMS manager
- mov dx,o msg_V86_no_XMS
- cmp native_V86,0
- jnz exit
-
- ;* enable A20 gate (RAW) / this code is from TRAN aka Thomas Pytel
- cli
- xor ax,ax ;set A20 test segments 0 and 0ffffh
- mov fs,ax
- dec ax
- mov gs,ax
- call enable_A20_test
- jz enable_A20_done
- in al,92h ;PS/2 A20 enable
- or al,2
- jmp $+2
- jmp $+2
- jmp $+2
- out 92h,al
- call enable_A20_test
- jz enable_A20_done
- call enable_A20_kb_wait ;AT A20 enable
- jnz wait_enable_A20
- mov al,0d1h
- out 64h,al
- call enable_A20_kb_wait
- jnz wait_enable_A20
- mov al,0dfh
- out 60h,al
- call enable_A20_kb_wait
- wait_enable_A20: ;wait for A20 to enable
- mov cx,800h
- loop_wait_enable_A20:
- call enable_A20_test
- jz enable_A20_done
- in al,40h
- jmp $+2
- jmp $+2
- jmp $+2
- in al,40h
- mov ah,al
- A20_wait_tick:
- in al,40h
- jmp $+2
- jmp $+2
- jmp $+2
- in al,40h
- cmp al,ah
- je A20_wait_tick
- loop loop_wait_enable_A20
- mov dx,o msg_a20
- jmp exit
- enable_a20_done:
- sti
-
- ;* get amount of RAW memory / this code is from TRAN aka Thomas Pytel
- mov ah,88h
- int 15h ;get RAW memory size
- or ax,ax
- jz flat
- movzx eax,ax
- shl eax,10
- add eax,100000h
- mov available_memory_table[4],eax
- les bx,dword ptr fs:[4*19h]
- mov eax,100000h
- cmp dword ptr es:[bx+12h],'SIDV'
- jne no_vdisk_1
- mov eax,dword ptr es:[bx+2ch]
- add eax,0fh
- and eax,0fffff0h
- no_vdisk_1:
- cmp dword ptr gs:[13h],'SIDV'
- jne no_vdisk_2
- movzx ebx,w gs:[2eh]
- shl ebx,10
- cmp eax,ebx
- ja no_vdisk_2
- mov eax,ebx
- no_vdisk_2:
- cmp eax,available_memory_table[4]
- jae flat
- mov available_memory_table[0],eax
- inc nb_available_memory
-
- ;* reserve all available RAW memory
- mov eax,fs:[15h*4]
- mov old_int15,eax
- mov w fs:[15h*4+2],cs
- mov w fs:[15h*4+2],o cs:int15_handler
- inc int15_hook
-
- flat:
- ;* flat mode switch
- call first_enable_flat
-
- init_return:
- ;* group contiguous allocated physical memory adresses
- push cs
- pop es
- mov exit_msg,o msg_badmem
- xor ecx,ecx
- sort_available_memory:
- mov dx,o msg_nomem
- mov cx,nb_available_memory
- dec cx
- js exit
- jz available_memory_grouped
- sort_available_memory_pass:
- mov eax,available_memory_table[ecx*8-8]
- cmp eax,available_memory_table[ecx*8]
- jna available_memory_sorted
- xchg eax,available_memory_table[ecx*8]
- mov available_memory_table[ecx*8-8],eax
- mov eax,available_memory_table[ecx*8-4]
- xchg eax,available_memory_table[ecx*8+4]
- mov available_memory_table[ecx*8-4],eax
- jmp sort_available_memory
- available_memory_sorted:
- loop sort_available_memory_pass
- group_available_memory:
- mov cx,nb_available_memory
- dec cx
- jz available_memory_grouped
- group_available_memory_pass:
- mov eax,available_memory_table[ecx*8-4]
- cmp eax,available_memory_table[ecx*8]
- ja exitmsg
- jb available_memory_block_grouped
- lea di,available_memory_table[ecx*8-4]
- lea si,[di+8]
- mov cx,nb_available_memory
- lea cx,available_memory_table[ecx*8]
- sub cx,si
- rep movsb
- dec nb_available_memory
- jmp group_available_memory
- available_memory_block_grouped:
- loop group_available_memory_pass
- available_memory_grouped:
-
- ;* check allocated pages if not RAW
- cmp local_A20,0
- jz dont_check_pages
- xor ax,ax
- mov es,ax
- xor ecx,ecx
- mov cx,nb_available_memory
- mov dx,o msg_error_pages
- check_allocated_pages:
- mov esi,available_memory_table[ecx*8-8]
- mov ebx,available_memory_table[ecx*8-4]
- sub ebx,esi
- shr ebx,4
- check_pages:
- lods d es:[esi]
- cmp eax,'PMI■'
- jne exit
- lods d es:[esi]
- cmp eax,' TCA'
- jne exit
- lods d es:[esi]
- cmp eax,'dutS'
- jne exit
- lods d es:[esi]
- cmp eax,'■soi'
- jne exit
- dec ebx
- jnz check_pages
- loop check_allocated_pages
- dont_check_pages:
-
- ;* install flat real mode interrupt handler
- cmp native_V86,0
- jz no_flatreal_handler
- lidt cs:ptr_IDT_flatreal
- sti
- no_flatreal_handler:
-
- ret
-
- ;*************************************************;
- ;* memory manager switch to native mode function *;
- ;*************************************************;
-
- mem32_native:
- cmp native_V86,0
- jz no_native_switch
- mov exit_msg,o ds:msg_V86
- cli
- lidt cs:ptr_IDT_native
- call disable_flat
- call switch_to_v86
- jc exitmsg
- call close_ouinedoze
- no_native_switch:
- ret
-
- ;****************************************************;
- ;* memory manager switch to flat real mode function *;
- ;****************************************************;
-
- mem32_flatreal:
- cmp native_V86,0
- jz no_flatreal_switch
- mov exit_msg,o ds:msg_V86
- call open_ouinedoze
- call switch_to_real
- call enable_flat
- lidt cs:ptr_IDT_flatreal
- sti
- no_flatreal_switch:
- ret
-
- ;*********************************************;
- ;* memory manager exit / unallocate function *;
- ;*********************************************;
- ; DS:DX = exit message to display
-
- exit:
- mov exit_msg,dx
- exitmsg:
-
- ;* disable flat mode
- cmp flat_enabled,0
- jz flat_disabled
- pushf
- call disable_flat
- popf
- flat_disabled:
-
- ;* native mode switch
- cmp no_native,0
- jz native_exit
- call switch_to_v86
- sti
- native_exit:
-
- ;* restore NMI state
- cmp NMI_state_touched,0
- jz no_NMI_state
- mov al,NMI_state
- out 70h,al ;restore NMI state
- rept 3
- jmp $+2
- endm
- in al,71h
- no_NMI_state:
-
- ;* unallocate RAW
- cmp int15_hook,0
- jz no_int15_hook
- xor ax,ax
- mov es,ax
- mov eax,old_int15
- mov es:[15h*4],eax
- no_int15_hook:
-
- ;* disable A20 gate (RAW) - not done yet (and not really necessary)
-
- ;* EMS unalloc
- cmp EMS_alloc,0
- jz EMS_unallocated
- mov ah,45h
- mov dx,EMS_handle
- int 67h ;unallocate pages
- EMS_unallocated:
-
- ;* XMS unalloc
- xor ecx,ecx
- mov cx,nb_XMS_handle
- jcxz XMS_unallocated
- XMS_unalloc:
- mov ah,0dh
- mov dx,XMS_handle[ecx*2-2]
- call himem_driver ;unlock XMS block
- mov ah,0ah
- call himem_driver ;release XMS block
- loop XMS_unalloc
- XMS_unallocated:
-
- ;* local disable A20 & XMS hook desinstall
- cmp local_A20,0
- jz no_A20_disable
- mov al,0ebh
- mov ah,XMS_hook_jmpval
- les bx,XMS_hook_base
- cli
- mov d es:[bx+1],90909090h
- mov w es:[bx],ax
- sti
- mov ah,6
- call himem_driver ;local disable A20
- no_A20_disable:
-
- ;* windows fake exit
- cmp native_V86,0
- jz no_fake_exit
- call close_ouinedoze
- no_fake_exit:
-
- mov dx,exit_msg
- immediate_exit:
- mov ah,9
- int 21h ;display exit message
-
- mov ax,4c00h
- int 21h ;exit without errorlevel
-
- ;***********************************************;
- ;* memory manager interrupt handling functions *;
- ;***********************************************;
-
- IDT_flatreal equ this word ;flat real mode interrupt table
- irpc hex,<0123456789abcdef>
- irpc unit,<0123456789abcdef>
- dw it&hex&&unit,_text
- endm
- endm
-
- num=0 ;flat real mode interrupt handlers
- irpc hex,<0123456789abcdef>
- irpc unit,<0123456789abcdef>
- it&hex&&unit:
- push eax
- mov al,num
- jmp it
- num=num+1
- endm
- endm
-
- it:
- lidt cs:ptr_IDT_native
- mov cs:automodif_int+1,al
-
- push ebx
- push ecx
- push edx
- push esi
- push edi
- push ebp
- push ds
- push es
- push fs
- push gs
- mov exit_msg,o ds:msg_V86
- call disable_flat
- call switch_to_v86
- jc exitmsg
- call close_ouinedoze
- pop gs
- pop fs
- pop es
- pop ds
- pop ebp
- pop edi
- pop esi
- pop edx
- pop ecx
- pop ebx
- pop eax
- push esp
- movzx esp,sp
- push w ss:[esp+8] ;flags, tricky !
- popf
- automodif_int db 0cdh,0 ;call the old interrupt handler
- pushf
- pop w ss:[esp+8] ;flags, tricky !
- cli
- pop esp
-
- push eax
- push ebx
- push ecx
- push edx
- push esi
- push edi
- push ebp
- push ds
- push es
- push fs
- push gs
- mov exit_msg,o ds:msg_V86
- call open_ouinedoze
- call switch_to_real
- call enable_flat
- pop gs
- pop fs
- pop es
- pop ds
- pop ebp
- pop edi
- pop esi
- pop edx
- pop ecx
- pop ebx
- pop eax
- lidt cs:ptr_IDT_flatreal
- iret
-
- ;*************************************;
- ;* memory manager internal functions *;
- ;*************************************;
-
- first_enable_flat:
- xor eax,eax
- mov ax,cs
- shl eax,4
- add dword ptr ptr_GDT+2,eax
- add dword ptr ptr_IDT_flatreal+2,eax
- mov si,offset cs:GDT
- mov word ptr [si+_text_selector+2],ax
- shr eax,16
- mov byte ptr [si+_text_selector+4],al
- cli
- in al,70h
- rept 3
- jmp $+2
- endm
- mov ah,al
- in al,71h
- rept 3
- jmp $+2
- endm
- mov al,ah
- mov NMI_state,al
- inc NMI_state_touched
- or al,80h
- out 70h,al ;disable NMI
- rept 3
- jmp $+2
- endm
- in al,71h
-
- enable_flat:
- pushf
- cli
- lgdt fword ptr ptr_GDT
- switch_prot _text,@@pmode
- @@pmode:
- mov ax,32
- mov ds,ax
- mov es,ax
- mov fs,ax
- mov gs,ax
- switch_real _text,@@rmode
- @@rmode:
- push cs
- pop ds
- popf
- inc flat_enabled
- ret
-
- disable_flat:
- cli
- switch_prot _text,@@pmode
- @@pmode:
- mov ax,16
- mov ds,ax
- mov es,ax
- mov fs,ax
- mov gs,ax
- switch_real _text,@@rmode
- @@rmode:
- push cs
- pop ds
- dec flat_enabled
- ret
-
- switch_to_real:
- xor ax,ax
- cli
- call modeswitch
- push cs
- pop ds
- jc exitmsg
- inc no_native
- ret
-
- switch_to_v86:
- mov ax,1
- cli
- call cs:modeswitch
- push cs
- pop ds
- mov no_native,0
- ret
-
- open_ouinedoze:
- mov ax,1605h
- xor bx,bx
- mov cx,bx
- mov dx,bx
- mov si,bx
- mov di,30bh ;version number 3.11
- mov ds,bx
- mov es,bx
- int 2fh ;set device name to "EMMXXXX0" & return entry point addr
- push ds
- push cs
- pop ds
- pop ax
- or cx,cx
- jnz exitmsg ;cannot run windows
- mov w modeswitch+2,ax
- mov w modeswitch,si
- or ax,si
- jz exitmsg ;modeswitch not available
- ret
-
- close_ouinedoze:
- mov ax,1606h
- xor dx,dx
- int 2fh ;restore device name
- ret
-
- fill_check_page:
- mov eax,'PMI■'
- stosd
- mov eax,' TCA'
- stosd
- mov eax,'dutS'
- stosd
- mov eax,'■soi'
- stosd
- loop fill_check_page
- ret
-
- XMS_hook:
- jmp $+5
- nop
- nop
- nop
- cmp al,3
- jb @@XMS_okay
- cmp al,6
- ja @@XMS_okay
- mov ax,1
- retf ;disable A20 control functions
- @@XMS_okay:
- jmp cs:XMS_hook_addr
-
- int15_handler:
- cmp ah,88h
- je reserve_high_memory
- jmp old_int15
- reserve_high_memory:
- xor ax,ax
- iret
-
- enable_A20_kb_wait: ;wait for safe to write to 8042
- xor cx,cx
- loop_enable_A20:
- jmp $+2
- jmp $+2
- jmp $+2
- in al,64h
- test al,2
- loopnz loop_enable_A20
- ret
-
- enable_A20_test: ;test for enabled A20
- mov al,fs:[0]
- mov ah,al
- not al
- xchg al,gs:[10h]
- cmp ah,fs:[0]
- mov gs:[10h],al
- ret
-
- ;* init
- ; switch natif
- ; message
- ; [switch frm]
- ; deinit / release
- ;* retour