add directory study
This commit is contained in:
155
study/sabre/os/files/ProtectedMode/SIMPL_PM.asm
Normal file
155
study/sabre/os/files/ProtectedMode/SIMPL_PM.asm
Normal file
@@ -0,0 +1,155 @@
|
||||
;----
|
||||
; Example program switching to Protected and back to Real Mode
|
||||
; Jerzy Tarasiuk 8-Jun-1995
|
||||
;
|
||||
code segment
|
||||
assume cs:code
|
||||
stk segment para stack 'stack'
|
||||
dw 100h dup(?)
|
||||
stk ends
|
||||
assume cs:code,ss:stk,ds:Nothing,es:Nothing
|
||||
.386P
|
||||
|
||||
;-
|
||||
; GDT to be used in Protected Mode
|
||||
;
|
||||
mygdt dq 0 ; null descriptor
|
||||
gdtcd dw -1,0,9A00h,0 ; 64kB code segment, base to be set
|
||||
dw -1,0,9200h,008Fh ; 4GB R/W segment, base=0
|
||||
dw -1,0,9200h,0 ; 64kB R/W segment, base=0
|
||||
|
||||
;---
|
||||
; pm_mem - access memory (peek/poke a byte) in Protected Mode
|
||||
;
|
||||
; entry EBX=address, CX=0 for peek to CL or CX!=0 for poke CL
|
||||
; changes EAX,EDX,GDTR,CL
|
||||
;
|
||||
; requires A20 to be enabled if to be used on a PC compatible
|
||||
; (A20 is usually enabled if DOS is loaded into HMA)
|
||||
;
|
||||
pm_mem proc
|
||||
pushf
|
||||
push ds
|
||||
mov ax,cs
|
||||
movzx eax,ax
|
||||
shl eax,4 ; eax=base for code segment
|
||||
mov dword ptr gdtcd[2],eax
|
||||
mov byte ptr gdtcd[5],9Ah ; set segment attribute
|
||||
mov dx,offset mygdt
|
||||
movzx edx,dx
|
||||
add eax,edx ; eax=base for GDT
|
||||
push eax
|
||||
push 20h
|
||||
movzx eax,sp
|
||||
cli ; make sure no ISR will interfere now
|
||||
lgdt fword ptr ss:[eax] ; LGDT is necessary before switch to PM
|
||||
add sp,6
|
||||
mov eax,cr0
|
||||
or al,1
|
||||
mov cr0,eax ; sets Protected Mode
|
||||
db 0eah ; far jump to set CS & clear prefetch queue
|
||||
dw pm_in
|
||||
dw 8
|
||||
|
||||
pm_in: mov dx,10h
|
||||
mov ds,dx ; load long segment descriptor from GDT into DS
|
||||
jcxz pm_get
|
||||
mov [ebx],cl
|
||||
pm_get: mov cl,[ebx]
|
||||
mov dl,18h
|
||||
mov ds,dx ; load 64kB segment descriptor from GDT into DS
|
||||
and al,not 1
|
||||
mov cr0,eax ; sets Real Mode
|
||||
db 0eah ; far jump to restore CS & clear prefetch queue
|
||||
dd pm_out ; it MUST be jump - far return crashed!
|
||||
pm_out: pop ds
|
||||
popf
|
||||
ret
|
||||
pm_mem endp
|
||||
|
||||
;---
|
||||
; vfycpu - make sure have proper CPU, in Real Mode, and A20 enabled
|
||||
;
|
||||
; changes AX,DX
|
||||
; returns AL=error code if anything wrong
|
||||
; error codes: 040h - not 32-bit CPU (PM,A20 not tested)
|
||||
; 001h - already in PM (386+, A20 not tested)
|
||||
; 0FFh - A20 disabled (32-bit CPU in RM)
|
||||
;
|
||||
vfycpu proc
|
||||
pushf ; save flags
|
||||
cli ; make sure no ISR will interfere now
|
||||
;
|
||||
pushf ; 1. make sure have at least 386
|
||||
pop ax ; AX=flags
|
||||
xor ah,40h ; toggle NT
|
||||
push ax ; stack: modified_flags,original_flags
|
||||
popf
|
||||
pushf ; stack: modified_flags_from_cpu,original_flags
|
||||
pop dx ; DX=flags passed via CPU
|
||||
mov al,dh
|
||||
xor al,ah
|
||||
jnz vcfail ; improper CPU
|
||||
;
|
||||
smsw ax ; 2. make sure are in Real Mode
|
||||
and al,1
|
||||
jnz vcfail ; if already in PM (maybe VM86)
|
||||
;
|
||||
push ds ; 3. make sure A20 is enabled
|
||||
push es
|
||||
push bx
|
||||
xor bx,bx
|
||||
mov ds,bx
|
||||
mov ax,-1
|
||||
mov es,ax
|
||||
xor [bx],ah ; change byte[000000h]
|
||||
mov al,es:[bx+10h] ; get byte[100000h]
|
||||
xor [bx],ah ; change byte[000000h]
|
||||
xor al,es:[bx+10h] ; compare byte[100000h] with its previous value
|
||||
; 0 if unchanged, -1 means [000000h]==[100000h]
|
||||
pop bx
|
||||
pop es
|
||||
pop ds
|
||||
;
|
||||
vcfail: popf ; restore flags
|
||||
test al,al ; test error code
|
||||
ret
|
||||
vfycpu endp
|
||||
|
||||
;---
|
||||
; sample program
|
||||
; - check if have proper CPU, exit with error message if bad
|
||||
; - peek byte[0FFFFFFF0h] in PM
|
||||
; - peek byte[0FFFEFFF0h] in PM
|
||||
; - exit (status = byte obtatained)
|
||||
;
|
||||
badcpum db "Not 80386+ CPU!",0Dh,0Ah,'$'
|
||||
inpmerm db "Already in Protected Mode!",0Dh,0Ah,'$'
|
||||
bada20m db "Address line A20 disabled!",0Dh,0Ah,'$'
|
||||
|
||||
start: call vfycpu ; make sure having proper CPU and mode
|
||||
add al,al
|
||||
jz cpuok ; .. OK
|
||||
lea dx,bada20m
|
||||
jc error
|
||||
lea dx,badcpum
|
||||
js error
|
||||
lea dx,inpmerm
|
||||
error: push cs ; not proper - error message and exit
|
||||
pop ds
|
||||
mov ah,9
|
||||
int 21h
|
||||
mov ax,4cffh ; exit, status=-1
|
||||
int 21h
|
||||
|
||||
cpuok: xor cx,cx ; peek a byte
|
||||
mov ebx,-10h ; from 0FFFFFFF0h
|
||||
call pm_mem
|
||||
xor cx,cx ; peek a byte
|
||||
mov ebx,-10010h ; from 0FFFEFFF0h
|
||||
call pm_mem
|
||||
exit: mov ah,4ch ; exit
|
||||
mov al,cl ; status = the byte
|
||||
int 21h
|
||||
code ends
|
||||
end start
|
||||
Reference in New Issue
Block a user