
|
Schuiven en roteren Genic Clubguide, 00-00-00
MACHINETAAL:
S C H U I V E N E N R O T E R E N
=======================================
Ik heb nu al een aantal mensen gesproken die in principe
best in staat moeten zijn om een werkend machinetaal
programma te schrijven. Ze kennen de meeste belangerijke
instrukties wel, maar tot mijn verbazing blijken roteer en
schuifinstrukties niet tot deze elementaire kennis te
vallen. Dit vind ik raar omdat deze soort instrukties niet
echt moeilijk zijn en ze vooral bij grafische software nogal
eens gebruikt moeten worden. Gevorderde programmeurs kunnen
het eerste stuk van het nu volgende artikel wel overslaan,
maar ik raad ze toch aan om het laatste deel te lezen omdat
daar interessante tips staan over vermenigvuldigen en delen.
Ik ga er vanaf nu verder vanuit dat u een lijst hebt met
MNEMONICS (=instruktie tabellen) + Opcodes (=de code van een
instruktie) hebt. Hebt u deze niet, zorg dan dat u er ‚‚n
krijgt omdat u anders NOOIT in staat zult zijn om een
behoorlijk programma te schrijven, omdat u niet zult weten
hoe de vlaggen be‹nvloed worden bij een willekeurige
instruktie.
(Nvdr: deze tabellen zullen in gedeelten op de paper-
enclosure worden gepubliceerd. Deze keer de tabel met
schuif- en roteerinstrukties.)
Er zijn twee soorten schuif en roteerinstrukties, nl.
logische en rekenkundige, maar het is in de praktijk niet
nodig dat u ze uit elkaar kunt houden. Als u de werking
ervan weet is dat goed genoeg.
Cy = De Carry vlag van het F register
Dus niet het C register
Bit: 76543210
RLCA Cy < 7 <--- 0 RLCA = Rotate
Left
Carry
Accumulator
Dit betekent zoiets als Roteer de Accu Linksom naar de
Carry. Bit 7 van het A register komt in de Cy vlag te staan,
waarna alle bits van het A register 1 plaats naar links
opschuiven. Het zevende bit komt op de plaats van bit 0
Vb. SCF ; (Set Cy vlag ==> Cy = 1)
CCF ; (Invert Cy vlag ==> Cy = 0)
LD A,33 ; (A = 10100001B Cy = 0)
RLCA ; (A = 01000011B Cy = 1)
RRCA werkt precies andersom, hier roteert alles naar rechts
en komt de inhoud van Bit 0 van register A in de Cy.
Dit is even een voorbeeld van een roteerinstruktie. Als u in
een MNEMONICS tabellenlijst kijkt zult u zien dat alles daar
nog veel duidelijker in staat. U zult bij de instrukties
plaatjes aantreffen met pijlen die de richting van de
verschillende bewegingen aangeven.
Als u deze tabellen eens even bestudeert, dan zult u ook
zien dat andere schuifinstrukties ook met andere registers
gedaan kunnen worden, of zelfs met bytes in het geheugen.
De instukties RLD en RRD vallen een beetje op door hun vele
pijltjes bij de uitleg. Het praktische nut van deze
instrukties is mij nog nooit opgevallen. Theoretisch wordt
een 12 bits woord 4 bits opgeschoven en worden de 4
afgestoten bits aan de andere kant weer neergezet. De 12
bits worden door het A register en byte (HL) gevormd.
Vb. A = 00001111B (HL) = 10101001B A = 16 (HL) = 196
RLD
A = 00001010B (HL) = 10011111B A = 10 (HL) = 159
RLD
A = 00001001B (HL) = 11111010B A = 09 (HL) = 250
RLD
A = 00001111B (HL) = 10101001B A = 16 (HL) = 196
Als iemand een toepassing voor deze beide instrukties heeft,
dan wil ik het graag horen.
Goed, dan komt nu het deel dat ook nog interessant kan zijn
voor de wat gevorderde programmeurs. Als je een byte schuift
dan is dat hetzelfde als een vermenigvuldiging of een deling
door 2, zolang er maar geen bit door het schuiven verdwijnt.
Het antwoordt zou in zo'n geval groter dan 255 worden, en
dat kan niet bij een 8 bits getal. Het getal dat verdwijnt
komt altijd in de Cy terecht. Dit verklaart meteen de naam
van dit bit. Een 'Carry overflow' is namelijk de Engelse
term voor het wegvallen van een bit. Als je alleen maar een
vermenigvuldiging of deling door 2 kunt doen, dan kom je
niet erg ver. Het is echter heel gemakkelijk om een
vermenigvuldiging met b.v. 25 te maken als je de
vermenigvuldiging opsplitst.
4 x 25 = 100
4 x (16 + 8 + 1) = 4 x 25 = 100
Als de vermenigvuldigingsfaktor dus niet een macht van twee
is, dan moet u deze faktor in machten van 2 opsplitsen zoals
hierboven vermeld staat. Ik kan hier alleen maar het
vermenigvuldigen en delen met integers behandelen.
Dan nu het praktische voorbeeld:
LD A,4 ; De startwaarde
LD B,A ; Bewaar faktor A x 2^0 = 1
RLCA ; A x 2
RLCA ; A x 2
RLCA ; A x 2 ==> totaal = x 8
LD C,A ; Bewaar faktor
RLCA ; A x 2 ==> totaal = x 16
ADD A,B ; Tel B erbij op
ADD A,C ; Tel C erbij op. In A staat nu het antwoord !
Hierboven staat dus: 4x1 + 4x8 + 4x16
= 4 x (1+8+16)
= 4 x 25
= 100
Een deling is niet volgens dit principe te maken, alleen als
u een getal door een macht van 2 wilt delen gaat dat. In
alle andere gevallen is herhaald aftrekken de enige methode.
192 / 16
LD A,192
SRL A ; SRL = Shift Right Logic
SRL A
SRL A
SRL A ; Totaal gedeeld door 2^4 = 16
U mag hier niet van de snelle roteer instrukties gebruik
maken omdat verdwijnende bits dan weer aan de linker kant in
het register geschoven worden. Dit kan niet de bedoeling
zijn, omdat dat verkeerde antwoorden oplevert.
192 / 24 = 8
192 - n x 24 = 0 ==> n = 8
LD A,192 ; Beginwaarde
LD B,255
_SP1: INC B
AND A
SUB 24 ; De deler
JP NZ,_SP1 ; Zolang A niet 0 is, blijven aftrekken
LD A,B ; Zet het antwoord in A
Goed, dat was het dan voor deze keer. Ik heb natuurlijk lang
niet alles behandeld, maar u kunt zelf ook wel wat
uitproberen. Pas met de deling op dat u alleen getallen
deelt waar als antwoord een geheel getal uit komt. Als het
toch anders uit kan komen, dan moet u deze routine niet
gebruiken omdat het dan mogelijk is dat de lus nooit
onderbroken zal worden. Het komt in de praktijk toch niet
veel voor dat u in een routine wilt delen, vermenigvuldigen
komt echter redelijk vaak voor en ik hoop dat ik een aantal
mensen heb kunnen helpen.
Veel programmeerplezier,
Alex van der Wal
|