home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
cpu
/
protex
/
prot5.asm
< prev
next >
Wrap
Assembly Source File
|
1991-03-14
|
11KB
|
291 lines
PAGE ,132
TITLE Method 2
.286p ; Tell MASM 2.0 about 286 instructions
;--------------------------------------------------------------:
; Sample Program 2 :
; :
; This program switches into Protected Virtual Mode, changes :
; the display attribute to reverse video, and returns to Real :
; Mode to exit to DOS :
; :
; Once entered into a file, do the following: :
; MASM SAMPLE2; :
; LINK SAMPLE2; :
; EXE2BIN SAMPLE2 SAMPLE2.COM :
; DEL SAMPLE2.EXE :
; :
; WARNING: This program will "kill" a PC. It should only :
; be run on an AT. :
;--------------------------------------------------------------:
bios_data_seg SEGMENT at 0040h
ORG 0067h
io_rom_init dw ? ; dword variable in BIOS data segment
io_rom_seg dw ? ; used to store a dword address
bios_data_seg ENDS
descriptor STRUC
seg_limit dw 0 ; segment limit (1-65536 bytes)
base_lo_word dw 0 ; 24 bit physical address
base_hi_byte db 0 ; (0 - (16M-1))
access_rights db 0 ; access rights byte
dw 0 ; reserved_386
descriptor ENDS
cmos_port equ 070h
code_seg_access equ 10011011b ;access rights byte for code seg
data_seg_access equ 10010011b ;access rights byte for data seg
enable_bit20 equ 11011111b ;8042 function code to gate A20
port_a equ 060h ;8042 port A
shut_cmd equ 0FEh ;cmd to 8042: shut down AT
shut_down equ 00Fh ;CMOS shut down byte index
status_port equ 064h ;8042 status port
virtual_enable equ 0001h ;LSB=1: Protected Virtual Mode
jumpfar MACRO jumpfar1,jumpfar2
db 0EAh
dw (offset jumpfar1)
dw jumpfar2
ENDM
SUBTTL Program entry point and data area
PAGE
cseg SEGMENT para public 'code'
ASSUME cs:cseg
ORG 100h
start: jmp short main
EVEN
gdt LABEL word
gdt_desc EQU (($-gdt)/8)*8 + 0000000000000000b
gdt1 descriptor <gdt_leng,,,data_seg_access,>
cs_code EQU (($-gdt)/8)*8 + 0000000000000000b
gdt2 descriptor <cseg_leng,,,code_seg_access,>
cs_data EQU (($-gdt)/8)*8 + 0000000000000000b
gdt3 descriptor <cseg_leng,,,data_seg_access,>
ss_desc EQU (($-gdt)/8)*8 + 0000000000000000b
gdt4 descriptor <0FFFFh,,,data_seg_access,>
ds_desc equ (($-gdt)/8)*8 + 0000000000000000b
gdt5 descriptor <0FFFFh,,,data_seg_access,>
es_desc equ (($-gdt)/8)*8 + 0000000000000000b
gdt6 descriptor <0FFFFh,,,data_seg_access,>
gdt_leng EQU $-gdt
PAGE
;--------------------------------------------------------------:
; Format of the Segment Selector Component: :
; :
; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ :
; | INDEX +TI+ RPL + : :
; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ :
; :
; TI = Table Indicator (0=GDT, 1=LDT) :
; RPL = Requested Privelege Level (00 = highest; 11 = Lowest) :
;--------------------------------------------------------------:
; Format of the Global Descriptor Table :
; .-----------+ +---> TI :
; V | |++-> RPL :
; GDT ==> +---------------+ | ||| :
; | GDT_DESC | --+ 0000000000000000b :
; +---------------+ :
; | CS_CODE | 0000000000001000b :
; +---------------+ :
; | CS_DATA | 0000000000010000b :
; +---------------+ :
; | SS_DESC | 0000000000011000b :
; +---------------+ :
; | DS_DESC | 0000000000100000b :
; +---------------+ :
; | ES_DESC | 0000000000101000b :
; +---------------+ :
;--------------------------------------------------------------:
SUBTTL Program Main
PAGE
;--------------------------------------------------------------:
; MAIN :
;--------------------------------------------------------------:
ASSUME ds:cseg
main PROC ;ES=DS=CS
cld ;forward
mov dx,cs ;form 24bit address out of
mov cx,offset gdt ;CS:GDT
call form_24bit_address
mov gdt1.base_lo_word,dx ;DESC now points to gdt
mov gdt1.base_hi_byte,cl
mov dx,cs ;form 24bit address out of
xor cx,cx ; CS:0000
call form_24bit_address
mov gdt2.base_lo_word,dx ;CS_CODE now points to
mov gdt2.base_hi_byte,cl ; CSEG as a code segment
mov gdt3.base_lo_word,dx ;CS_DATA now points to
mov gdt3.base_hi_byte,cl ; CSEG as a data segment
mov dx,ss ;form 24bit address out of
xor cx,cx ;SS:0000
call form_24bit_address
mov gdt4.base_lo_word,dx ;SS_DESC now points to
; stack segment
mov gdt4.base_hi_byte,cl
lgdt gdt ;Load the GDTR
mov ah,enable_bit20 ;gate address bit 20 on
call gate_a20
or al,al ;was the command accepted?
jz m_10 ;go if yes
mov dx,offset gate_failure ;print error msg
mov ah,9 ; and terminate
int 21h
int 20h
gate_failure db "Address line A20 failed to Gate open$"
m_10: cli ;No interrupts
pushf ;Simulate INT by pushing Flags,
push cs ; CS,
mov ax,offset real ; and offset of return address.
push ax
pusha ;Now, set up stack the way BIOS block-
push es ; move logic will expect it.
push ds ;On return, this is the way
; the regs will be.
ASSUME ds:bios_data_seg
mov dx,bios_data_seg ;Place on Stack current SS:SP
mov ds,dx
mov io_rom_seg,ss
mov io_rom_init,sp
mov al,shut_down ;Set shutdown byte to
out cmos_port,al ; shut down code x"09"
jmp short $+2 ;I/O delay
mov al,9
out cmos_port+1,al
mov ax,virtual_enable ;machine status word needed
lmsw ax ; to switch to virtual mode
jumpfar m_20,cs_code ;Must purge prefetch queue
m_20: ASSUME ds:cseg ;IN VIRTUAL MODE ...
mov ax,ss_desc ;stack segment selector
mov ss,ax ;user's ss+sp
; is not a descriptor
mov ax,cs_data
mov ds,ax ;DS = CSEG as data
mov gdt5.base_lo_word,8000h ;use 8000 for COLOR
mov gdt5.base_hi_byte,0Bh
mov gdt6.base_lo_word,8000h
mov gdt6.base_hi_byte,0Bh
mov ax,ds_desc
mov ds,ax
mov ax,es_desc
mov es,ax
mov cx,80*25
xor si,si
xor di,di
m_30: lodsw
mov ah,80h ;attribute reverse video
stosw
loop m_30
mov al,shut_cmd ;shutdown cmd
out status_port,al ;get back into REAL mode
m_40: hlt
jmp short m_40
SUBTTL Gate A20
PAGE
;--------------------------------------------------------------:
; GATE_A20 :
; This routine controls a signal which gates address bit 20. :
; The gate A20 signal is an output of the 8042 slave processor.:
; Address bit 20 should be gated on before entering protected :
; mode. It should be gated off after entering real mode from :
; protected mode. :
; Input: (AH)=0DDh addr bit 20 gated off (A20 always 0) :
; (AH)=0DFh addr bit 20 gated on (286 controls A20) :
; Output: (AL)=0 operation successful. 8042 has accepted cmd :
; (AL)=2 Failure -- 8042 unable to accept command. :
;--------------------------------------------------------------:
gate_a20 PROC
cli ;disable ints while using 8042
call empty_8042 ;insure 8042 input buffer empty
jnz gate_a20_01 ;ret if 8042 unable to accept cmd
mov al,0D1h ;8042 command to write output port
out status_port,al ;output cmd to 8042
call empty_8042 ;wait for 8042 to accept command
jnz gate_a20_01 ;ret if 8042 unable to accept cmd
mov al,ah ;8042 port data
out port_a,al ;output port data to 8042
call empty_8042 ;wait for 8042 to port data
gate_a20_01:
ret
gate_a20 ENDP
;--------------------------------------------------------------:
; EMPTY_8042 :
; This routine waits for the 8042 buffer to empty :
; Input: None :
; Output: (AL)=0 8042 input buffer empty (ZF=1) :
; (AL)=2 Time out, 8042 buffer full (ZF=0) :
;--------------------------------------------------------------:
empty_8042 PROC
push cx ;save CX
sub cx,cx ;CX=0 will be time out value
empty_8042_01:
in al,status_port ;read 8042 status port
and al,00000010b ;test inp. buffer full flag (D1)
loopnz empty_8042_01 ;loop until input buffer empty
; or time out
pop cx ;restore CX
ret
empty_8042 ENDP
SUBTTL form_24bit_address
PAGE
;--------------------------------------------------------------:
; FORM_24BIT_ADDRESS :
; Input: DX has some segment :
; CX has some offset :
; Output: DX has base_lo_word :
; CL has base_hi_byte :
;--------------------------------------------------------------:
form_24bit_address PROC
push ax
;DX == s15 s14 s13 s12 s11 ... s04 s03 s02 s01 s00
rol dx,4
;DX == s11 ... s04 s03 s02 s01 s00 s15 s14 s13 s12
mov ax,dx
;AX == s11 ... s04 s03 s02 s01 s00 s15 s14 s13 s12
and dl,0F0h
;DX == s11 ... s04 s03 s02 s01 s00 0 0 0 0
and ax,0Fh
;AX == 0 ... 0 0 0 0 0 s15 s14 s13 s12
add dx,cx ;form_24bit_address
mov cx,ax ;get base_hi_byte in CL
adc cl,ch ;carry in (CH=0)
pop ax
ret
form_24bit_address ENDP
SUBTTL Real Mode re-entry point.
PAGE
ASSUME ds:cseg ; IN REAL MODE ...
real: sti ; turn the int's on
int 20h ; back to DOS
main ENDP
cseg_leng EQU $
cseg ENDS
END start