HTML

Az élet kódjai

Csináld maga. Senki nem csinálja meg helyetted.

Friss topikok

Tanuljunk assemblyt - kicsit máshogy 2. rész

2020.01.19. 22:11 Travis.CG

Az előző részben sikerült egy pixelt kigyújtani a képernyőn. Szép teljesítmény, de elég sokat kellene gépelni, ha valami összetett ábrát akarunk látni, nem igaz? Szerencsére nincs is rá szükség, mert a programozás tele van olyan nagyszerű elemekkel, mint a ciklusok, vagy a feltételek.

De előtte rajzoljuk tele a képernyőt. A megoldás nagyon hasonlít az előzőleg bemutatott kódra, de van benne egy plusz utasítás. Az inc. Ez nem csinál mást, mint eggyel növeli az adott regiszter tartalmát. Párja, a dec, csökkenti azt. Ha tehát minden egyes ugrás után megnöveljük a memóriacímet, ahova rajzolunk, elboríthatjuk fénylő pixelekkel a képernyőt. Rajta, ne tétovázzunk!

   org 100h
section .text
start:
   mov ax, 13h
   int 10h
   mov ax, 0A000h
   mov es, ax
draw:
   mov dl, 7
   mov [es:di], dl
   inc di
   jmp draw
section .data
section .bss

A program végtelen ciklust hajt végre, soha nem jut el a jmp utáni kódrészletig. Persze, ez még mindig csak számítások egymásra hányása. A rendszer ugyanis túlcsordul, de ez nem hibaként jelentkezik, hanem azzal, hogy újból rajzolni kezd az elejéről. Ugyan azzal a színnel. Mit is mondunk az ilyen képre? Uncsi! Mi lenne, ha egy cilkust használnánk?

A ciklus megvalósítása nem nehéz. A loop utasítás segítségével visszaugorhatunk egy korábbi címre. A ciklus számlálója az CX regiszter. Amíg a regiszter nagyobb, mint egy, a loop visszaugrik. Tehát egy 10 lépéses ciklust a következő módon hozhatunk létre:

   mov cx, 10
for:
   ; instructions
   loop for

Kiváló! Sikerült felülkerekedni a jmp hátrányain! De ha kicsit belegondolunk, a szívünk összeszorul. Elhasználtunk egy csomó regisztert! Már nincs AX, nincs BX, ha ciklusokat akarunk használni, le kell mondani a CX-ről. A programunk komplexitása szinte a zérón áll, és máris elhasználtuk a regisztereket. Hol vagyunk még az Unreal Engine összetettségétől?

Nem kell aggódni, mert még alig használtuk gépünk memóriáját. Ott van például a stack (vagy verem). Ez pont olyan, mint a "Fontos!" feliratű doboz a munkahelyemen. Ha kapok egy fontos papírt, akkor azt oda teszem. Kapok még egyet, rárakom az előzőre. Aztán gondolok egyet, hogy most fontos dolgokkal kellene foglalkoznom, és kiemelem a legfelső papírt a dobozból, és elvégzem, ami rajta van.

Ez az analógia annyira jól működik, hogy ha nem dolgozom fel elég gyorsan a fontos dolgokat, akkor pontosan ugyan az történik velem is, mint a számítógéppel. Megtelik a verem. (Ekkor kapjuk a híres stack overflow hibaüzenetet.)

Két utasítással kezelhetjük a stack-et. Ez a push és a pop. Előbbivel egy regiszter értékét menthetjük oda, másodikkal az ott található értéket helyezhetjük el egy regiszterben. Ha tehát két ciklust akarunk egymásba ágyazni, akkor a CX regiszter mentéséről magunknak kell gondoskodnunk a stack segítségével. Nem kell lefoglalni a memóriát, vagy ellenőrizni, ez mindig hűségesen a rendelkezésünkre áll.

   org 100h
section .text
start:
   mov ax, 13h
   int 10h
   mov ax, 0A000h
   mov es, ax
   mov cx, 64000
cycle1:
   mov di, cx
   push cx
   mov cx, 256
cycle2:
   mov dl, cl
   mov [es:di], dl
   loop cycle2
   pop cx
   loop cycle1
   mov ax, 3
   int 10h
section .data
section .bss

A program telerajzolja a képernyőt, de lassabban, mert minden egyes pozícióban 256-szor megváltoztatja a képpont színét. De a végeredmény továbbra is egyszínű képernyő. Ezen sürgősen változtatni kell! Mi lenne, ha az elejét és a végét más színnel rajzolnánk?

Természetesen megtehetnénk, hogy két ciklust készítünk, de akkor kétszer kell leírni a kirajzoló rutint is. Inkább egy vizsgálat kellene. Ha a képernyő elején vagyunk, átállítjuk a rajzolás színét (esetünkben a dl regisztert). A vizsgálatotokat több utasítás alkalmazásával tudjuk megvalósítani. Először a cmp utasítás megvizsgálja, hogy két érték egyenlő-e, és beállít további regisztereket (most mindegy, hogy melyeket). Aztán egy másik utasítás a regiszterek alapján ugrik az általunk megadott címre. Ezért annyi ugró utasítás van, ahányféle összehasonlítás. Én csak hármat mutatok be. A je ugrik, ha a két érték egyenlő. jb akkor fog ugrani, ha a cmp-ben használt kifejezés bal oldali mennyisége kisebb, a ja utasítás pedig akkor, ha nagyobb. Módosítsuk a jmp-s példát, hogy mindez világos legyen:

draw:
   mov dl, 2 ;green colour
   cmp di, 8000
   ja set
   mov dl, 12 ;red colour
set:
   mov [es:di], dl
   inc di
   jmp draw

Beállítjuk a színt zöldre, majd megnézzük, hogy a pozíció kisebb-e 8000-nél. Ha nagyobb, ugrunk a kirajzolásra. Ha nem nagyobb, akkor az ugrás nem valósul meg, a szín piros lesz. Most már tudunk készíteni egy programot, ami nem uncsi. Kirajzolhatjuk a Magyar zászlót.

draw:
   mov dl, 2 ;green
   cmp di, 21119
   ja iftwo
   mov dl, 12 ;red
   jmp set
iftwo:
   cmp di, 42239
   ja set
   mov dl, 15 ;white
set:
   mov [es:di], dl
   inc di
   jmp draw

Először megnézzük, hogy a pozíció nagyobb-e 21119-nél. Ha nagyobb, ugrunk a második összehasonlításra. Ha nem, beállítjuk az első színt és ugrunk a kirajzolásra. Ha nem így tennénk, a program végrehajtaná a második összehasonlítást is. Majd hasonló logikával jön a második feltétel. Bonyolult? Ha a válasz igen, akkor ideje megszeretni a GOTO-t, mert alacsony szinten ez a király. Nagyon sok mindent nem érintettem a posztban, de ennek az ismertetőnek nem is célja, hogy mindent bemutassak. A cél az érdeklődés felkeltése.

Ezért, akinek van kedve, elgondolkodhat azon, hogy az utolsó példánál át lehet-e rendezni úgy a vizsgálatokat, hogy ne legyen szükség az első jmp utasításra.

Szólj hozzá!

Címkék: programozás demoscene

A bejegyzés trackback címe:

https://cybernetic.blog.hu/api/trackback/id/tr9315412576

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása