rendered paste bodyComment |
Oprogramowanie Systemowege
Program przykladowy do testowania trybu chronionego procesora 80386 i wyzszych
wersja 2.0 - marzec 2000
|
.386p
MIN_SECT EQU 1
MIN_TRACK EQU 0
MIN_HEAD EQU 0
MAX_SECT EQU 18
MAX_TRACK EQU 79
MAX_HEAD EQU 1
WLK_BUFORA EQU 512
CR EQU 0DH
LF EQU 0AH
; rejestry kontrolera stacji dyskietek
MSR EQU 03F4H ;glowny rejestr statusowy sterownika
DOR EQU 03F2H ;rejestr wyjsciowy
CDR EQU 03F5H ;rejestr rozkazow/danych sterownika
DTR EQU 03F7H ;rejestr szybkosci transmisji
DIR EQU 03F7H ;drugi rejestr statusowy
;-------------------------------------------------------------------------
; globalna tablica deskryptor˘w
segment_GDT SEGMENT use16
dq 0 ; poz. 0 - deskryptor zerowy (nieuzywany)
dq 0 ; poz. 1 - selektor 0008H
dq 0 ; poz. 2 - selektor 0010H - segment 'nowe_dane'
dq 0 ; poz. 3 - selektor 0018H
dq 0 ; poz. 4 - selektor 0020H
dq 0 ; poz. 5 - selektor 0028H
dq 0 ; poz. 6 - selektor 0030H
dq 0 ; poz. 7 - selektor 0038H
dq 0 ; poz. 8 - selektor 0040H
dq 0 ; poz. 9 - selektor 0048H
dq 0 ; poz.10 - selektor 0050H
segment_GDT_end LABEL byte
segment_GDT ENDS
;-------------------------------------------------------------------
; tablica deskryptorow przerwan
segment_IDT SEGMENT use16
; Tablica zawiera furtki prowadz?ce do procedur obs?ugi przerwa¤
; i wyj?tk˘w o numerach 0 - 127. Pola 'offset' w kolejnych furtkach
; zawierac beda liczby 0, 7, 14, 21, itd.
xpom=0
REPT 128
dw xpom ; offset
dw 6 SHL 3 ; selektor
db 0 ; licznik
db 10000110B ; bajt dost?pu
dw 0 ; rezerwa
xpom=xpom+7
ENDM
segment_IDT_end LABEL byte
segment_IDT ENDS
;-------------------------------------------------------------------------
; segment danych dla trybu chronionego - segment ten wskazywany jest przez
; selektor 2 * 8 = 0010H
nowe_dane SEGMENT use16
;zmienne okreslajace polozenie na dyskietce
nr_sect db MIN_SECT
nr_track db MIN_TRACK
nr_head db MIN_HEAD
;bufor na odczytany sektor
bufor_dysk db 512 dup ('#')
;zmienne statusu
floppy_int db 0 ;flaga informujaca, czy bylo przerwanie ze
; stacji dyskietek
oczekiwanie db 0 ;zmienna zawierajaca ilosc wywolan przerwania
;zegara pozostalych do zakonczenia czekania
kom4 db 'Procesor pracuje w trybie chronionym (protected mode)'
db ' - Esc - wyjscie', 0
kom5 db 'Nierozpoznane polecenie', 0
kom_dysk_blad db 'Blad w odczycie danych z dysku',0
kom_dysk_ok db 'Wszystko OK! :)',0
kom_info db '--------------------------------------------------------------------------------'
db '| ENTER - wczytanie sektora | W - sciezka+1 |'
db '| ESC - wyjscia z progr. | S - sciezka-1 |'
db '| | |'
db '| Q - sektor+1 | E - przelacz strone |'
db '| A - sektor-1 | |'
db '| | |'
db ' -------------------------------------------------------------------------------'
db ' SEKTOR: SCIEZKA: STRONA: ',0
txt_czas db 'czas',13,0
txt_polecenie db 'dysk',13,0
bufor_klaw db 128 dup (?) ; bufor klawiatury
indeks_klaw dw ?
ekran_x db 0 ; wskaznik nr kolumny do zapisu na ekranie
ekran_y db 0 ; wskaznik nr wiersza do zapisu na ekranie
bufor db 50 dup (?)
kom10 db 'otrzymalem przerwanie', 0
; tablica do przekodowania kodow pozycji na kody ASCII
tabl_przekA db 0, 1BH, '1234567890-=',08H, 09H ; kody 0 - 15
db 'qwertyuiop[]', 0DH, 0, 'as' ; kody 16 - 31
db 'dfghjkl;''`',0,'\zxcv' ; kody 32 - 47
db 'bnm,./',0,'*',0,' ',0 ; kody 48 - ...
nowe_dane_end LABEL byte
nowe_dane ENDS
;-------------------------------------------------------------------------
nowy_stos SEGMENT use16 ; stos dla trybu chronionego
pstos dw 2048 dup (?)
nowy_stos_end LABEL byte
nowy_stos ENDS
;---------------------------------------------------------------------------
stos_RM SEGMENT use16 stack ; stos dla trybu rzeczywistego
dw 256 dup (?)
stos_RM ENDS
;---------------------------------------------------------------------------
ekran SEGMENT use16 at 0B800H ; segment imituj?cy pami?? ekranu
db 4000 dup (?)
ekran_end LABEL byte
ekran ENDS
;---------------------------------------------------------------------------
rozkazy SEGMENT use16 ; rozkazy programu
; obszary 48-bitowe potrzebne do ladowania rejestr˘w GDTR oraz IDTR
zaw_GDTR dp 0
zaw_IDTR dp 0
rm_idt LABEL qword ; wskaznik do tabl. wekt. przerwan (tryb rzecz.)
dw 03FFH ; wielko?? tablicy IDT
dd 0
komunikat1 db CR, LF, 'Laboratorium Oprogramowania Systemowego', CR,LF
db 'Program przykladowy do cwiczenia 8 - '
db 'wersja 2.0 - marzec 2000', CR, LF, LF
db 'Aktualnie procesor pracuje w trybie rzeczywistym', CR, LF
db 'Nacisniecie dowolnego klawisza powoduje przejscie do '
db 'trybu chronionego', CR, LF
db 'Esc - wyjscie z programu',CR, LF, '$'
komunikat2 db CR, LF, LF, 'Zakonczenie programu - procesor pracuje '
db 'ponownie w trybie rzeczywistym', CR, LF, '$'
komunikat6 db CR, LF, 'Procesor pracuje aktualnie w trybie V86', CR, LF
db ' - przelaczenie do trybu chroniego jest mozliwe tylko '
db 'z trybu rzeczywistego', CR, LF, '$'
;----------------------------------------------------------------------
; kod wykonywany ponownie w trybie rzeczywistym bezposrednio przed
; zakonczeniem wykonywania programu
ASSUME cs:rozkazy
ptt3:
lidt cs:rm_idt ; podanie adresu tabl. wektorow przerwan
; dla trybu rzeczywistego
mov ax, SEG stos_RM ; tworzenie stosu dla trybu rzecz.
mov ss, ax
mov sp, 80H
sti
call czysc_ekran
push cs
pop ds
mov dx, OFFSET komunikat2
mov ah, 09H
int 21H ; wy?wietlenie komunikatu
pelny_koniec:
mov ax,4C00H ; zako¤czenie wykonywania programu
int 21H
;----------------------------------------------------------------------
; kod wykonywany w trybie rzeczywistym bezposrednio po uruchomieniu programu
pocz: nop
INCLUDE GDT.INC
; fragment programu zawarty w pliku GDT.INC wykonywany jest w trybie
; rzeczywistym bezposrednio po uruchomieniu programu; wykonywane jest tam
; czyszczenie ekranu, po czym podawane sa komunikaty informacyjne, po
; ktorych oczekuje sie na potwierdzenie dalszego wykonywania programu
; nastepnie wpisuje odpowiednio zakodowane deskryptory
; do Globalnej Tablicy Deskryptorow GDT
;------------------------------------------------------------------------
; przygotowanie do wykonania rozkazu LGDT (ladowanie rejestru GDTR)
mov ax, OFFSET segment_GDT_end ; rozmiar tablicy GDT
mov word PTR cs:zaw_GDTR+0, ax
mov ax, SEG segment_GDT ; adres (segmentowy) globalnej
; tablicy deskryptorow
movzx eax, ax ; zerowanie starszej czesci EAX
shl eax, 4 ; w EAX adres bazowy segmentu
mov dword PTR cs:zaw_GDTR+2, eax
; przygotowanie do wykonania rozkazu LIDT (ladowanie rejestru IDTR)
mov ax, OFFSET segment_IDT_end ; rozmiar tablicy GDT
mov word PTR cs:zaw_IDTR+0, ax
mov ax, SEG segment_IDT ; adres (segmentowy) tablicy
; deskryptorow przerwan
movzx eax, ax ; zerowanie starszej czesci EAX
shl eax, 4 ; w EAX adres bazowy segmentu
mov dword PTR cs:zaw_IDTR+2, eax
cli ; zablokowanie przyjmowania przerwan
lgdt cs:zaw_GDTR ; ladowanie rejestru GDTR
lidt cs:zaw_IDTR ; ladowanie rejestru IDTR
; przelaczenie do trybu chronionego
mov eax, CR0
or eax, 1
mov CR0, eax
jmp next ; oczyszczenie kolejki rozkaz˘w
; oczekuj?cych na wykonanie
next: nop
; Skok daleki do nastepnej instrukcji - instrukcja ta powoduje zapisanie
; takze rejestru CS w taki sposob, ze selektor 0040H (czyli 8 * 8)
; wpisany do CS wskazuje na deskryptor w tablicy GDT, opisujacy
; niniejszy segment. Zatem bedzie dalej wykonywany kod z tego samego
; segmentu, ale rejestr CS zawiera teraz selektor, a nie adres segmentu.
; Rozkaz skoku dalekiego jest kodowany bajtowo poniewaz
; w asemblerze brak potrzebnego trybu adresowania 'jmp far PTR ca1'
DB 0EAH
DW tryb_PM
dw 8 * 8 ; selektor wskazujacy na deskryptor
; segmentu 'rozkazy'
tryb_PM: nop
;-------------------------------------------------------------------------
; przeprogramowanie uk?adu 8259, tak by przerwanie z zegara (nr 8 w trybie
; rzeczywistym) by?o zwi?zane z nr 32, przerwanie z klawiatury (nr 9)
; - z nr 33, itd.
call przestaw_8259
; inicjalizacja stosu - segment stosu dla trybu chronionego
; opisany jest przez deskryptor 7
mov ax, 7 * 8
mov ss, ax
mov sp, 1000
; inicjalizacja rejestrow DS, ES, FS, GS - wpisanie selektora wskazujacego na
; segment 'nowe_dane'
mov ax, 2 * 8
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call zeruj_bufor_klaw ; zerowanie bufora klawiatury
sti ; wlaczenie przyjmowania przerwan
; wyswietlenie komunikatu "Procesor pracuje w trybie chronionym"
mov bx, OFFSET kom4
call wyswietl
;-----------------------------------------------------------------------
; Glowna petla przyjmowania zlecen od uzytkownika w trybie chronionym
; sprawdz, czy w buforze klawiatury jest kod Enter (0DH) lub Esc (1BH)
czytaj_od_nowa:
mov ax, 2 * 8
mov ds, ax
; mov dx, 0 ; uzywany do sterowania wyswietlaniem
klaw14:
mov cx, ds:indeks_klaw
jcxz klaw14 ; skok, gdy pusty bufor
; cmp cx, dx
; jbe ptl_klaw3 ; skok, gdy nie napisano nowych znakow
; mov bx, OFFSET bufor_klaw
; call wyswietl ; wyswietlanie bufora klawiatury
mov cx, ds:indeks_klaw
; mov dx, cx ; przepisanie CX do DX po wyswietleniu bufora
ptl_klaw3:
mov bx, 0
ptl_klaw2:
mov al, ds:bufor_klaw[bx]
cmp al, 0DH
je byl_Enter
cmp al, 1BH
je byl_Esc
inc bx
loop ptl_klaw2
jmp klaw14
byl_Enter:
mov si, OFFSET bufor_klaw
mov di, OFFSET txt_czas
call porownaj_teksty
jne nast1
call wyswietl_czas
jmp cd43a
nast1:
mov si, OFFSET bufor_klaw
MOV di, OFFSET txt_polecenie
CALL porownaj_teksty
JNE cd43
CALL interfejs
;MOV si
jmp cd43a
cd43:
mov bx, OFFSET kom5 ; nierozpoznane polecenie
call wyswietl
cd43a:
call zeruj_bufor_klaw ; zerowanie bufora klawiatury
jmp czytaj_od_nowa
byl_esc:
mov bx, OFFSET bufor_klaw
call wyswietl
; przygotowanie do powrotu do trybu rzeczywistego - skok daleki
; do segmentu kodu (kodowany bajtowo, poniewaz
; w asemblerze brak potrzebnego trybu adresowania 'jmp far PTR przelacz_do_RM'
DB 0EAH
DW przelacz_do_RM
dw 10 * 8 ; nr pozycji deskryptora wskazuj?cego
; segment rozkazowy
;-----------------------------------------------------------------------
INCLUDE PODPROGR.INC
; plik PODPROGR.INC zawiera podprogram zmiany trybu ukladu 8259
; oraz podprogram wyswietlania tekstu na ekranie w trybie chronionym
INCLUDE FLOPPY.INC
;plik zawiera podprogramy do obslugi dyskietki
rozkazy_end LABEL near
rozkazy ENDS
;----------------------------------------------------------------------
roz_zak SEGMENT use16
ASSUME cs:roz_zak
; rozkazy zawarte w tym segmencie wykonywane sa bezposrednio przed
; przejsciem z trybu chronionego do trybu rzeczywistego
przelacz_do_RM: nop
; przywr˘cenie tradycyjnych numer˘w przerwa¤
cli ; wy??czenie przyjmowania przerwa¤
mov al,11H
out 20H,al
mov al,8
out 21H,al
mov al,4
out 21H,al
mov al,1
out 21H,al ; ladowanie ICW4
mov al,0BCH
out 21H,al
; przed przejsciem do trybu rzeczywistego rejestry segmentowe powinny
; zawierac selektory wskazujace fikcyjny segment danych (zob. opis
; deskryptora 10)
mov ax, 9 * 8 ; deskryptor na pozycji nr 9 wskazuje
; fikcyjny segment danych
mov ds,ax
mov es,ax
mov ss,ax
mov fs, ax
mov gs, ax
; zerowanie bitu PG w CR0
mov eax, CR0
and eax, 7FFFFFFFH
mov CR0, eax
; zerowanie rejestru CR3
mov eax, 0
mov CR3, eax
; zerowanie bitu PE w rejestrze CR0 (wlaczenie trybu rzeczywistego)
mov eax, CR0
and eax,0FFFFFFFEH
mov CR0, eax
jmp far PTR ptt3
roz_zak ENDS
;-----------------------------------------------------------------------
obsl_int SEGMENT use16
ASSUME cs:obsl_int
; Ka§demu przerwaniu odpowiadaj? 3 rozkazy zajmuj?ce ??cznie 7 bajt˘w.
; Pierwszy z tych rozkaz˘w zapami?tuje rejestr CX na stosie, za? nast?pny
; wpisuje do CX nr przerwania lub wyj?tku, co pozwala, w dalszej cz??ci
; procedury obs?ugi, zidentyfikowa? przyczyn? przerwania i ewentualnie
; podj?? dzia?ania w?a?ciwe dla zaistnia?ego zdarzenia.
xpom=0
REPT 128
push cx ; nr przerwania lub wyj?tku
mov cx,xpom
jmp proc_obsl
xpom=xpom+1
ENDM
ORG $+128 ; wymusza by nie wyst?powa?y JMP SHORT
proc_obsl: sti
push ds
push es
push ax
push bx
push dx
push si
mov ax, 3 * 8 ; selektor pamieci ekranu
mov ds,ax
; wyst?pienie przerwania lub wyj?tku b?dzie sygnalizowane za pomoc?
; znaku '*' wy?wietlanego w wierszu 15 na pozycji odpowiadaj?cej
; numerowi przerwania lub wyj?tku
mov bx,160 * 15
add bx,cx ; w CX znajduje si? nr przerwania lub wyj?tku
add bx,cx ; dodawanie (BX) + 2 * (CX), bo znak
; zajmuje w pami?ci ekranu dwa bajty
mov byte PTR ds:[bx],'*'
inc bx
mov byte PTR ds:[bx],7 ; atrybut znaku
cmp cx,33 ; czy przerwanie z klawiatury
jne przeskocz_klaw
; obsluga przerwania z klawiatury
in al,60H ; odczyt kodu pozycji klawisza
xor ah,ah ; zerowanie rejestru AH
push ax ; przechowanie rejestru AX
in al,61H
or al,82H
out 61H,al
and al,7FH
out 61H,al
pop ax ; odtworzenie rejestru AX
cmp al, 55
ja przeskocz_klaw ; nie sa obslugiwane klawisze o kodach
; pozycji > 55
mov bx, 2 * 8 ; selektor do segmentu 'nowe_dane'
mov ds, bx
mov si, OFFSET tabl_przekA
mov bl, al
xor bh, bh
mov al, ds:[si+bx]
cmp al, 0
jne klaw2
mov al, ' '
; wyswietlenie znaku na ekranie w przedostatnim wierszu
klaw2:
mov bx, 3 * 8 ; selektor pamieci ekranu
mov es, bx
mov bx, ds:indeks_klaw
shl bx, 1
add bx, 160 * 23 + 4
mov es:[bx], al
; dopisanie znaku do bufora
cli
mov bx, OFFSET bufor_klaw
add bx, ds:indeks_klaw
mov ds:[bx], al
inc word PTR ds:indeks_klaw
cmp ds:indeks_klaw, 128
jb klaw3
dec word PTR ds:indeks_klaw ; dekrementacja, gdy koniec bufora
klaw3:
sti
przeskocz_klaw:
CMP cx,38
JNE przeskocz_floppy
MOV ax,2*8 ;deskryptor segmentu nowe_dane
MOV ds,ax
MOV ds:floppy_int,1
;obsluga przerwania ze stacji dyskietek
przeskocz_floppy:
CMP cx,32
JNE przeskocz_zegar
MOV ax,2*8 ;deskryptor segmentu nowe_dane
MOV ds,ax
MOV al,ds:oczekiwanie
CMP al,0 ;nie odliczamy juz?
JE przeskocz_zegar
DEC al ;zmniejsz licznik
MOV ds:oczekiwanie,al
przeskocz_zegar:
mov al, 20H
out 20H, al ; end of interrupt (OCW2)
pop si
pop dx
pop bx
pop ax
pop es
pop ds
pop cx
iret
obsl_int_end LABEL near
obsl_int ENDS
END pocz