A programozás oktatásának speciális területe a gépi kódú programozás oktatása. A valódi processzoron alapuló utasításismertetés a számos különböző típusú és működésű processzor miatt nem lenne célszerű. A programozás iránt fokozottabban érdeklődő és az informatikát érettségi tárgyként választó diákok számára viszont szükséges e terület alapszintű oktatása.
Megállapodások
A gép korlátait célszerű elsőként egyértelműen meghatároznunk. Az egyszerűség kedvéért egész számokkal végzett műveletek elvégzésére legyen csak képes. Ugyancsak egyszerűsítés, hogy a gép maximum két operandusú, azaz az utasítások mögé egy vagy két érték kerülhet, egy regiszter vagy egy memóriacím. A regisztereket a betűk, míg a címeket a számok jelzik.
Első lépés annak a gépmodellnek a megalkotása, amelyen végrehajtjuk a gépi kódú programot. A regiszterek igen fontosak. A legegyszerűbb gép a kétregiszteres. Szabadabb programozást - és így kevesebb utasítást - tesz lehetővé, ha gépünk 8 regisztert tartalmaz, de kitüntetett szerepű lesz az első kettő, ami az X és Y nevet kapja.
A maradék hat regiszter A-tól F-ig kap betűjelet.
X | Y |
A | B |
C | D |
E | F |
Utasítások
A versenyfeladatban megadott pár utasításon kívül célszerű még újabbakat is felvennünk. Tekintsük át a szükséges utasításokat!
Matematikai műveletek
A matematikai műveletek közül az alapműveleteket célszerű elsőként megadni. Az egyszerűség kedvéért megállapodunk abban, hogy az eredmény az első operandusként megadott regiszterben képződik. A négy alapműveletet feltétlenül célszerű megadni, amelyek mindegyike kétoperandusú: az összeadás ADD reg reg, kivonás SUB reg reg, a szorzás MLP reg reg nem tér el az alapértelmezéstől. Az osztás DIV reg reg művelete viszont a maradék nélküli egész osztást jelenti, ami jobban lesz hasznosítható, és persze egész eredményt ad.
Az alapműveletek mellett célszerű lesz további két additív utasítást is bevezetni a számlálásos ciklus elkészítéséhez. Ez a regiszter tartalmának eggyel való növelése és csökkentése: INC reg és DEC reg nevet kapja.
Mozgatások
A regiszterek és a tárak között adatmozgatást a valódi gépi nyelvek számos utasítással oldják meg. A modellünkben elegendő lesz ehhez egyetlen MOV reg reg utasítás, amely az elsőként megadott regiszterbe átmásolja a második regiszterben lévő értéket. A regiszterek és a memória közötti adatmozgatást is megvalósíthatjuk egy bővített modellben, de ezt most egyelőre elhagyjuk.
Adat be- és kivitel
Az adatok bevitelére a billentyűzetről közvetlenül a regisztereket használjuk, a kivitelére egy kiíró rekeszt. Az INP reg utasítás beviteli ablakon keresztül olvas be, az OUT reg utasítás a kiírásra szolgáló regiszterbe másolja a regiszterből az értéket. Egyszerűbb, ha a beolvasást egybevonjuk az értékbeírással, és INP utasítást használhatjuk INP reg érték formában is. Hasonlóan célszerű engednünk egy olyan kiírási módot is, amely nem egy regiszterből másol ki, hanem közvetlenül az utasítás mögé írt szöveget íratja ki, azaz az OUT érték is használható lesz. A kiíratható értékek listájában szerepelnek az IGEN/NEM, IGAZ/HAMIS, 0/1 párok.
A fenti utasítások már elegendőek ahhoz, hogy egy beolvasott szám 15-szörösét vagy éppen hatodát képezzük.
- Készítsünk programot, amely kiírja egy beolvasott szám 12-szeresét! (Eredeti feladat)
Ugró utasítások
Ennyi előkészület után már tudunk írni egyszerűbb lineáris programokat, ahogy azt a versenypélda is tartalmazta, de nincs még módunk ciklus szervezésére. A feltétel nélküli ugró utasítás az első, amire a hurokképzéshez szükségünk lesz. Ez a GTO cím feltétel nélküli ugró utasítás lesz, ami mögött egy memóriacím áll.
Az elágazás megoldásához szükség lesz két különböző feltételes ugró utasításra is. Egyik azt vizsgálja, hogy két regiszter tartalma egyenlő-e, a másik pedig azt, hogy az első nagyobb-e mint a második. Ezek az utasítások a feltétel igaz volta esetén ugrást eredményeznek egy megadott címre. Ez a kétoperandusú utasításformában úgy oldható meg, ha két előre meghatározott regiszterrel végezzük az összehasonlításokat, azaz nem kell azokat külön megadni. Ezek legyenek az X és Y regiszterek. Az egyenlőséget vizsgálja a JMP cím, míg az X nagyobb Y-nál vizsgálatát a SIG cím nevű utasítás végezze el.
Az ugró utasítások már sokkal nagyobb szabadságot adnak, és érdekesebb feladatok megoldását is lehetővé teszik.
- Készítsünk programot, amely kiírja két szám minimumát!
- Készítsünk programot, amely egy beírt szám abszolútértékét írja ki!
- Készítsünk olyan programot, amely ellenőrzi, hogy három megadott szám lehet-e egy háromszög három oldala! Írjunk ki IGEN-t vagy NEM-et válaszként!
- Készítsünk programot, amely két szám legnagyobb közös osztóját írja ki!
A későbbiekben hasznos lesz az ismétlődő utasítások szubrutinként való kezelése, azaz a kisebb programrészletek meghívása. A megvalósításként a GSB cím és a RET nevű utasításokat használjuk. A szubrutinhívás feltételezi azt, hogy a számítógépünk rendelkezik egy olyan veremmel, amely segítségével a szubrutinhívás helyére való visszatérést megoldhatjuk. Újabb egyszerűsítésként a gépünk működjön úgy, hogy csak a meghívás címét tároljuk el, és a regiszterek tartalmát nem, azaz a regiszterek tartalma globális változóként működik, nem ürülnek ki a meghíváskor, és persze nem is tárolódnak el, a szubrutin is módosítja azokat. A visszatérés RET utasítása a GSB címe után soron következő utasítás címére adja át a vezérlést, a regiszterek a megváltozott tartalommal működnek tovább. Pusztán technikai okok miatt ötre korlátozzuk a verem méretét.
- Készítsünk programot, amely euklideszi algoritmust végez!
- Készítsünk programot, amely megállapítja, hogy egy szám prím-e vagy sem!
A fenti utasítások kiegészítésére van mód, számos más utasítással is végezhetünk műveletet, de ezek az alaputasítások gyakorlatilag már minden egyéb utasítást megvalósíthatnak, ha kellő módon készítjük el ezekből.
A következő cikkben a feladatok megoldásával foglalkozunk.
Melléklet
- Comenius Logo program, amely alkalmas a fenti utasítások beolvasására és végrehajtására (gep.lgp, 1.0 verzió).