(2831)  Mon 14 Feb 94 12:46p
By: Elad Nachman
To: Maynard Philbrook
Re: PROTECT INSTRUTIONS
St:                                                                       <1848
---------------------------------------------------------------------------
@MSGID: 2:403/169.4 2d5f72fc
@REPLY: 1:320/42 52f6b466
@PID: GED G1218
Hello Maynard!

 On the Tuesday February 08 1994 22:49, Maynard Philbrook Headbanged on my
metal fuses and wrote to Craig Jackson:

 MP> EMM386 interface.. But if i Disble EMM386 i can do any of thing
 MP> with out a problem. I have most of the data on the EMM386 and it
 MP> explains some what about the few functions in the VCPI, it
 MP> mentions getting the machine state and getting a LDT but my Docs
 MP> do not explain how to do it.

You can go to a raw-like CPL0 protected mode via VCPI using int 67/ax=de01
and then int 67/ax=de0c (You must set the LDT,GDT,IDT,TSS,Page frame and so
on).
Here's a one (Took me fairly long to do, but it works!):


.radix 16
.386P
code segment USE16
assume cs:code,ds:code,es:code,ss:code
org 100h

begin:
jmp start

desc struc
Limit dw ? ; Segment Limit, 286/386
Base1 dw ?
base2 db ? ; 24 linear Pointer to start of segment
rights db ? ; Access Rights
dat386 db ? ; limit+other flags
base3 db ? ; 386 Addition
ENDS

TSS equ $
previous_tss dd 0 ; only low-word is used
_esp0 dd 0 ; Esp for ring 0
_ss0 dd 028h ; SS for ring 0, only low word used
_esp1 dd 0 ; same for ring 1
_ss1 dd 028h ;   "    "    "  1
_esp2 dd 0 ;  same for ring 2
_ss2 dd 028h ; same for ring 2
_cr3_ dd 0
_eip dd 0
_eflags dd 0
_eax dd 0
_ecx dd 0
_edx dd 0
_ebx dd 0
_esp dd 0 ; Current - After Task Switch
_Ebp dd 0
_esi dd 0
_edi dd 0
_es dd 20h
_cs dd 30h ; Set after task switch
_ss dd 28h ; current
_ds dd 28h
_fs dd 28h
_gs dd 28h
_LDTR_ dd 0 ; All selectors from _es to _ldtr_ are counted only for low word
IO_bitmap dd 00680000h ; I/O premission bitmap - if 0, not I/O allowed
bitmap db 100h dup (0) ; I/O bitmap - most required I/Os allowed

pdata equ $
_cr3 dd 0 ; Value for CR3 register - address of PDT
_GDTR dd 0 ; Pointer to GDTR register
_IDTR dd 0 ; Pointer to IDTR register
_LDTR dw 0 ; Selector for LDT
_TSS dw 40h ; Selector for TSS
entry df 003000000000h ; FWORD cs:EIP

msg1 db "No Memory Manager Present",'$'
msg2 db "Not in V86 mode!",'$'
msg3 db "No VCPI installed!",'$'


ServerPtr df 000800000000h

pt_seg dw 0  ; Segment for page table
pdt_seg dw 0 ; Segment for Page Directory Table
real_seg dw 0

IDTR equ $
IDTR1 dw 0ffh*8
IDTR2 dd ?
IDT dq 0ffh dup (0)

GDTR equ $
GDTR1 dw 080h  ; GDT limit (16 descriptors)
GDTR2 dd ?  ; Linear 32 bit pointer to GDT
nope dw 0 ; For compatibility ??!?!?!?
GDT equ $
data_nul dq 4 dup (0) ; null descriptor
data2 desc <0ffffh,8000h,0bh,10010010b,11001111b,0> ; 4GB video segment - 20h
data3 desc <0ffffh,0,0,10010010b,0,0> ; Real Mode style 64KB data segment
data4 desc <0ffffh,0,0,10011010b,0,0> ; Real Mode Style 64kb Code Segment - 30h
data5 desc <0ffffh,0,0,10010010b,11001111b,0> ; 4GB Data Segment - 38h
tss_sel desc <0160h,0,0,10001001b,0,0> ; Selector for Task Segmet = 40h
data_ dq 6 dup (0) ; More descriptors

stck db 200h dup (0) ; stack

start:
push ds
xor ax,ax
mov ds,ax
mov eax,ds:[67h*4]
pop ds
or eax,eax
jne EMM
mov ah,9h
mov dx,offset msg1
int 21h
mov ah,4ch
int 21h
emm:
smsw ax
test ax,1
jne v86
mov ah,09h
mov dx,offset msg2
int 21h
mov ah,4ch
int 21h
v86:
mov ax,0de00h
int 67h
or ah,ah
je VCPI
mov ah,9
mov dx,offset msg3
int 21h
mov ah,4ch
int 21h
VCPI:
push cs
pop ds
push cs
pop es
cli
mov sp,offset stck+100h
sti
mov bx,offset dummy
mov cl,4
shr bx,cl ; Bytes -> paragraphs
inc bx
add bx,300h ; Makes sure we can align both page table and page table
mov ah,4ah  ; Directory on a 4Kb boundary ( 12 lower bits of page entries/
int 21h     ; Cr3 are not counted in the address )

mov ax,cs
mov bx,offset dummy
mov cl,4
shr bx,cl ; Offset -> segment
add bx,ax ; add segment
and bx,0ff00h
add bx,100h ; Align on Page boundary
mov [pdt_seg],bx ; Got it
mov es,bx
add bx,100h ; Align on next page - that's the Page Table
mov [pt_seg],bx
movzx ebx,bx
mov cl,4
shl ebx,4 ; Segment->Linear
or ebx,1 ; Set Present Bit
mov dword ptr Es:[0000],ebx ; Store the needed PDT entry
mov bx,[pt_seg]
mov es,bx
xor di,di ; Aligned on page boundary, remember?
mov si,offset GDT+8
mov ax,0de01h
int 67h
push cs
pop ds
mov dword ptr ds:[serverptr],ebx

mov ax,cs
movzx eax,ax
mov cl,04h
shl eax,cl ; Segment -> linear
mov ebx,eax
mov cx,offset GDT
movzx ecx,cx
add eax,ecx
mov [GDTR2],eax ; Store linear GDT address
sub eax,ecx
mov cx,offset IDT
movzx ecx,cx
add eax,ecx
mov [IDTR2],eax
sub eax,ecx
xor ecx,ecx
mov cx,offset GDTR
add eax,ecx
mov [_GDTR],eax
sub eax,ecx
mov cx,offset IDTR
movzx ecx,cx
add eax,ecx
mov [_IDTR],eax
sub eax,ecx

mov si,offset data3.base1
mov ecx,02h
set_base:
mov eax,[si]
or eax,ebx
mov [si],eax
add si,08h
loop set_base ; Set base addresses for data/code descriptors
add si,08h
mov eax,[si]
mov cx,offset TSS
movzx ecx,cx
or eax,ebx
add eax,ecx
mov [si],eax     ; same for TSS

mov ax,offset start_pmode
movzx eax,ax
mov dword ptr [entry],eax

mov dx,[pdt_seg]
mov cl,4
movzx edx,dx
shl edx,4 ; Segment->linear

mov [_cr3],edx
mov [_cr3_],edx ; Set cr3 both in data for VCPI and in TSS

mov ax,offset start_pmode
movzx eax,ax
mov [_eip],eax

mov ax,offset stck+50h
movzx eax,ax
mov [_esp],eax
mov [_esp0],eax
mov [_esp1],eax
mov [_esp2],eax

mov ax,cs
mov [real_seg],ax

mov ax,offset pdata
movzx eax,ax
add eax,ebx
mov esi,eax
mov ax,0de0ch
cli
int 67 ; Bye bye V86 mode... Will we succeed?
nop
nop

start_pmode: ; Here we go (Or not!)
cli
mov ax,20h
mov es,ax
mov edi,0000h ; Video Screen - What else ?
mov ecx,100h ; That'll be enough
mov eax,08c418c41h ; 2 Flashing A's
cld
rep stosd
mov ax,28h
mov ds,ax
mov ss,ax
mov ax,offset stck+100h
movzx esp,ax
mov ax,0de03h
call fword ptr cs:[serverptr]
xor di,di
xor eax,eax
mov ecx,90h
cld
rep stosd
mov ax,cs:[real_seg]
movzx eax,ax
push eax
push eax
push eax
push eax
push eax ; GS,FS,DS,ES,SS register's values (real mode?)
mov ax,offset stck+100h
movzx eax,ax
push eax ; ESP
pushfd
mov ax,cs:[real_seg]
movzx eax,ax
push eax ; Code Segment Selector
mov ax,offset return_v86
movzx eax,ax
push eax ; Offset for return
mov ax,38h
mov ds,ax
mov eax,8c418c41h
mov ds:[0b8000h],eax ; Tests if 4gb segment ok
mov ax,0de0ch
call fword ptr cs:[serverptr]


return_v86:
sti
mov ax,4c00h
int 21h

dummy:
code ends
end begin

Fare thee well,

Elad

---
 * Origin: None is Listed! (2:403/169.4)

@PATH: 403/169 150 170/400 209/209 270/101 260/1 362
