HTML

Az élet kódjai

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

Friss topikok

Tanuljunk assemblyt - kicsit máshogy

2019.09.23. 22:58 Travis.CG

Az X86 assembly programozás is olyan volt számomra, hogy többször belekezdtem és valahol megszakadt a tanulási folyamat. Többségében azért, mert nem tudtam átverekedni magam az unalmas bevezetőkön. Szerettem volna mindjárt valami látványosat alkotni, de a könyvek csak a processzorok történetével, memória felépéítéssel és minden mással foglalkoztak.

Természetesen ez érthető, mivel  az assembly programozáshoz ismerni kell a gép felépítését. Nincs lehetőségünk magas szintű eljárásokat használni, ezért még az olyan egyszerű feladatok is, mint amilyen a képernyőre történő írás, komoly kódolást igényel.

A könyvek tehát logikusan vannak felépítve, de oktatás metodikailag nem megfelelőek. Nem adnak siker élményt, nem sarkallják az embert arra, hogy megismerjék a nyelvet. Hiszen ki akarna assemblyben szenvedni és több oldalon keresztül arról olvasni, hogyan kell két számot osztani? (Különösen, hogy a matematikai társprocesszor jó ideje ott csücsül a gépekben) Hol marad az öröm, hogy valamit sikerült elérni?

Ezért én megpróbálok írni egy tutorialt, aminek nem az a célja, hogy mindent megismertessek, ami az assembly programozáshoz nélkülözhetetlen, sokkal inkább kedvcsináló legyen, hogy olyan hangosan énekeljünk, mint Tom Hanks, amiért sikerült tüzet gyújtania.

Ami kelleni fog, az egy FreeDOS. Miért? Először is, megvan benne minden, ami nekünk kell: szöveg szerkesztő, assembly fordító, és könnyű hozzáférés a grafikus képernyőhöz. Igen, ez a másik előny. Míg egy modern operációs rendszeren eszetlenül sok dolog kell, hogy egy egyszerű pontot kitegyünk a képernyőre, addig FreeDOS alatt pár sor assembly kódból ez megvan. Más szavakkal: rajzoláson keresztül fogjuk megismerni az assemblyt, ami szerintem király. Gyakorlatilag ezt csinálják 256b intrókban is, ezért nyugodtan mondhatjuk, hogy ez egy intró tutorial is egyben.

A NASM fordítót fogjuk használni. Először is, mert szerintem tisztább a kód, mint amit a GNU Assemblernek kell adni, másrészt a legtöbb 256 byte intró is ezt használja.

vi gyorstalpaló

Ebben a cikkben a vi szövegszerkesztőt használjuk. A vi nagyon egyszerű, de szépen kiszínezi a forrás fájlunkat, ami elég látványos. Ha nem ismersz semmilyen szövegszerkesztőt FreeDOS alatt, akkor itt egy rövid leírás, ami elég arra, hogy nagyon alapszinten használni tudd.

Elindítani az c:\elvis\vi paranccsal lehet. Mivel nincs menü rendszere, ezért a parancsokat be kell gépelni a vi-nek. Amikor parancsokat gépelünk, az meglepő módon a parancs mód. Amikor elindul a szövegszerkesztő, akkor parancs módban van. Ha lenyomjuk az i billentyűt, akkor szerkesztő módban kerül, szerkeszthetjük a fájlokat. Ha vissza akarunk térni parancs módba, akkor az esc billentyűt kell lenyomni. Ha nem tudod, milyen módban vagy, nyomd le az esc-t. Ha szerkesztő módban vagy, átvált parancs módba, ha parancs módban vagy, nem történik semmi.

Szerkesztés közben egyedül a backspace nem működik. Törléshez sajnos csak a del gombot tudjuk használni. Ezt természetesen lehet módosítani, de mivel ez egy gyorstalpaló, ezzel nem foglalkozunk. Csak jegyezd meg, hogy a del a törlés. Minden más úgy működik, ahogy a többi szövegszerkesztőnél.

Ha végeztél a szerkesztéssel és ki akarsz lépni, akkor a következő gombokat kell lenyomni. Ebben a sorrendben: esc : w q enter. Szóközök nélkül. Ezzel belépsz parancs módba, elmented a munkádat és kilépsz a programból. Gyakorlatilag ez a minimális tudás, ami a program használatához kell. Ha többet akarsz megtudni, akkor a neten rengeteg leírás található.

De ha ez túl bonyolult, az edit paranccsal is lehet szöveget szerkeszteni. Ekkor vannak menük, de nincs kód színezés.

Beállítások

Ha telepítettük a FreeDOS-t, akkor két beállítást javaslok. Két könyvtárat rakunk az elérési útba, hogy használhassuk onnan a programokat. A c:\autoexec.bat fájlban a SET PATH sor végére írjunk két könyvtárat:

SET PATH=%dosdir%\BIN;c:\elvis;c:\devel\nasm

Ezzel két legfontosabb programunkat, a szövegszerkesztőt és a fordító programot bárhonnan el tudjuk érni.

Váz

Azért, hogy minél egyszerűbb legyen a dolgunk, COM fájlokat fogunk készíteni. Ez a legegyszerűbb bináris futtatható fájl, amit csak el lehet képzelni. Minden fájl a következő módon épül fel:

org 100h
section .text
start:
section .data
section .bss

Négy részből épül fel, amit a section kulcsszóval definiálunk. A text a forrás állomány lesz. A data, ami olyan, mintha konstansok lennének egy magasabb programozási nyelvekben. A bss pedig a nem inicializált memória terület, vagyis változók. Ez csak váz, ha lefordítjuk, nem kapunk semmi értelmeset. Lépjünk is tovább.

org 100h
section .text
start:
    ; Set video mode
    mov ax, 13h
    int 10h
    ; Set base address
    mov ax, 0A000h
    mov es, ax
    ; Set screen coordinate and colour
    mov di, 150
    mov dl, 7
    mov [es:di], dl
    ; Back to DOS
    mov ax, 3
    int 10h
section .data
section .bss

A programot a következő módon fordíthatjuk, feltéve, hogy minisc.asm a fájl neve:

nasm -fbin minisc.asm -o minisc.com

Ha futtatjuk, a gép sebességétől függően nem történik semmi látható. Ha olyan tetü lassú gépet használunk, mint amilyet én, akkor egy pillanatra látszik, ahogy átvált grafikus módba.

Mi is történik? Két utasítást látunk: mov és int. Az int az egyszerűbb, azzal kezdem. Egy megszakítást generál. A megszakítás olyan, mint egy API hívás. A BIOS vagy a DOS megcsinál helyettünk valamit. Nem kell bonyolult dologra gondolni, mert csak egyszerű dolgokat kérhetünk (lévén, hogy egy egyszerű operációs rendszert használunk). Pl. billentyűzet lenyomást, képernyő felbontás váltás, stb. A 10h egy BIOS megszakítás, ami a képernyőt kezeli. Beállíthatjuk a képernyő módot, karaktereket írhatunk, de akár a fényceruza pozícióját is megtudhatjuk. Aki nem tudja, hogy ez utóbbi micsoda, ne is akarja tudni. Örüljetek, hogy van érintő képernyő.

Hogyan lehet ennyi különböző funkciót rendelni egyetlen megszakításhoz? Kell, hogy legyen valami paraméterezés. Van is, amit a regisztereken keresztül érhetünk el. A regiszterek olyanok, mint a globális változók. És ezzel el is érkeztünk oda, miért nem szeretik sokan az assemblyt. Míg a magasabb programozási nyelveknél nem szabad globális változókat használni, kerülni kell a goto utasítást, addig a gép processzorának legmélyén ezeket az elveket hírből sem ismerik. A káoszt csak erősíti, hogy az assembly utasítások folyton ezeket a regisztereket figyelik és ide irkálnak mindenfélét. Aki ezeket mind megtanulja, ki fogja ismerni magát az asm kódokban.

A programozás nagy részében ezekbe a regiszterekbe fogunk pakolni értékeket mi is, ezért a második utasítás, amivel megismerkedünk, a mov. Az első parancsnál is, az AX regiszterbe 13h-t rakunk, amitől a megszakítás után a BIOS tudni fogja, hogy a képernyőt 320x200-as felbontásba akarjuk kapcsolni. Ez azért jó, mert ha a memória egy dedikált helyére adatokat pakolunk, akkor az megjelenik a képernyőn. Ezért a programunkban, amíg vissza nem kapcsolunk karakteres módba, csak mov utasítást használunk.

Ez a dedikált memória hely az 0A000h. Erre kell beállítani az ES regisztert. Mivel az ES regisztert közvetlenül nem állíthatjuk be (ne kérdezzétek, miért), ezért először az AX regiszterbe pakoljuk az értéket és onnan az ES-be. Ez a memória terület folytonos, vagyis a képernyőn a sor végét elérve a következő sor elejére ugrunk. Sőt, mivel ez a terület egyetlen szegmens, ha elértük a képernyő alját, a tetején jelenünk meg újra. Ezt az intrók előszeretettel ki is használják.

Az offsetet, vagyis az alap memóricímtől való eltérést, és ezen keresztül a pozíciót a DI regiszterben állítjuk be. Amit ezen a memóriacímen beállítunk, az színként jelenik meg a képernyőn. (Kicsit zavaró lehet, hogy a DL regisztert használjuk, ami igazából a DX regiszter, csak az egyik fele. Az alsó fele, hogy pontosak legyünk.)

Oké, de még mindig nem látjuk a pontot a képernyőn. Ha már úgyis a GOTO-t emlegettük, mi lenne, ha visszaugranánk a rajzolás előtti részre?

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

Szuper, látszik a pont. Igaz, ha eleget gyönyörködtünk benne, akkor újra kell indítani a gépet, de akkor is látszik. Az új parancs a jmp, amivel egy címre tudunk ugrani. A DOS-ba való visszatérés igazából itt felesleges, mert egy végtelen ciklust készítettünk.

Elég sok mindent nem érintettünk, de 16 sorból rajzoltunk valamit. A részleteket meghagyom a könyveknek. Viszont van egy keretrendszerünk, amit fejleszhetünk és nem kell a debuggerben nézni, hogyan változnak a regiszterek.

Szólj hozzá!

Címkék: programozás demoscene

A bejegyzés trackback címe:

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

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