background image

Instytut Teleinformatyki i Automatyki

LABORATORIUM 

SYSTEMÓW WBUDOWANYCH

Sprawozdanie z ćwiczenia laboratoryjnego nr 2

TEMAT: 

Tryby pracy procesorów firmy Intel

 

Prowadzący ćwiczenia:

dr inż. Artur Arciuch
mgr inż. Waldemar Szylberg

background image

WSTĘP TEORETYCZNY

Zasadniczo istnieją 4 tryby pracy procesora 386+: 

tryb rzeczywisty (real mode) 

tryb chroniony (protected mode) 

tryb wirtualny V86 - kombinacja 2 powyższych 

ryb nierzeczywisty (tzw. unreal mode - procesor pracuje w RM, ale można używać adresowania 32-
bitowego; to jest raczej sztuczka programistyczna) 

Każdy procesor z rodziny x86 po rozpoczęciu pracy działa w trybie rzeczywistym. W takim trybie procesor 
"widzi" tylko pierwszy megabajt RAM'u i dopiero system operacyjny (typu Windows lub Linux) przełącza 
go w protected mode podczas bootowania. W dodatku pamięć w RM jest podzielona na segmenty po 64kB 
co   np.   bardzo   utrudnia   używanie   w   programach   tablic   o   rozmiarach   przekraczających   ten   limit.

Tryb   chroniony   stwarza   możliwość   użycia   naprawdę   dużej   ilości   pamięci   (do   4   GB   na   386,   w 
przeciwieństwie do dotychczasowego 1 MB). Nie trzeba już używać powolnych EMS i XMS by dostać się 
do pamięci rozszerzonej. Ponieważ rozmiar segmentu nie jest ograniczony do 64kB, można w praktyce 
wyeliminować  rejestry  segmentowe  i operować  w tzw. trybie  flat  - jest  to ważne  w przypadku  kiedy 
potrzebujemy dużej prędkości działania programu, DS jest zajęty a my nie chcemy prefixowac ES'em, 
FS'em itd. Inne zastosowanie: operacje na buforach ekranowych przy dużych rozdzielczościach i/lub dużej 
liczbie kolorów, które to bufory wymagają więcej niż 64kB pamięci.

W   trybie   chronionym   wszystkie   przerwania   BIOS   lub   DOS'a,   których   używaliśmy,   przykładowo,   do 
obsługi plików, staja się bezużyteczne bo nie mogą działać w Protected Mode (oczywiście można to obejść 
poprzez   chwilowe   wychodzenie   z   trybu   chronionego   do   trybu   rzeczywistego   na   czas   wykonywania 
przerwania,

 

ale

 

nie

 

jest

 

to

 

już

 

takie

 

łatwe).

 

Nie   można   także   beztrosko   używać   samomodyfikujacego   się   kodu   -   czytanie   lub   zapis   w   segmencie 
wykonywalnym

 

spowoduje

 

wygenerowanie

 

wyjątku

 

GP.

Wprowadzenie mechanizmów ochrony pamięci wymagało podjęcia specjalnych środków. Każdy segment 
(kod,   dane,   stos)   opisywany   jest   przez   tzw.   deskryptor.   Zadaniem   deskryptora   jest   określenie   BAZY 
SEGMENTU (jego fizycznego adresu w pamięci, np. dla bufora VGA adres bazowy wynosi 0A0000h), 
LIMITU (rozmiaru segmentu - może wynosić od 1B do 4GB) oraz jego TYPU/FLAG (czy segment zawiera 
dane,

 

kod,

 

etc.)

Technicznie rzecz biorąc deskryptor jest to 8-bajtowa struktura danych, która rezyduje gdzieś w pamięci 
operacyjnej i ma następujący format:

background image

Znaczenie

 

kolejnych

 

bajtów

 

jest

 

takie:

0,

 

1

 

-

 

młodsze

 

słowo

 

długości

 

segmentu

 

(limitu)

2,

 

3

 

-

 

młodsze

 

słowo

 

adresu

 

bazowego

 

segmentu

4

 

-

 

młodszy

 

bajt

 

starszego

 

słowa

 

adresu

 

bazowego

5

 

-

 

flagi

 

segmentu

6

 

-

 

starszy

 

półbajt

 

limitu

 

i

 

tzw.

 

flagi

 

dostępu

7

 

-

 

starszy

 

bajt

 

starszego

 

słowa

 

adresu

 

bazowego

Rozmiar segmentu w protected mode może być dowolny (a wiec nie tylko 64kB, ale także każda inna 
wielkość od 1B do 4GB). Jak wynika z opisu limit w deskryptorze jest to liczba 20-bitowa (8 + 8 + 4) co 
daje maksymalnie 1048576 czyli 1MB. 

Adres bazowy to 32-bitowa liczba wyznaczająca początek segmentu w pamięci. Zazwyczaj pisząc typowy 
DOS'owy extender bazę możemy wyznaczyć poprzez pomnożenie przez 16 numeru segmentu, w którym 
znajduje się nasz kod 32-bitowy. Wartość ta będzie dla nas bardzo ważna jeśli będziemy chcieli np. dobrać 
się do pamięci ekranu. 

Pojawia się pytanie:  skąd procesor wie, gdzie  w pamięci  znajduje  się dany deskryptor? Postanowiono 
grupować deskryptory w tablice tzn. kolejno następujące po sobie deskryptory.

Tablica   ta   zawiera   3   deskryptory:   tzw.   Null   Descriptor,   deskryptor   segmentu   kodu   oraz   deskryptor 
segmentu   danych.   Ten   pierwszy   pojawia   się   tylko   w   tablicach   GDT   i   zawsze   zawiera   same   zera.

Wyróżniamy 3 typy tablic: GDT (Globalna Tablica Deskryptorów), LDT (Lokalna Tablica Deskryptorów; 
używana   przez   pojedynczy   proces   w   systemie)   oraz   IDT   (Tablica   Deskryptorów   Przerwań).

Procesor musi wiedzieć, gdzie takie tablice się znajdują i dlatego dysponuje specjalnymi rejestrami, które 
zawierają 32-bitowy fizyczny adres danej tablicy oraz jej długość. Są 3 rejestry: GDTR (przechowuje adres 
i długość GDT) oraz, analogicznie, LDTR i IDTR.

Kod programu przełączający procesor w tryb protected:

Comment |

Program przełączający w tryb protected

|

.386p

CR         EQU     0DH

LF         EQU     0AH

;-------------------------------------------------------------------------

background image

; globalna tablica deskryptorów

segment_GDT    SEGMENT     use16

           dq      0       ; poz. 0 - deskryptor zerowy (nieużywany)
           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
           

           dq      0       ; poz.11 - selektor 0050H
           dq      0       ; poz.12 - selektor 0050H

           dq      0       ; poz.13 - selektor 0050H
           dq      0       ; poz.13 - selektor 0050H

segment_GDT_end    LABEL   byte

segment_GDT    ENDS

;-------------------------------------------------------------------

; tablica deskryptorów przerwań

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
; zawierać będą 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
kom4       db      'Procesor pracuje w trybie chronionym '

           db      ' - wciśnięcie dowolnego klawisza spowoduje wyjście'

   db 

   ' - naciśniecie ESC spowoduje zakończenie programu',0

kom5       db      'Nierozpoznane polecenie', 0
txt_czas   db      'czas',13,0

bufor_klaw db      128 dup (?)      ; bufor klawiatury
indeks_klaw dw      0

indeks_zeg  dw

    0

ekran_x    db       0               ; wskaźnik nr kolumny do zapisu na ekranie

ekran_y    db       0               ; wskaźnik nr wiersza do zapisu na ekranie
; tablica do przekodowania kodów pozycji na kody ASCII

pozycja

   dw     160*12+80 

x

   dw     1

y

   dw     1

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

background image

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 ładowania rejestrów GDTR oraz IDTR
zaw_GDTR   dp      0

zaw_IDTR   dp      0
rm_idt     LABEL   qword   ; wskaźnik do tabl. wekt. przerwań (tryb rzecz.)

           dw      03FFH                       ; wielkość tablicy IDT
           dd      0

czy_koniec  db 0           
komunikat1     db  'Wciśnij dowolny klawisz aby przełączyć w Protected Mode',CR, LF, '$'

komunikat2     db  'Real Mode', CR, LF, '$'
komunikat3

db 'Zakończono program',CR,LF,'$'

zadania

dw zy1,zy2,zy3

komunikat1z     db  'Zadanie1 w RealMode',CR,LF,'$'

komunikat2z     db 'Zadanie2 w RealMode',CR,LF,'$'
komunikat3z

db 'Zadanie3 w RealMode',CR,LF,'$'

;----------------------------------------------------------------------

; kod wykonywany ponownie w trybie rzeczywistym bezpośrednio przed

; zakończeniem wykonywania programu
           ASSUME  cs:rozkazy

ptt3:
           lidt    cs:rm_idt   ; podanie adresu tabl. wektorów przerwań

                               ; 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
           mov     al,byte ptr [czy_koniec]

           cmp

al,0

           je

pocz;

pelny_koniec:

   mov     dx, OFFSET komunikat3

           mov     ah, 09H
           int     21H

           mov     ax,4C00H      ; zakończenie wykonywania programu
           int     21H

;----------------------------------------------------------------------
; kod wykonywany w trybie rzeczywistym bezpośrednio po uruchomieniu programu

pocz:      nop

background image

mov

al,34h

out

43h,al

mov

al,0ffh

out

40h,al

mov

al,0ffh

out

40h,al

; Wyświetlanie komunikatów o przeznaczeniu programu i oczekiwanie

; na potwierdzenie dalszego wykonywania programu
           call    czysc_ekran

           jmp     cd_przyg
; czyszczenie ekranu - przewiniecie okna o zero wierszy

czysc_ekran        PROC    near
           mov     ah, 06      ; przewiniecie okna

           mov     al, 0       ; zero wierszy
           mov     bh, 07      ; atrybut

           mov     ch, 0       ; współrzędne okna
           mov     cl, 0       ; lewy górny róg

           mov     dh, 24      ; prawy dolny róg
           mov     dl, 79

           int     10H
           mov     ah, 2      ; ustawienie kursora w górnym lewym rogu ekranu

           mov     dl, 0
           mov     dh, 0

           mov     bh, 0
           int     10H

           ret
czysc_ekran    ENDP

zy1:
mov     dx, OFFSET komunikat1z

           mov     ah, 09H
           int     21H    

ret

zy2:
mov     dx, OFFSET komunikat2z

           mov     ah, 09H
           int     21H    

ret

zy3:

mov     dx, OFFSET komunikat3z
           mov     ah, 09H

           int     21H    

ret

cd_przyg:

           push    cs
           pop     ds

dalej_RM:

   call   [zadania]

   call

[zadania+2]

   call

[zadania+4]

   

           mov     dx, OFFSET komunikat1

           mov     ah, 09H
           int     21H         ; wyświetlenie komunikatu

           mov     ah, 07H     ; oczekiwanie na naciśniecie klawisza
           int     21H

           cmp     al,27
           je      pelny_koniec; naciśnięto Esc

           call czysc_ekran;

; tworzenie deskryptorów w globalnej tablicy przerwa¤ (na razie wszystkie
; pola w deskryptorach zawierają zera)

; we wszystkich deskryptorach bajt 6 (bity G, D, 0, AVL, rozmiar 19 - 16)
; pozostawiany jest bez zmian (zawiera zero)

;           ASSUME  ds:segment_GDT
           mov     ax, SEG segment_GDT

           mov     ds, ax          ; ładowanie rejestru DS         

background image

; tworzenie deskryptora na pozycji 2 w GDT - deskryptor ten opisuje

; segment 'nowe_dane'
           mov     bx, 2 * 8       ; offset w segmencie segment_GDT

           mov     word PTR ds:[bx], OFFSET nowe_dane_end  - 1 ; rozmiar segmentu
           mov     ax, SEG nowe_dane

           movzx   eax, ax         ; zerowanie starszej części EAX
           shl     eax, 4          ; w EAX adres bazowy segmentu

           mov     ds:[bx]+2,ax       ; adres bazowy 15 - 0
           rol     eax, 16         ; zamiana połówek EAX

           mov     ds:[bx]+4, al      ; adres bazowy 23 - 16
           mov     ds:[bx]+7, ah      ; adres bazowy 31 - 24

           mov     byte PTR ds:[bx]+5, 10010010B ; bajt dostępu
; tworzenie deskryptora na pozycji 3 w GDT - deskryptor ten opisuje

; segment 'ekran'
           mov     bx, 3 * 8       ; offset w segmencie segment_GDT

           mov     word PTR ds:[bx], OFFSET ekran_end  - 1 ; rozmiar segmentu
           mov     ax, SEG ekran

           movzx   eax, ax         ; zerowanie starszej części EAX
           shl     eax, 4          ; w EAX adres bazowy segmentu

           mov     ds:[bx]+2,ax       ; adres bazowy 15 - 0
           rol     eax, 16         ; zamiana połówek EAX

           mov     ds:[bx]+4, al      ; adres bazowy 23 - 16
           mov     ds:[bx]+7, ah      ; adres bazowy 31 - 24

           mov     byte PTR ds:[bx]+5,10010010B ; bajt dostępu
; tworzenie deskryptora na pozycji 6 w GDT - deskryptor ten opisuje

; segment 'obsl_int'
           mov     bx, 6 * 8       ; offset w segmencie segment_GDT

           mov     word PTR ds:[bx], OFFSET obsl_int_end  - 1 ; rozmiar segmentu
           mov     ax, SEG obsl_int

           movzx   eax, ax         ; zerowanie starszej części EAX
           shl     eax, 4          ; w EAX adres bazowy segmentu

           mov     ds:[bx]+2,ax       ; adres bazowy 15 - 0
           rol     eax, 16         ; zamiana połówek EAX

           mov     ds:[bx]+4, al      ; adres bazowy 23 - 16
           mov     ds:[bx]+7, ah      ; adres bazowy 31 - 24

           mov     byte PTR ds:[bx]+5,10011010B ; bajt dostępu
; tworzenie deskryptora na pozycji 7 w GDT

           mov     bx, 7 * 8       ; offset w segmencie segment_GDT
           mov     word PTR ds:[bx], OFFSET nowy_stos_end  - 1 ; rozmiar segmentu

           mov     ax, SEG nowy_stos
           movzx   eax, ax         ; zerowanie starszej części EAX

           shl     eax, 4          ; w EAX adres bazowy segmentu
           mov     ds:[bx]+2,ax       ; adres bazowy 15 - 0

           rol     eax, 16         ; zamiana połówek EAX
           mov     ds:[bx]+4, al      ; adres bazowy 23 - 16

           mov     ds:[bx]+7, ah      ; adres bazowy 31 - 24
           mov     byte PTR ds:[bx]+5,10010010B ; bajt dostępu

; tworzenie deskryptora na pozycji 8 w GDT
           mov     bx, 8 * 8       ; offset w segmencie segment_GDT

           mov     word PTR ds:[bx], OFFSET rozkazy_end  - 1 ; rozmiar segmentu
           mov     ax, SEG rozkazy

           movzx   eax, ax         ; zerowanie starszej części EAX
           shl     eax, 4          ; w EAX adres bazowy segmentu

           mov     ds:[bx]+2,ax       ; adres bazowy 15 - 0
           rol     eax, 16         ; zamiana połówek EAX

           mov     ds:[bx]+4, al      ; adres bazowy 23 - 16
           mov     ds:[bx]+7, ah      ; adres bazowy 31 - 24

           mov     byte PTR ds:[bx]+5,10011010B ; bajt dostępu
; tworzenie deskryptora na pozycji 9 w GDT - deskryptor używany jako

; atrapa przy przejsciu z trybu chronionego do rzeczywistego (w tym
; przypadku adres bazowy w deskryptorze nie ma żadnego znaczenia)

           mov     bx, 9 * 8       ; offset w segmencie segment_GDT
           mov     word PTR ds:[bx],0FFFFH        ; wymagany rozmiar segmentu

; bajt dostępu musi opisywać segment danych (fikcyjny), w którym:
; P=1, ED=0, W=1

           mov     byte PTR ds:[bx]+5,10010010B ; bajt dostępu
; tworzenie deskryptora na pozycji 10 w GDT - deskryptor ten opisuje

; segment kodu 'roz_zak', który jest wykonywany bezpośrednio przed

background image

; przejściem do trybu rzeczywistego (pole "wielkosc" = FFFFH)
           mov     bx, 10 * 8       ; offset w segmencie segment_GDT

           mov     word PTR ds:[bx], 0FFFFH       ; rozmiar segmentu
           mov     ax, SEG roz_zak

           movzx   eax, ax         ; zerowanie starszej części EAX
           shl     eax, 4          ; w EAX adres bazowy segmentu

           mov     ds:[bx]+2,ax       ; adres bazowy 15 - 0
           rol     eax, 16         ; zamiana połówek EAX

           mov     ds:[bx]+4, al      ; adres bazowy 23 - 16
           mov     ds:[bx]+7, ah      ; adres bazowy 31 - 24

           mov     byte PTR ds:[bx]+5,10011010B ; bajt dostępu
           

; tworzenie deskryptora na pozycji 11 w GDT
           mov     bx, 8 * 11       ; offset w segmencie segment_GDT

           mov     word PTR ds:[bx], OFFSET zad1_end- 1 ; rozmiar segmentu
           mov     ax, SEG zad1

           movzx   eax, ax         ; zerowanie starszej części EAX
           shl     eax, 4          ; w EAX adres bazowy segmentu

           mov     ds:[bx]+2,ax       ; adres bazowy 15 - 0
           rol     eax, 16         ; zamiana połówek EAX

           mov     ds:[bx]+4, al      ; adres bazowy 23 - 16
           mov     ds:[bx]+7, ah      ; adres bazowy 31 - 24

           mov     byte PTR ds:[bx]+5,10011010B ; bajt dostępu           
; tworzenie deskryptora na pozycji 11 w GDT

           mov     bx, 8 * 12       ; offset w segmencie segment_GDT
           mov     word PTR ds:[bx], OFFSET zad2_end- 1 ; rozmiar segmentu

           mov     ax, SEG zad2
           movzx   eax, ax         ; zerowanie starszej części EAX

           shl     eax, 4          ; w EAX adres bazowy segmentu
           mov     ds:[bx]+2,ax       ; adres bazowy 15 - 0

           rol     eax, 16         ; zamiana połówek EAX
           mov     ds:[bx]+4, al      ; adres bazowy 23 - 16

           mov     ds:[bx]+7, ah      ; adres bazowy 31 - 24
           mov     byte PTR ds:[bx]+5,10011010B ; bajt dostępu           

; tworzenie deskryptora na pozycji 11 w GDT
           mov     bx, 8 * 13       ; offset w segmencie segment_GDT

           mov     word PTR ds:[bx], OFFSET zad3_end- 1 ; rozmiar segmentu
           mov     ax, SEG zad3

           movzx   eax, ax         ; zerowanie starszej części EAX
           shl     eax, 4          ; w EAX adres bazowy segmentu

           mov     ds:[bx]+2,ax       ; adres bazowy 15 - 0
           rol     eax, 16         ; zamiana połówek EAX

           mov     ds:[bx]+4, al      ; adres bazowy 23 - 16
           mov     ds:[bx]+7, ah      ; adres bazowy 31 - 24

           mov     byte PTR ds:[bx]+5,10011010B ; bajt dostępu           
           

; tworzenie deskryptora na pozycji 11 w GDT
           mov     bx, 8 * 14       ; offset w segmencie segment_GDT

           mov     word PTR ds:[bx], OFFSET shed_end- 1 ; rozmiar segmentu
           mov     ax, SEG shed

           movzx   eax, ax         ; zerowanie starszej części EAX
           shl     eax, 4          ; w EAX adres bazowy segmentu

           mov     ds:[bx]+2,ax       ; adres bazowy 15 - 0
           rol     eax, 16         ; zamiana połówek EAX

           mov     ds:[bx]+4, al      ; adres bazowy 23 - 16
           mov     ds:[bx]+7, ah      ; adres bazowy 31 - 24

           mov     byte PTR ds:[bx]+5,10011010B ; bajt dostępu 

; przygotowanie do wykonania rozkazu LGDT (ładowanie 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 deskryptorów

           movzx   eax, ax             ; zerowanie starszej części EAX

background image

           shl     eax, 4              ; w EAX adres bazowy segmentu
           mov     dword PTR cs:zaw_GDTR+2, eax

; przygotowanie do wykonania rozkazu LIDT (ładowanie 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

                                       ; deskryptorów przerwań
           movzx   eax, ax             ; zerowanie starszej części EAX

           shl     eax, 4              ; w EAX adres bazowy segmentu
           mov     dword PTR cs:zaw_IDTR+2, eax

           cli                         ; zablokowanie przyjmowania przerwań
           lgdt    cs:zaw_GDTR         ; ładowanie rejestru GDTR

           lidt    cs:zaw_IDTR         ; ładowanie 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 następnej instrukcji - instrukcja ta powoduje zapisanie
; także rejestru CS w taki sposób, że selektor 0040H (czyli 8 * 8)

; wpisany do CS wskazuje na deskryptor w tablicy GDT, opisujący
; niniejszy segment. Zatem będzie dalej wykonywany kod z tego samego

; segmentu, ale rejestr CS zawiera teraz selektor, a nie adres segmentu.
; Rozkaz skoku dalekiego jest kodowany bajtowo ponieważ

; w asemblerze brak potrzebnego trybu adresowania 'jmp far PTR ca1'
           DB      0EAH

           DW      tryb_PM
           dw      8 * 8       ; selektor wskazujący 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 wskazującego 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                     ; włączenie przyjmowania przerwań
; wyswietlenie komunikatu "Procesor pracuje w trybie chronionym"

           mov     bx, OFFSET kom4
           call    wyswietl

;-----------------------------------------------------------------------
; Główna pętla przyjmowania zleceń od użytkownika w trybie chronionym

; sprawdź, czy w buforze klawiatury jest kod Enter (0DH) lub Esc (1BH)
czytaj_od_nowa:

           mov     ax, 2 * 8
           mov     ds, ax

;           mov     dx, 0       ; używany do sterowania wyświetlaniem
 DB      0EAH

          DW      str1
         dw      8 * 14

         
         db 0

klaw14:

   mov     cx, ds:indeks_klaw

           jcxz    klaw14      ; skok, gdy pusty bufor

   mov

   ds:indeks_klaw,0

background image

   cmp 

   cx,001Bh

   jne

   klaw14b;

   push ds
   mov

   ax,8*8

   mov

  ds,ax

   mov

  al,1

   mov    byte ptr[czy_koniec],al
   pop ds

   

klaw14b:

   

; przygotowanie do powrotu do trybu rzeczywistego -  skok daleki

; do segmentu kodu (kodowany bajtowo, ponieważ
; 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

; 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.

przestaw_8259      PROC
           mov     al,11H

           out     20H,al      ; ładowanie ICW1 (d4=1 - znacznik
                               ; wskazujący, ze programujemy ICW1

                               ; bit d0=1 - znacznik ,ze wystąpi ICW4
           mov     al,32

           out     21H,al      ; ustawienie bazowego wektora przerwań
                               ; (ustawienie ICW2)

           mov     al,4
           out     21H,al      ; ICW3 - d2=1 - tryb niebuforowany, 8259 master

           mov     al,1
           out     21H,al      ; ICW4 - d0=1 - potwierdzenie ICW2 jako wektora

                               ; przerwań
           ret

przestaw_8259      ENDP

;--------------------------------------------------------------------------
; wyswietlanie tekstu na ekranie - tekst zawarty jest w segmencie danych

; dla trybu chronionego (selektor 0010H), a offset podany jest w BX
; tekst wyswietlany jest w wierszu wskazanym przez zmienna ekran_y

; ekran_x    db       0               ; wskaźnik nr kolumny do zapisu na ekranie
; ekran_y    db       0               ; wskaźnik nr wiersza do zapisu na ekranie

wyswietl   PROC

; selektor 0010H (2 * 8) wskazuje deskryptor segmentu danych dla trybu
; chronionego ('nowe_dane')

           push    ds
           push    es

           mov     ax, 2 * 8
           mov     ds, ax

           mov     ax, 3 * 8   ; selektor pamięci ekranu
           mov     es,ax

           mov     al, 160
           mul     byte PTR ds:ekran_y         ; w AX adres ekranu do zapisu

           mov     di, ax
           mov     ah,7        ; atrybut wyświetlania

ptl_kom:   mov     al,ds:[bx]  ; pobranie kolejnego znaku komunikatu
           or      al, al

           jz      koniec_wysw ; bajt zerowy wskazuje koniec tekstu
           mov     es:[di],ax  ; przesłanie znaku do pamięci ekranu

           inc     bx          ; inkrementacja BX

background image

           inc     di          ; inkrementacja DI
           inc     di          ; inkrementacja DI

           jmp     ptl_kom
koniec_wysw:

           mov     al, ds:ekran_y
           inc     al

           cmp     al, 23
           jae     przesun_ekran

           mov     ds:ekran_y, al
zak_wysw:

           pop     es
           pop     ds

           ret
; przesuwanie calego ekranu o jeden wiersz w gore

przesun_ekran:
           dec     al

           mov     ds:ekran_y, al
           mov     ax, 3 * 8   ; selektor pamięci ekranu

           mov     ds, ax
           mov     es, ax

           mov     cx, 2000 - 240
           mov     si, 160

           mov     di, 0
           cld

           rep     movsw
           jmp     zak_wysw

wyswietl   ENDP

rozkazy_end    LABEL near

rozkazy    ENDS

;----------------------------------------------------------------------

roz_zak    SEGMENT use16

           ASSUME  cs:roz_zak

; rozkazy zawarte w tym segmencie wykonywane są bezpośrednio przed

; przejściem 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

background image

           mov     al,1

           out     21H,al      ; ładowanie ICW4

           mov     al,0BCH

           out     21H,al

; przed przejściem do trybu rzeczywistego rejestry segmentowe powinny

; zawierać selektory wskazujące 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 (włączenie trybu rzeczywistego)

           mov     eax, CR0

           and     eax,0FFFFFFFEH

           mov     CR0, eax

           jmp     far PTR ptt3

roz_zak    ENDS

background image

;-----------------------------------------------------------------------

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

           cmp     cx,33       ; czy przerwanie z klawiatury

   je    klawisze

   sti
   jmp

   przeskocz_klaw

; obsluga przerwania z klawiatury

klawisze:

           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, 57

           ja      przeskocz_klaw  ; nie sa obsługiwane 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]

klaw2:
; dopisanie znaku do bufora

           cli
;           mov     bx, OFFSET bufor_klaw

;           add     bx, ds:indeks_klaw
;           mov     ds:[bx], al

background image

dalej:

       mov     word PTR ds:indeks_klaw,ax    

    mov

    bx,3*8

    mov

    es,bx

    mov     bx,ds:pozycja

    mov

    es:[bx],al

    

    jmp     przeskocz_klaw

przeskocz_klaw:

           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
shed SEGMENT use16

ASSUME  cs:shed
z1 db 0

z2 db 0
z3 db 0

nz db 0
nzb db 0

str1:

DB      0EAH

    DW      s

dw      8 *11       ; selektor wskazujący na deskryptor

za2:

DB      0EAH

    DW      ss1

dw      8 *12       ; selektor wskazujący na deskryptor

za3:

DB      0EAH

    DW      sss

dw      8 *13       ; selektor wskazujący na deskryptor

konza:

DB      0EAH

    DW      klaw14

dw      8 *8       ; selektor wskazujący na deskryptor

                               ; segmentu 'rozkazy'

shed_end label near                               
shed ENDS

zad1    SEGMENT use16

ASSUME  cs:zad1
s:

push ds;
mov ax,8*3

mov ds,ax
mov al,'a'

mov bx,160*3
mov byte ptr ds:[bx],al

pop ds

DB      0EAH

background image

    DW      za2

dw      8 * 14       ; selektor wskazujący na deskryptor

                               ; segmentu 'rozkazy'

zad1_end  label near                               
zad1 ENDS

zad2    SEGMENT use16
ASSUME  cs:zad2

ss1:

push ds;
mov ax,8*3

mov ds,ax
mov al,'b'

mov bx,160*4+2
mov byte ptr ds:[bx],al

pop ds
DB      0EAH

    DW      za3

dw      8 * 14       ; selektor wskazujący na deskryptor

                               ; segmentu 'rozkazy'
zad2_end  label near                               

zad2 ENDS

zad3    SEGMENT use16
ASSUME  cs:zad3

sss:

push ds;

mov ax,8*3
mov ds,ax

mov al,'c'
mov bx,160*5+4

mov byte ptr ds:[bx],al
pop ds

DB      0EAH

    DW      konza

dw      8 * 14       ; selektor wskazujący na deskryptor

                               ; segmentu 'rozkazy'

zad3_end  label near                               
zad3 ENDS

           END     pocz


Document Outline