Comment | 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