Assembly programozás gyakorlat 2011

Gyakorlati számonkérések időpontjai

Kis ZH-k: 5. hét (február 28.), 8. hét (március 21.), 11. hét (április 11.), 12. hét (április 18.)

Nagy ZH: Április 29. 08:00 óra. Helyszín: TIK kongresszusi terem.

1. Gyakorlat

Számrendszerek
Számok konvertálása 2-es, 10-es, 16-os számrendszerek között. Pl:
77d = 100 1101b = 4Dh
185d = 1011 1001b = 0B9h
BEDh = 1011 1110 1101b = 3053d 

19,625d = 1 0011,101b
114,25d = 111 0010,01b
Hány különböző szám fejezhető ki n darab bináris számjegyen?
Helyik a legnagyobb?
Ha r az alap?
Műveletek
Összeadás, kivonás 2-es, 16-os számrendszerben.
Negatív számok: 1-es, 2-es komplemens.
Memóriakezelés
Szegmens: offszet címzés: Lineáris cím = segm * 16 + offs.
segm:1272h  ===> *16  ===>    12720h
offs:1a3bh                   + 1a3bh
                             -------
                              1415bh    lineáris cím
Egy lineáris címnek hány logikai (szegmens:offszet) címe van?
Mondjunk olyan logikai címeket, melyek az 12345h lineáris címre mutatnak! Mi a helyzet a 0ffffh:0010h címmel?
Mi a különbség a lineáris cím és a fizikai cím között?
Címzés
Kódba épített adat
Címzés: [BX v. BP] + [SI v. DI] + [rel8 v. rel16]
Alapértelmezett szegmens: DS, vagy BP használata esetén SS. Szegmens felülbírálással CS, DS, ES, SS elérhető. Alternatív jelölésmódok: [BX][SI], vagy 04h[BX]
Címzések
Melyik címzés helyes és melyik nem?
[12h+56h]
ES:[09D3h]
[123456789ABCh] 
[SI+DI]         
[IP]            
[SI-500d]
[AX]            
SS:[BX+DI+1999d]
[CX+1234h]      
[SP+BP]         
DS:[BP+SI]
IP:[0000h]      

2. gyakorlat

Turbo Debugger
Csomagold ki a tasm.zip állományt egy tetszőleges könyvtárba. A td.exe-t kell elindítani.
MASM
A MASM elérhető a kabinetes gépeken. A MASM használata.
Összeadas
Tegyük fel hogy a következő példákban az adatszegmensünk így néz ki:
ds:0000 CD 20 FF 9F 00 9A F0 FE
mov       al, [0]         ;al=CD
mov       ax, [0]         ;ax=20CD    Bájtsorrend!!
mov       ax, 5h         ;ax=0005h
add       al, 0001h      ;ax=0006h
mov       ax, 5h
add       al, [0001h]    ;ax=0025h
mov       ax, 5h
mov       bx, 6h
add       ax, bx         ;ax=000Bh
mov       ax, 5h
mov       bx, 6h
add       ax, [bx]       ;ax=FEF5h
Adjunk össze egy 8 bites előjeles számot és egy 16 bites előjeltelen számot! Például a -10d-t és a 2525d-t.
mov al, -10d             ;al=0f6h
mov bx, 2525d            ;bx=09ddh
cbw                      ;ax=0fff6h
add ax, bx               ;ax=09d3h
Szorzás
mov       ax, 0102h
mov       cx, 0003h
mul       cl             ;ax=0006h
mov       ax, 0102h
mov       cx, 0003h
mul       cx             ;dxax=0000 0306h
mov       ax, 0202h
mov       si, 0003h      ;ds:0003= 9fh
mul       byte ptr [si]  ;ax=013eh
mov       ax, 0602h
mov       si, 0003h      ;ds:0003= 9f 00h
mul       word ptr [si]  ;0602h*009fh = 0003 bb3eh
Előjeles szorzás:
mov       al, -2d        ;al=0feh
mov       cl, 3d         ;cl=03h
imul      cl             ;ax=fffah
Szorozzunk össze egy 8 bites előjeles, ill. egy 16 bites előjeles számot! Például a -2d-t és a -520d-t.
mov       al, -2d        ;al=0feh
cbw                      ;ax=0fffeh
mov       cx, -520d      ;cx=0fdf8h
imul      cl             ;dxax=0000 0410h azaz 1024d

3. gyakorlat

Feladat
Írjunk egy programrészletet, amely kiszámolja az alábbi kifejezés értékét! Feltesszük, hogy minden regiszter előjeltelen számot tartalmaz és minden művelet eredménye elfér 16 biten. Az eredményt tároljuk ax-ben.

(cx + ax ) * bx
bx * dx + ax
ax * ax + bx * bx
Gyakorlás
Legyen a 8 bites előjeles (pl. -2), b 16 bites előjeles (-3), és c 8 bites előjeltelen (130d) szám. Adjuk össze őket!
Osztás
mov       ax, 0007h
mov       cx, 0003h
div       cl          ; ax= 0102h
Osszuk el a 1234h-t 00h-val! Mi fog történni?
Osszuk el a 1234h-t 03h-val!
Feladat
Legyen a és b 8 bites előjeltelen, c pedig 16 bites előjeles. Számoljuk ki a (a*b + c) / b kifejezést!

4. gyakorlat

Feltételes ugrások
Számoljuk ki a következő kifejezés értékét! Az eredményt helyezzük AX regiszterbe!
AX := min( a*c , a+b )
adat  segment
  a     db 4  ;elojeltelen
  c     db 3  ;elojeltelen
  b     dw 9  ;elojeltelen
adat  ends    
Oldjuk meg a feladatot előjeles számokra is! További kifejezések:
AX := max(a+b, a+c)
AX := mid(a,b,c)
AX := (a+b) == c ? a : b+c
AX := abs(a+b)

5. gyakorlat

Üres assembly program
Az üres assembly program nem tartalmaz mást, mint azokat a kötelező utasításokat, amelyek a program elindulásához és befejeződéséhez kellenek.
Sztring hossza
Számoljuk meg, hogy milyen hosszú egy sztring! Tegyük fel, hogy a sztringet a 0 karakter zárja. Az adatszegmensünk a következő:
adat  segment
  hahostr   db "Haho !", 0
adat  ends
A teljes forráskód letölthető innen.
Turbo Debugger
Turbo Debugger (TASM) használata. Ahhoz hogy a Debuggerben a forrásprogramunkat is lássuk, a következőképpen kell a fordítást és a linkelést végezni (%1 a forrásfile neve kiterjesztés nélkül)
tasm /zd %1.asm
tlink /v %1.obj
Debuggolás: td.exe
MASM
A MASM elérhető a kabinetes gépeken. A MASM használata. A fordítás menete MASM használatával:
masm %1.asm,,,,
link %1.obj,,,,
Debuggolás: debug
Feladatok
Oldjuk meg az alábbi feladatokat a sztring hossza program átírásával!
  1. Számoljuk meg, hogy hány darab "a" betű van egy karakterláncban!
  2. Cseréljünk le egy string minden "a" betűjét "b" betűre.
  3. Titkosítás: Cseréljünk ki minden betűt (A-Z, és a-z) az "x" betűre, az egyéb karaktereket hagyjuk meg.
  4. Cseréljünk le egy string minden kisbetűjét nagybetűre (UPPER CASE). Mit kell módosítani a programon, hogy a nagybetűkből legyenek kisbetűk? (lower case)
  5. Invetáljuk a kis és nagy betűket egy karaktersorozatban. (iNVERT cASE)
  6. A szavak első betűjét állítsuk nagybetűsre, a többi részét pedig kisbetűsre. A szavakat szóközök választják el. (Proper Case)
Szöveg kiírása
Írjunk eljárást, amely kiírja az AL-ben található karaktert a képernyőre.
;eljárás ami kiír egyetlen betűt. a betű kódját al-ben
;várja
betukiir proc             ;al ben a kiirandó betű
         mov     ah, 14   ;BIOS rutin paramétere
         int     10h      ;10h megszakítás hívása
         ret              ;visszatérés
betukiir endp

Írjunk eljárást, ami kiír egy 0-val záródó karakterláncot a képernyőre!
;eljárás ami kiír egy 0-val záródó karakterláncot
;a string elejét si mutatja
strkiir proc
  kov:  mov     al, [si]  ;következő betű
        cmp     al, 0     ;0 jelzi a str végét
        je      strvege   ;ha elértünk a végére ugrunk
        call    betukiir  ;egy betű kiirása
        inc     si        ;mutató a következő betűre
        jmp     kov       ;ugrás
  strvege:
        ret               ;eljárás vége
strkiir endp
A teljes forráskód letölthető innen.

6. gyakorlat

Szám kiírása
Írjunk ki egy előjeltelen 16 bites számot decimális alakban a képernyőre! Algoritmus: a számot osztjuk tízzel. A maradékot kiírjuk, a hányadost pedig tovább osztjuk.
;eljárás, ami kiír egy számot decimális alakban
;a számot ax regiszterben várja
szamkiir proc
  mov bx, 10d    ;számrendszer alapja
  mov cx, 0      ;verembe tett számok számlálója
k1:
  cmp ax, 0      ;addig osztunk amíg nulla nem lesz
  je  v1         ;ha nulla ugrik
  mov dx, 0      ;a kov ut. dx:ax-et osztja!
  div bx         ;osztás bx
  push dx        ;maradek a verembe
  inc cx
  jmp k1
v1:
  jcxz cxnulla   ;ugrik, ha nem tettünk semmit a verembe
k2:
  pop ax         ;kiveszünk egy értéket a veremből
  add al, '0'    ;hozzáadjuk a '0' ASCII kódját
  call betukiir  ;kiírjuk a számot (mint betűt)
  loop k2        ;jöhet a következő
  jmp v2
cxnulla:
  mov al, '0'    ;ha ax-ben 0 volt, 
  call betukiir  ;írjunk ki egy 0-t
v2:
  ret
szamkiir endp
A teljes forráskód letölthető innen. Feladatok:
  1. Írjuk át a programot, hogy 8 bites számokat írjon ki a képernyőre.
  2. Írjuk át a programot, hogy más számrendszerben is ki tudjon írni számokat.
  3. Írjuk át a programot, hogy előjeles számot is ki tudjon írni.
Maximum
Keressük meg egy bájtokból álló számsorozat legnagyobb elemét! A számsorozat hosszát a len változó tartalmazza. Az eredményt taroljuk a max változóban. Az adatszegmens pl a következő is lehet:
adat  segment
    len   dw 5
    max   db 0
    sor   db 4,5,2,7,3
adat  ends
Feladatok:
  1. Módosítsuk a maximum kereső programot hogy szavakból (dupla bájt) álló számsorozatra is működjön.
  2. Módosítsuk a maximum kereső programot minimum kereső programra! Azaz keressük meg a sorozat legkisebb elemét. Figyeljünk a megfelelő kezdőértékekre!
  3. Egészítsük ki a maximum kereső programot, hogy a legnagyobb szám első/utolsó előfordulási helyét a "pos" változóban tároljuk!

7. gyakorlat

String beolvasás billentyűzetről
Irjunk egy eljárást, ami a billentyűzetről beolvas egy sztringet egy bufferbe.
; eljárás ami beolvas egy stringet az SI altal mutatott bufferbe
strolvas proc
     push si           ;si mentése
 olv:
     mov ah, 1h        ;bios eljárás sorszáma
     int 21h           ;bios interrupt
     cmp al, 0dh       ;enter kódja
     je olvasvege
     mov [si], al      ;betű tárolása a memóriában
     inc si            ;a következő betű egyel magasabb mem. címre kerüljön
     jmp olv           ;vissza az olvasás elejére

olvasvege:
     mov byte ptr [si], 0 ;a string veget 0-val lezárjuk
     
     mov ax, 0e0ah     ;újsor karakter kiírása
     int 10h
    
     pop si
     ret
strolvas endp
String fordítás
Fordítsunk meg egy stringet! Írjunk eljárást, amely egy string tartalmát megfordítja. Az eljárás SI regiszterben várja a string elejét. Kiindulási forrás: strford.asm.
  • Oldjuk meg a feladatot a verem használata nélkül!
  • Használjuk a vermet a megoldáshoz!
  • Használjuk a sztingkezelő utasításokat

8. gyakorlat

Paraméterek a veremben!
Írjuk egy eljárást amely összead 2 számot. A paramétereket a veremben adjuk át!
  ...
  mov   ax, 2d
  push  ax
  mov   ax, 4d
  push  ax
  call  osszead
  add   sp, 4
  ...
osszead proc
  push  bp         ;bp mentése
  mov   bp, sp     ;verem teteje
  push  bx         ;bx mentése
  
  mov   bx, [bp+4] ;2. paraméter
  mov   ax, [bp+6] ;1. paraméter
  add   ax, bx     ;összeadás
  
  pop   bx         ;bx visszatöltése
  pop   bp         ;bp visszatöltése
  ret
osszead endp
A teljes forráskód letölthető innen.
Átlag
Írjunk egy eljárást, amely kiszámolja egy sorozat átlagát! Az eljárásnak 2 paramétere legyen (melyeket a veremben kap): az első a sorozat offsetje, a második a sorozat hossza. Kiindulási forrás a gyakorlati munkához: atlag.asm
Skalárszorzat
Írjunk eljárást, ami 2 n hosszúságú vektor skalárszorzatát határozza meg! A paramétereket a vermen keresztül kapja! A teljes forráskód letölthető innen.

9. gyakorlat

Rendezés
Írjunk programot, sorbarendez egy bájtokból álló előjeltelen számsorozatot. Működési elv: a sorozat minden egyes elemére végrehajtjuk a következőket: végigmegyünk a rákövetkező elemeken, és ha kisebbet találunk mint az aktuális, akkor megcseréljük őket.
;eljárás bx-ben várja a bájtsorozat elejét
;ha talál az első elemnél kisebb elemet, akkor 
;megcseréli őket
min proc
     mov dl, [bx]  ;dl-ben az elso szám
     mov si, bx    ;si mutasson az elejére
k1:  mov al, [si]  ;akt szám betöltése
     cmp al, 0     ;nulla?
     je v1         ;ha igen: vége
     cmp al, dl    ;akt. szám és az eddigi legkisebb
     jae k2        ;ha az akt. nagyobb ugorjunk
     mov dl, al    ;jegyezzük meg mert kisebb
     xchg al, [bx] ;csere
     mov [si], al  ;csere
k2:  inc si        ;köv betű
     jmp k1        ;
v1:  ret           ;visszatérés
min endp
;eljárás, mely rendez egy bájtsorozatot
rendez proc
k3:  mov al, [bx]  ;akt szám betölt
     cmp al, 0     ;nulla?
     je  v2        ;ha igen: vége
     call min      ;tegyük az elejére a legkisebbet
     inc bx        ;köv betű
     jmp k3        
v2:  ret           ;eljárás vége
rendez endp
A teljes forráskód letölthető innen. Feladatok: Írjuk át a programot úgy hogy, ...
  • számoljuk, hogy hány csere történik, majd irassuk ki a cserék számát képernyőre!
  • kiírja az eredeti és a rendezett sorozatot is a képernyőre!
  • előjeles számokat kezeljen! Írjuk meg a szamkiir eljaras előjeles változatát is!
  • 16 bites számokat kezeljen!
  • csökkenő sorrendbe rendezze a számokat!
ASCII to Integer
Írjuk meg az atoi() függvényt előjeltelen számokra. A teljes forráskód letölthető innen.
  mov si, [bp+4]    ;parameter atvetele
  mov cx, 10        ;számrendszer alapja
  mov ax, 0         ;ax-ben lesznek a részeredmények
  mov bh, 0         ;bl-ben lesz az aktuális számjegy, bh-ban meg nulla
kovszamjegy:
  mov bl, [si]      ;betöltünk egy betűt
  cmp bl, 0         ;vége-e a sztringnek?
  je vege
  sub bl, '0'       ;levonja az első számjegy ASCII kódját, megkapjuk az értékét
  mul cx            ;eddigi részeredmény x 10
  add ax, bx        ;hozzáadjuk az aktuális számjegyet
  inc si            ;lépés a köv betűre
  jmp kovszamjegy
vege:  
Feladatok: Írjuk át a programot úgy hogy, ...
  • hexadecimális/bináris számokra működjön!
  • előjeles számokat kezeljen!
  • lebegőpontos számokat is kezeljen!

Gyakorló feladatok ZH-ra

Stringek
String esetén a kezdőcím SI regiszterben van megadva, ill. a végét a 0 jelzi. Az eredményt (feltéve hogy van) AX-ben kell tárolni.
  1. Határozd meg az első "a" betű pozícióját (az első betű a nulladik, a második az első, stb...)! Ha nincs "a" betű a stringben legyen -1 a visszatérési érték!
  2. Számold meg hány betű van egy stringben a szóközök és írásjelek nélkül!
  3. Számold meg hány szó van egy sztringben. (dupla szóközök esetén a szavak száma nem változik!)
  4. Konvertáld a stringet csupa nagy-, ill. kisbetűsre! (To uppercase / to lower case)
  5. Egy string összes nagybetűjét váltsd kicsire, a kicsiket pedig nagyra! (Invert case)
  6. Minden szó kezdőbetűjét állítsd nagybetűsre! (Capitalize)
  7. Határozd meg hány kisbetű ( nagybetű, szám-karakter, írásjel ) van a szövegben!
  8. Határozd meg melyik betű hányszor fordul elő. (Pl. DI egy 256 elemű táblázat elejét mutatja)(hisztogram)
  9. Határozd meg, hogy a DI által mutattot string betűi hányszor fordulnak elő összesen!
  10. Határozd meg, hogy a DI által mutattot string hányszor fordul elő!
  11. Határozd meg a DI által mutatott string első/utolsó előfordulasának pozícióját! (strstr)
  12. Határozd meg a szóismétlések számát! (na, ez már durva...)
Számsorozatok, tömbök
Számsorozat kezdőcíme SI-ben, a hossza CX-ben van megadva. Az eredményt (feltéve hogy van) AX-ben kell tárolni. A sorozat lehet előjeles/előjeltelen, 8/16 bites.
  1. Határozd meg hány darab szám esik 100 és 200 közé!
  2. Határozd meg a legnagyobb/legkisebb számot!
  3. Határozd meg a legnagyobb/legkisebb szám (első/utolsó előfordulásának) pozícióját!
  4. Határozd meg a legnagyobb/legkisebb szám előfordulásainak számát!
  5. Számolj átlagot/szórást.
  6. Határozd meg hányszor szerepel két egyforma szám egymás mellett!
  7. Határozd meg hányszor szerepel két egyforma abszolult értékű szám egymás mellett!
  8. Határozd meg hányszor szerepel n darab egyforma szám egymás mellett!
  9. Határozd meg hány n-el osztható szám van a sorozatban!
  10. Határozd meg hány négyzetszám van a sorozatban!
  11. Határozd meg hány előjelváltás történik a sorozatban!
  12. Határozd meg, hogy a számsorozat növekvő/csökkenő sorrendben van e! AX legyen 1, ha igen, különben 0.
  13. Határozd meg, hogy a számsorozat számtani sorozatot alkot e. AX legyen 1, ha igen, különben 0.
  14. Határozd meg, hogy a számsorozat mértani sorozatot alkot e. AX legyen 1, ha igen, különben 0.
  15. Határozd meg, hogy a számsorozat Fobonacci-sorozatot alkot e. AX legyen 1, ha igen, különben 0.
  16. Határozd meg, a leghosszabb növekvő/csökkenő részsorozat hosszát. AX legyen 1, ha igen, különben 0.
n-el osztható számok
Számoljuk meg hány n-el osztható szám van egy sorozatban!
;eljárás amelyik meghatározza, h. hány n-el osztható 
;szám van sorozatban. Az eredményt ax-be teszi.
;1. param: 16 bites előjeltelen sorozat eleje
;2. param: hossz
;3. param: n
ndiv  proc
    push    bp        ;bp mentése
    mov     bp, sp    ;bp = si
    push    si bx cx dx;regiszterek mentése

    mov     si, [bp+8];sorozat eleje
    mov     cx, [bp+6];hossz
    mov     bx, 0     ;számolja az n-el osztható elemeket
kezd:
    mov     ax, [si]  ;ax-be a sor következő eleme
    mov     dx, 0     ;a köv. div dx:ax-et osztja!
    div     word ptr [bp+4] ;osztunk n-el
    cmp     dx, 0
    jne     nemoszthato
    inc     bx        ;számláló növel
nemoszthato:
    add     si, 2     ;kov elem
    loop    kezd    
    mov     ax, bx    ;eredmény ax-be
    pop     dx cx bx si;regiszterek visszatöltése
    pop     bp
    ret
ndiv  endp   
A teljes forráskód letölthető innen.