All pastes #918025 Raw Edit

Miscellany

public text v1 · immutable
#918025 ·published 2008-02-25 21:07 UTC
rendered paste body
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