ÚÄÄÄ        ÚÄÄÄ     ÚÄ       ÚÄ
  ÚÄ  ÚÄ      ÚÄ   ÚÄ   ÚÄÚÄ   ÚÄÚÄ
 ÚÄ    ÚÄ     ÚÄ        ÚÄ  ÚÄÄ  ÚÄ
ÚÄÄ    ÚÄÄ      ÚÄÄ     ÚÄ   Ú   ÚÄ  ASSEMBLY RULEZ
ÚÄÄÄÄÄÄÄÄÄ         ÚÄ   ÚÄ       ÚÄ
ÚÄÄ    ÚÄÄ   ÚÄ    ÚÄ   ÚÄ       ÚÄ    III.rész
ÚÄÄ    ÚÄÄ     ÚÄÄÄÄ    ÚÄ       ÚÄ

 

MEGSZAKÍTÁSOK

     A számítógépek egyik legfontosabb tulajdonságukat köszönhetik a megszakításoknak. Nevezetesen azt, hogy reagálni tudnak a külsõ eseményekre (pl.: egy billentyû lenyomása) anélkül, hogy állandóan várni kellene rájuk, így nem pocsékolják feleslegesen a proci idejét.

     Mik is azok a megszakítások? Röviden azt lehet mondani, hogy minden olyan esemény megszakítás, aminek hatására a proci abbahagyja amit addig csinált és elkezd a megszakítás okozójával foglalkozni. Persze ez egy nagyon általános megfogalmazás, de kezdetnek megteszi.
   A PC-ben háromféle dolog válthat ki megszakítást:

     Na akkor itt teszünk egy kis kitérõt. Az elõbb hivatkoztam a valós meg a védett üzemmódra. Ezek csak a 80286 vagy fejlettebb procikon vannak. Valós üzemmódban a proci úgy mûködik mint egy 8086, csak gyorsabb. Tehát az összes 8086-ra írt program fut rajta. Védett módban megnyílnak a proci plusz képességei felé vezetõ utak, de ezt legfeljebb a cikksorozat végén taglalom majd bõvebben.

     Vissza a megszakításokhoz!
A megszakítások magukban semmit nem érnek. Kell hozzájuk kiszolgáló rutinokat írni. Ezek fogják elvégezni a szükséges feladatokat. Példul a billentyûzet megszakítás-kezelõje lekérdezi a lenyomott billentyût, és a megfelelõ kódot elhelyezi egy tárolóban.

     Nézzük elõször a szoftver megszakításokat, mivel ezek nélkül nem tudjuk elérni a DOS "szolgáltatásait".
A szoftver megszakítások nem mások, mint olyan rutinok, amelyeknek nem ismerjük a pontos memóriabeli helyét, csak egy sorszámmal hivatkozunk rájuk. Ezt a sorszámot az INT utasítással adjuk át a procinak, mire õ elindítja a megfelelõ rutint.

   INT utasítás:

     Használat: INT megszakítás_sorszáma

A megszakítás_sorszáma egy szám, az ennek megfelelõ rutint hívja meg a proci.

     Példa:  INT 21h  ; Ez a DOS funkciókat hívja meg
                INT 10h  ; A képernyõkezelõ rutinok gyûjteménye

     Bizonyára feltûnt, hogy a példában rutingyûjteményre hivatkoztam. Ez nem elírás. A 8086 csak 255 megszakítást képes kezelni, de sokkal több rutin kell a mûködéshez. Ezért a rutinokat csoportosították (pl.:DOS, Video-BIOS esatöbbi). Egy-egy ilyen csoport kapott egy megszakításszámot. Most az a kérdés, hogy miként választom ki, melyik rutin kell nekem. Erre ad megoldást a funkciókód, ami az adott csoporton belül azonosítja a kívánt rutint. A funkciókódot általában (gyakorlatilag mindig) az AH regiszterbe kell tölteni. Ezt a MOV utasítással tehetjük meg.

   MOV utasítás:

     Használat:  MOV cél, forrás

 Ez betölti a forrás értékét vagy az általa meghatározott byteot a célba.

A cél és a forrás a következõk lehetnek. Itt a legtöbb cél-forrás kombinációt leírom. Ami kimarad azt majd késõbb mesélem el.

Cél

Forrás

Példa

regiszter

regiszter

MOV BX,CX

regiszter

számérték

MOV DI,szám

regiszter

memória rekesz

MOV AL,memória

16 bites regiszter

szegmens regiszter

MOV DX,DS

szegmens regiszter

16 bites regiszter

MOV ES,AX

szegmens regiszter

16 bites memória rekesz

MOV ES,memória

memória rekesz

számérték

MOV memória,szám

memória rekesz

regiszter

MOV memória,SI

memória rekesz

szegmens regiszter

MOV memória,SS

 

     Azt hiszem mindent leírtam. A regiszter bármelyik regiszter lehet, a 16 bites regiszter jelzés viszont kizárja a félregisztereket (AL,Bl...). A 16 bites memóriarekesz pedig azt jelenti, hogy az assembler által 8 bitesnek értelmezett memóriaegységre nem tölthetünk be 16 bites értéket, csak ha külön jelezzük a fordítónak (az assembly forráskód szerkezetét majd késõbb).

   Ezek után már meg tudjuk hívni bármelyik DOS funkciót. Teszem azt fejezzük be a programot. Ehhez a 4Ch funkciót kell meghívni a DOS funkciók közül.

     MOV AH,4Ch
     INT 21h

   És már ki is lépett a programunk. Mielõtt bárki le akarná fordittatni most szólok, hogy nem fog tetszeni a fordítónak. Majd nemsokára kiderül miért.

 

CÍMZÉSI MÓDOK

     Ahhoz, hogy el tudd érni a memóriában tárolt adataidat, meg kell tudni címezni az adott részt. Elég sok címzési mód van, de egyelõre csak néhányat mondok el, a többit majd ha szükség lesz rá. Amiket most leírok egyszerûbb dolgokra elegendõek.

     Most ennyit gondolok fontosnak, de akit a többi is érdekel, az a cikk végén a könyvekbõl utánanézhet. Nagyon fontos még az alapértelmezett szegmensregiszter. Ez azt jelenti, hogy minden címzési módhoz van egy szegmensregiszter, amivel a proci kiszámolja a valódi címet. Lássuk ezeket:

     Persze kissé kényelmetlen lenne, ha csak ezeket a szegmensregisztereket lehetne használni, meg akkor mi értelme lenne a többinek. Ezért van egy un. szegmensfelülíró prefix. Ez mondja meg a procinak, hogy az alap helyett melyiket használja. Használni is egyszerû: MOV es:[kender],1234h és máris az ES-hez viszonyítva címez a proci. Ilyen felülíró lehet CS, ES, SS de ha valakinek olyanja van a DS-t is kiteheti, nem baj.

 

PORTOK

     A portok segítségével lehet valamilyen hardver elem részeihez hozzájutni, onnan adatot olvasni vagy oda adatot írni. Portokon keresztül vezérelhetõ a videokártya, a billentyûzet, a hangkártya, az I/O kártya, a CMOS és még sok egyéb dolog. Amit memóriába írással/olvasással nem lehet elérni, azt a portok írásával/olvasásával tesszük meg. A 8086 összesen 65536 portot tud kezelni. Persze néhány dolognál kissé egyszerûbbé tették a dolgot és nem kell a portokkal bajlódni. Ilyen pl a videokártya, amit a 10h megszakítási rutin gyûjteménnyel érhetünk el.

     Persze ezek a könnyítések mindig csak egy határig azok. Ha a feladat bonyolult vagy nagy sebességre kell írni, akkor a BIOS körülményes lehet. Jó példa erre egy egyszerû 640x480x256-os kép kirajzolása. BIOSszal qrva lassú, de ha te magad írod meg a rutint minden nyûgöt vállalva akkor gyors lesz. Példul nézd meg a KENDERMAGot. Ha a videokártya választáskor megtaláltad a saját kártyádat és azt választottad, akkor elég gyors a kép kirajzolása (ne a menüt figyeld hanem egy igazi kép kirajzolását). Viszont a BIOS-t választva (ha az újság ismeri a kártyád, akkor is választhatod)
iszonytatóan lassú és ez kivételesen nem a programozó (szándékosan nem coder) hibája. Majd ha olyan dolgot kell megoldani, akkor itt is bemutatom a portok programozását. Egyelõre elég annyit tudni, hogy az IN és OUT utasításokkal lehet elérni ezeket.

   IN utasítás:
   
Használat:  IN akkumulátor,port

      Ez egy byteot vagy szót tölt be az adott portról az akkuba. Ha nem emlékeznél az akkumulátor az AX regisztert jelöli (meg a részeit is). Itt most csak az AX vagy AL használható. A portot kétféle módon lehet megadni. Vagy közvetlen értékkel vagy a DX-ben tárolt számmal.

     Példa:  IN AL,60h        ; Lenyomott billentyû scankódjának olvasása
               MOV DX,3DAh  ; Portszám DX-be, VGA státuszregiszter
               IN AL,DX          ; DX által adott portról adat olvasása

   Ha közvetlen értékkel adjuk meg a portot, akkor csak az elsõ 256-ot lehet elérni, mivel az érték egybyteos lehet.

   OUT utasítás:

Használat: OUT port,akkumulátor

     Egy byteot vagy szót ír ki a megadott portra. A kiírandó értéknek az akkuban kell lennie (AX vagy AL). A port itt is úgy adható meg, mint az IN utasításnál. Lényegében az IN utasítás fordítottja, így közvetlen értékkel csak az elsõ 256 port érhetõ el.

     Példa:  OUT 70h,al  ; AL által meghatározott CMOS regiszter kiválasztása
                MOV DX,3D4h ; A VGA kártya CRTC regisztereibõl a
                MOV AL,00h  ; 00h sorszámút választjuk ki a 3D4h
                OUT DX,AL   ; portra való írással

   Szoktak két egymás melletti portot úgy definiálni, hogy az elsõre kiírt érték a hardver elem egy regiszterét választja ki, aminek tartalmát a második porton keresztül lehet olvasni vagy írni. Ilyen megoldás van a CMOS elérésénél vagy a videokártyákon. Ilyenkor az elsõ port általában nem olvasható.

     Azt hiszem ennyi elég is volt a portokról, jöjjön a forráskód.

Lucifer of ZeroBit