Digitális technika 2 - Házi második részére példa
Figyelem! A programot kizárólag azért töltöttem fel, hogy részleteiben esetleg ötleteket adhasson a házi feladat készítése közben, vagy még inkább annak megírása után esetleges referenciaként szolgálhasson. A programot akár csak részleteiben lemásolni és házi feladatként beadni szigorúan tilos, és veszélyes. Természetesen más az alábbitól eltérő megoldási módok is léteznek, és természetesen el is fogadják őket házifeladat-beadásban.
; BEMENET:
; DE: kezdőcím
; BC: hossz
; feltöltés: ~(hi^lo) (az alsó és felső címbájt kizáró vagykapcsolatának negáltja)
;
; KIMENET
; DE: legalacsonyab című hiba vagy kezdőcím
; HL: hibák száma
; Z = 1: volt hiba
ELLENOR: ; A feladatkiírás szerinti rutin
PUSH PSW ; Mentés
PUSH B ; a darabszámra is szükség lesz később
; HL <- kezdőcím (ciklus előfeltétel)
MOV H, D
MOV L, E
CIKLUS_FELTOLT: ; Feltöltő ciklus. HL mutat az aktuális címre.
MOV A, B ; Ciklusfeltétel ellenőrzése
ORA C ; BC = 0 ?
JZ CIKLUS_FELTOLT_VEGE
; Kiszámítjuk a felső és alsó bájt kizáró vagy kapcsolatának negáltját
MOV A, H
XRA L ; A = H XOR L
CMA ; A = ~A, negálás
MOV M, A ; Kiírjuk a memóriába
INX H ; Következő cím
DCX B ; Egyel kevesebb cím van hátra
JMP CIKLUS_FELTOLT
CIKLUS_FELTOLT_VEGE:
; Ellenőrzés:
; A stackben tároljuk a legalacsonyabb hibacímet, a hibák számát pedig a DE regiszterben.
POP B ; BC <- a memóriablokk hossza (visszaállítjuk a stackből az értéket)
PUSH B ; De a stackben is ott hagyjuk
PUSH D ; Elmentjük a memóriablokk kezdőcímét a stackbe. Az első hibánál felülírjuk majd.
; Innentől: SP <- kezdőcím / első hiba
MOV H, D
MOV L, E ; HL <- kezdőcím (ciklus előfeltétel)
LXI D, 0 ; DE <- eddigi hibaszám
; Változók: DE hibaszám
; HL aktuális memóriacím
; BC maradék blokk hossza
; Stack:
; +-------------------------+
; | E *kezdőcím / első hiba | <-- SP
; | D *kezdőcím / első hiba |
; | C eredeti hossz |
; | B eredeti hossz |
; | PSW (flags) |
; | PSW (A) |
; | ... |
CIKLUS_ELL: ; Ellenőrzőciklus
MOV A, B ; ciklusfeltétel ugyanaz, mint a feltöltéskor: hátralévő blokkhossz BC != 0
ORA C
JZ CIKLUS_ELL_VEGE
; Ellenőrző kód kiszámítása
MOV A, H
XRA L
CMA ; A = ~(H XOR L)
; Összevetés a memóriával. Ugyanaz -> A = 0, Z = 1
XRA M
JZ ELL_FOLYT
; HIBA VAN (Z = 0)
MOV A, D
ORA E ; Ha nem volt még hiba, akkor A = DE = 0, Z = 1
JNZ VOLT_MAR_HIBA
; ELSŐ HIBA (Z = 1), mentsük el a helyét
INX SP
INX SP ; POP (kezdőcím)
PUSH H ; SP <- első hiba címe
VOLT_MAR_HIBA:
INX D ; Hibaszám növelése
ELL_FOLYT: ; Ciklus folytatása
INX H ; következő memóriacím
DCX B ; egyel kevesebb van hátra
JMP CIKLUS_ELL
CIKLUS_ELL_VEGE: ; ellenőrzés vége, visszatérés a kiírás szerint
XCHG ; HL <- hibaszám, DE <- x
POP D ; DE <- kezdőcím / első hiba címe (végleges kimenet)
POP B ; stack ürítése, B visszaállítása, SP <- PSW (flagek)
MOV A, H
ORA L ; HL = hibaszám = 0 ? Z flaget állítja.
XTHL ; L <- flagek, H <- A (PSW), SP <- HL (hibaszám)
MOV A, L ; a flageket (Z-t) fogjuk állítani
JZ NINCS_HIBA ; hibaszám = 0, Z = 1 volt
; VOLT HIBA
ORI 64 ; 6. bit (Z) 1-be állítva (64 = 0100 0000)
JMP VEGE
NINCS_HIBA:
ANI 191 ; 6. bit (Z) 0-ba állítva (191 = 1011 1111)
VEGE:
MOV L, A
XTHL ; Stack <- PSW (Z felülírva), HL <- hibaszám (végleges kimenet)
POP PSW ; flagek visszaállítva, Z felülírva (végleges kimenet)
RET