"
Jak używać portów?
"
O portach pisałem już trochę w informacjach
podstawowych, lecz teraz przyszedł czas na bardziej konkretne
informacje.
Sprawa portów jest dość podobna do przerwań - istnieje jedna
instrukcja do ich (przerwań) obsługi a możliwości jakie przez nią
uzyskujemy są ogromne, ale warunkiem jest znajomość parametrów
przerwań o czym również pisałem.
W przypadku portów istnieją dwie instrukcje - IN - pobierz z portu i
OUT - wyślij na port, ale warunkiem pełnego wykorzystania tych
instrukcji jest znajomość specyfikacji poszczególnych urządzeń (karta
muzyczna chociażby).
Składnia:
IN AKUMUL, PORTNUM
OUT PORTNUM, AKUMUL
Instrukcja IN (in - w) powoduje pobranie bajtu lub słowa z portu i
wrzucenie go do "akumul". Można tu znaleźć analogie do
pascalowskiego port i portw - gdy "akumul" jest bajtem (al) pobrany
zostaje bajt z portu, gdy zaś jest słowem (AX),
jeden bajt pobrany będzie z portu "portnum" a drugi z "portnum"+1.
Warto tu jeszcze zaznaczyć, że "akumul" to bezwzględnie rejestr AL
(port), lub AX (portw) - inne rejestry nie są dozwolone.
W pascalu zapis instrukcji IN wyglądał więc by tak:
var
al:byte;
ax:word;
...
al:=port[portnum];
lub
AX:=portw[portnum]; (w zależności od tego o czym pisałem).
OUT (out - poza) wyrzuca "akumul"(AL lub AX) na port - jest to robione
analogicznie jak przy IN tzn. jeśli "akumul" jest bajtem, to wówczas
bajt ten zostanie wrzucony na port o numerze "portnum", jeśli "akumul"
jest słowem(AX) - AL pujdzie na port o numerze "portnum",
AH natomiast na port "portnum"+1.
W pascalu wyglądać to będzie:
port[portnum]:=AL;
lub
portw[portnum]:=AX;
Oczywiście tutaj również "akumul" znaczy wyłącznie rejestr AX
(accumulator register - rejestr akumulatora).
Pewnych wyjaśnień wymaga tu jeszcze "portnum" - otóż nie
powiedzieliśmy sobie, czy ma to być rejestr czy też wartość wpisywana
bezpośrednio... i tu sprawa nie jest już tak prosta.
Zasada jest prosta - jeśli numer portu na który chcemy coś wyrzucić
bądź pobrać jest <=0FFH (255) (wartość bajt), to wówczas możemy go adresować
zarówno bezpośrednio (IN AL, 60H) jak i przez rejestr (IN AL, DX).
Gdy więc "portnum" jest >255 (dwubajtowy), wówczas możemy odwoływać
się wyłącznie przez rejestr DX, w sposób następujący:
...; deklaracje segmentów itd.
MOV DX,378H; numer lpt1, przykładowy numer portu
OUT DX, AL ; wyrzucenie wartości AL na port 378h
...; dalsza część pprogramu
Jak już pisałem porty same w sobie bez znajomości sposobu odwoływania
się do urządzeń nie dają nam zbyt wielkich możliwości; niestety -
specyfikacje urządzeń bywają niekiedy znacznie trudniejsze od
przerwań choćby dlatego, że nie ma żadnych generalnych ustaleń - każde
urządzenie (dysk twardy, interfejs midi... czy wreszcie karta
muzyczna) ma swój własny standard... o tym więc mówi się przy okazji
omawiania "konieczności znajomości budowy wewnętrznej komputera" przed
przystąpieniem do nauki Assemblera.
Pewne rzeczy jednak, należą do "klasyki" - np. to, że port 60H jest
portem klawiatury i z niego można czytać znaki bezpośrednio: Jeśli
wartość pobrana z tego portu jest <80h, to znaczy, że wciśnięto jakiś
klawisz (wówczas wartość portu 60H = skankod tego klawisza), jeśli zaś
AL będzie >80H - znaczy, że puszczono klawisz (wartość na porcie
=skankod puszczonego klawisza +128).
Skankod jest zdecydowanie czymś innym niż Ascii - np. klawisz ESC ma
tu wartość 01H... jeśli chcesz uzyskać listę skankodów zajrzyj do
książki, lub napisz sobie prosty program (w assemblerze), który
wyświetli kod naciskanego klawisza i poeksperymentuj.
Przykładowy program demonstrujący użycie IN i
OUT dziś znacznie mniej ambitny, ale przecież to tylko przykład:).
Powrót do spisu treści
kursu

Copyright by
Grzegorz Złotowicz
Form and Graphics: Michał Stanek