ASSEMBLY GYAKORLAT 3. Irta Kaproncai Tamas [tomcat@szif.hu] -SZUBRUTINOK- 12a. Mindenki nezze meg az ASMGYAK2.TXT fajlt! Ebben benne van az elozo gyakorlat teljes anyaga es a hazi feladatok is. Komplett, teljes megoldast csak ket feladathoz adtam meg, azokat a programokat 12b. vagjuk ki egy tetszoleges szovegszerkesztovel es probaljuk ki oket! (Mig a diakok dolgoznak, addig kozben a tablanal...) Letrehoztam egy WEB oldalt a gyakorlat szamara, ennek cime: http://rs1.szif.hu/~tomcat/asm Itt a kovetkezo dolgokat talaljatok meg: o A gyakorlatok osszefoglaloit (ASMGYAK?.TXT) o A hasznalt programok teljes verzioit, forras programmal egyutt (NASM, VAL, DEBUG, TECHHELP, NASMIDE !!!) o Korabbi gyakorlataim peldait (nem pont ASM kezdo gyakorlatok voltak) o Egy internetes link gyujtemenyt (Interrupt lista, FAQ, tutorial, konyv stb.) 13a. A teglalap rajzolo programbol csinaljunk szubrutint! A szubrutinnak is, mint mindennek a leheto legegyszerubb formajat gyakoroljuk. Eloszor is kell a szubrutin neve, azt egy cimkebe irjuk: teglalap: A vegen lezarjuk a szubrutint: RETN (Ez mar ismeros, a DOS is hasonloan hivja meg a COM programunk). Egy szubrutin elott erdemes elmenteni a regiszterek erteket es a kilepes elott pedig visszatolteni a verembol az eredeti ertekeket. teglalap: PUSHA ; a verembe helyezi az osszes regiszter tartalmat PUSH ES ; kiveve a szegmens regisztereket ezert meg PUSH ES POP ES ; az elmentes sorrendjevel ellentetesen visszatoltjuk POPA ; a regiszterekbe az eredeti ertekeiket RETN Igy eleg lesz csak a foprogramot neznunk, mert a szubrutinok nem valtoztatjak meg a regiszterek ertekeit. A bemeno adatokat (parametereket) regiszterekben fogjuk atadni a szubrutinnak. Tetszolegesen valaszthatjuk meg a regisztereket, de ezeket utana illik a megjegyzes reszben felsorolni, hogy kesobb eloveve a szubrutijainkat, ne jelentsen gondot az ujboli felhasznalasuk. Ime a teglalap szubrutin: teglalap: ; BX: szelesseg PUSHA ; DX: magassag PUSH ES ; AL: szin ; DI: a bal-felso sarok memoriacime MOV CX,0B800H MOV ES,CX ; Azert CX-szel csinalom, mert AL foglalt! MOV CX,DX .ciklus1: ; ha egy cimke .-tal kezdodik, akkor az lokalis PUSH CX PUSH DI MOV CX,BX .ciklus2: PUSH CX MOV [ES:DI],AL ADD DI,2 POP CX LOOP .ciklus2 POP DI ADD DI,160 POP CX LOOP .ciklus1 POP ES POPA RETN Nezzuk, hogy kell ezt a szubrutint hasznalni, meghivni! Elszor feltoltjuk a megfelelo regisztereket a bemeno adatokkal, aztan CALL. MOV BX,40 ; 40 karakter szeles MOV DX,12 ; 12 karakter magas MOV AL,44H ; piros elol-hatul MOV DI,1 ; a kep bal-felso sark szinkodjanak mem.cime CALL teglalap Mivel az op.rendszer a COM fajlunk elso utasitasara adja ra a vezerlest, ezert a kesz program sorrendje a kov. 1. foprogram - benn a CALL - varakozas egy billentyu lenyomasara - es a kilepes a DOS-hoz 2. szubrutinok 13b. A szubrutinunk segitsegevel tegyunk a kep kozepere egy piros teglalpot kek keretben! 14a. A szubrutinunk segitsegevel rajzoljunk 8x8-as sakktablat! Egy mezo 6x3-as teglalp legyen! Eloszor mindenki 2 kulonbozo szinu 6x3-as teglalpot helyezzen el egymas melle! Ezt egy 4-es ciklussal ismetelve kirajzolhatjuk a sakk tabla egy sorat. A kovetkezo sort hasonloan kell megcsinalni, csak a szinek sorrendje lesz forditva. Ezt megint egy negyes ciklusba teve kesz a sakktabla! (Hagyjunk idot ennek gyakorlasasra es egyszer csak kozben...) Ez a feladat tipikusan olyan, amikor ket ertek kozott kell valtogatni. Egyeszer az egyik, egyszer meg a masik szinnel rajzolunk egy mezot. Erre a feladatra kihasznalhatjuk a XOR utasitas tulajdonsgat, azaz hogy egymas utan ketszer vegrehajtva ugyanazt az eredmenyt adja. Pl. MOV AL,33H ; AL = 33H XOR AL,11H ; AL = 22H XOR AL,11H ; AL = 33H XOR AL,11H ; AL = 22H XOR AL,11H ; AL = 33H Ha ezt kihasznaljuk, akkor a belso ciklusmagba eleg egy teglalap rajzolas es egy szinvaltas (XOR). Ha konkretan ertekek kozott szeretnenk a XOR utasitassal valtogatni, azt igy tehetjuk meg: XOR AL,44H^11H ; Ez a piros es a sotetkek szin kozott valt ; (Felteve, ha AL kezdeti erteke 44H vagy 11H) Ezek alapjan itt egy rovid megoldasa a sakktabla felrajzolasanak: (csak a foprogramot irom le) MOV BX,6 MOV DX,3 MOV AL,44H MOV DI,1 MOV CX,8 cikl1: PUSH CX PUSH DI MOV CX,8 cikl2: PUSH CX CALL teglalap ADD DI,2*6 XOR AL,44H^11H ; Szin cserelese minden mezo kirajzolasa utan. POP CX LOOP cikl2 POP DI ADD DI,160*3 XOR AL,44H^11H ; Megegyszer kell szint valtani, mert a kov. ; sor ugyanolyan szinu mezovel indul. POP CX LOOP cikl1 MOV AH,0 INT 16H MOV AX,4C00H ; Kilepni a DOS-hoz igy is lehet a 4CH DOS INT 21H ; funkcio meghivasaval, ilyenkor AL erteke ; a DOS-nak visszaadott hibakodot fogja megadni 15a. Irjunk egy masik szubrutint, egy sztring kiirot! Ehhez eloszor nezzuk, hogyan lehet eltarolni egy stringet... A programban tarolt adatainkat a szovegfajlunk vegere fogjuk elhelyezni, hogy konnyen megtalaljuk oket. (A legelejen persze nem is lehetnenek, mert ott a foprogram lesz. Ha odairnank az adatokat akkor a processzor utasitasoknak probalna meg ertelmezni, es abbol nem sok jo sulne ki). A memoriavaltozonak, vagy adatnak adunk egy nevet (cimket) es DB utan irjuk az erteket, ha adatunk bajtos: szoveg: DB 17 (Ebben az esetben a : el is hagyhato). Ekkor egy 17-es erteku bajtot fog a fodito a COM fajlunk vegen elhekyezni. Felsorolhatunk tobb adatot is: szoveg DB 10,13 Irhatjuk erteket ASCII kodokkal is: szoveg DB 'A','B' De a sztringet irhatjuk egybe is, es a sztringunket zarje le egy 0 erteku bajt: szoveg DB 'Hello!',0 Irjuk meg a szubrutint is: strki: ; SI: a sztring memoria cime PUSHA ; DI: a szoveg kezdo pozicioja a kepen PUSH ES MOV AX,0B800H MOV ES,AX .ujra: MOV AL,[SI] ; Egy karaktert beolvas a sztrinbol, INC SI ; lep a sztrin kov. karakterere. CMP AL,0 ; Megvizsgaljuk, hogy a karakter nulla-e, JZ .vege ; ha igen akkor ugras a szubrutin vegere. MOV [ES:DI],AL ; Kiirjuk a beolvasott karaktert a kepre, ADD DI,2 ; lepes a kovetkezo karakterre a kepernyon. JMP .ujra ; Feltetel nelkul ugras az iteracio elejere. .vege: POP ES POPA RETN Vegul a foprogram: ORG 100H ; Ez egy fontos sor, amit az adatok pontos cimenek kiszamolashoz kell ; beirni a forditonak. A COM programunk a 100H offset cimen indul. MOV SI,szoveg ; A kiirando sztring mem.cime MOV DI,0 ; A kepernyo bal-felso sarkanak cime CALL strki MOV AH,0 INT 16H MOV AX,4C00H INT 21H Megegyszer emlekeztetoleg az egyes reszek sorrendje: 1. foprogram 2. szubrutinok 3. adatok 15b. Piros keretben a kepernyo kozepere irjuk ki, hogy hello! Kell egy CALL teglalap es egy CALL strki. Lathatjuk, hogyha az embernek vannak mar elore megirt szubrutinjai, akkor konnyen latvanyosabb programot is el tud kesziteni. Ezeket a szubrutinokat erdemes egy kulon fajlba osszegyujteni es minden olyan programba ami hasznalja oket, egyszeruen csak 'beincludolni'. Azaz pl. a rutinokat elhelyezem egy kulon fajlban: RUTINOK.INC (A kiterjesztes is tetszoleges lehet), es a foprogram utan, oda ahol a szubrutinoknak a helye van beirom ezt a sort: %INCLUDE "rutinok.inc" Ezzel azt erem el, mintha az osszes rutint belemasoltam volna a prgramomba a megadott helyre. 15c. Probaljuk ki az %INCLUDE lehetoseget! 15d. strki helyett a DOS string Alapveto funkciok persze megvannak a BIOS-ban vagy a DOS-ban is. Igy pl. sztringet kiirni a DOS-szal szokas. - A funkcio szama a 9H - A sztring cime a DX-be kerul - A sztringet '$' jel zarja le!!! Ime a sztring kirasa DOSszal: ORG 100H MOV DX,szoveg MOV AH,9 INT 21H RETN szoveg DB 'Hello!',7,10,13,'$' Ezzt kiprobalva latszik, hogy a DOS a 32-nel kisebb kodu karaktereket vezerlo kodoknak tekinti. Igy peldaul a 7-es hatasara sipolni fog egyet. Az altalunk irt strki viszont a 7-es karakter jelet is megejelenitene. Gyakorlaskent feladom a kov. feladatokat ======================================== 16a. Irjunk olyan ablak rajzolo szubrutint, aminek duplavonalas kerete van. Segitsegkent felhasznalhato az ASMGYAK2.TXT keretrajzolos programja. 17a. Irjunk szam kiiro szubrutint. Ez hasznalhatja a sztringkiiro rutinunk. Eloszor stringge kell konvertalni a szamot. Legyen a szamunk AX regiszterben! Elos lepes, hogy egy szamjegyet levalasztunk, ezt a 10-zel valo osztassal erjetjuk, a kerdese szamjegy a maradek (DX) lesz. Ebbol az egy jegybol ugy csinalhatunk konnyen karaktert, ha hozzaadjuk a 0 ASCII kodjat: ADD DL,'0' Ha egy karakter magvan, akkor azt eltaroljuk a sztring vegere, es ha a hanyados (AX) meg nem nulla az osztast iteraljuk. Megoldasok ========== 17a. Irjunk szam kiiro szubrutint. Ez hasznalhatja a sztringkiiro rutinunk. ORG 100H MOV AX,12345 ; a kiirando szam, pl. 12345 MOV DI,0 ; a kiiras helye CALL szamki MOV AH,0 INT 16H MOV AX,4C00H INT 21H %INCLUDE "rutinok.inc" szamki: ; AX: a kiirando szam erteke PUSHA ; DI: a kiiras kepernyo pozicioja MOV SI,szamstr + 4 ; az utolso szamjegy helye a sztringben .ujra: MOV BX,10 ; 10-es osztassal valasztunk le egy jegyet MOV DX,0 ; DX:AX az osztando szam, BX az oszto DIV BX ; hanyados -> AX, maradek -> DX ADD DL,'0' ; a kapott szamjegy karakterre alakitasa MOV [SI],DL ; egy karakter beirsa a sztringbe DEC SI ; lepes a kovetkezo jegy mem.cimehez CMP AX,0 ; Van meg mit osztani? JNZ .ujra ; ha igen, akkor ujabb iteracio INC SI CALL strki ; sztring kiiras POPA RETN szamstr DB ' ',0 ; helyfoglalas a sztringnek (min. 5 karakter).