Assembly Cursus 6

ACNa de onvoorwaardelijke sprongen, wordt het nu tijd om te kijken naar voorwaardelijke sprongen en de opdrachten die hierbij komen kijken. Deze gebeuren dus enkel op een door jou zelf bepaalde voorwaarde en zijn o.a. gelijk aan de FOR… NEXT lussen in BASIC. We zullen dus ook enkele commando’s bespreken die de voorwaarde creëren voor het vertakken/springen. Daarnaast zullen we het statusregister wat nader bekijken!

CursusAssembly Deel1 hdr

ACComputer: Commodore 64
Datum: 2012
T
ype: Programmeertaal
Door: Addy van Ladesteijn

Voorwaardelijk!
Na de onvoorwaardelijke sprongen, wordt het nu tijd om te kijken naar voorwaardelijke sprongen en de commando’s die hierbij komen kijken. Deze gebeuren dus enkel op een door jou zelf bepaalde voorwaarde en zijn o.a. gelijk aan de FOR… NEXT lussen in BASIC. We zullen dus ook enkele opdrachten/commando’s bespreken die de voorwaarde creëren voor het vertakken/springen. 

Naast de commando’s die een voorwaarde laten ontstaan hebben we ook meer kennis nodig van het status register, want dat houdt de onstane voorwaarden netjes bij.   Het is essentieel dat deze opdrachten een tweede natuur worden, want deze zullen vaak gebruikt worden! Zorg dus dat je dit stuk met de voorbeelden begrijpt. Ik heb zoveel mogelijk voorbeelden gebruikt om de werking aan te tonen. Mocht je nog vragen hebben, kun je altijd mailen!

Naast de Onvoorwaardelijke sprongen zijn er de even zo krachtige voorwaardelijke sprongen. Denk hierbij aan de equivalenten van IF…THEN of FOR…NEXT. Om deze goed uit te leggen zullen we in dit deel een aantal opdrachten bespreken die je niet kunt vermijden.

Voorwaardelijke sprongen
Een voorwaardelijke sprong doet ook precies wat zijn naam zegt; vertakken als er aan een bepaalde voorwaarde voldaan is. Om deze voorwaarden te controleren en te beïnvloeden, gebruiken we onderstaande instructies:

BEQ – Branch (vertak) als het resultaat gelijk (EQual) is aan 0  
BNE – Branch als het resultaat niet gelijk is (Not Equal) aan 0
DEX – DEcrement (verlaag met 1) de inhoud van het X register
DEY – DEcrement (verlaag met 1) de inhoud van het Y register
INX – INcrement (verhoog met 1) de inhoud van het X register
INY – INcrement (verhoog met 1) de inhoud van het Y register
CPX – ComPare (vergelijk) de inhoud van een adres met het X register
CPY – ComPare (vergelijk) de inhoud van een adres met het Y register
CMP – CoMPare (vergelijk) de inhoud van een adres met de Accumulator
BMI – Branch als de N vlag gezet is (MInus)
BPL – Branch als de N vlag niet gezet is (PLus)

Het Statusregister
In Deel 2 is het statusregister al voorbij gekomen. Bovenstaande commando’s gebruiken het zogenaamde statusregister (SR). Het statusregister is net als de accumulator en de X/Y registers een 8 bits register. Dit register wordt echter op een totaal andere wijze gebruikt. De andere registers worden gebruikt om bytes op te slaan en te manipuleren. Het statusregister wordt echter behandeld alsof het uit acht afzonderlijke bits (van betekenis) bestaat die als signaal of vlag worden gebruikt. Elke bit representeert dus één of andere gezette status/vlag. De processor bekijkt maar één statusvlag (zoals ze worden genoemd) tegelijk. Hij maakt dan het bit ‘0’ of ‘1’ of hij test of het bit gezet is (bit = ‘1’) of niet (bit =’0′).
ACZ-vlag
Een voorbeeld van een statusvlag is de Z-vlag (of nul-vlag). Wanneer een berekening (of een verschuiving) als resultaat een nul oplevert in het desbetreffende register (A, X of Y) dan wordt de Z-vlag op ‘1’ gezet. Als het resultaat niet nul is, wordt de Z-vlag op ‘0’ gezet. Je kunt ook zeggen dat een ‘0’ waarde betekent dat een conditie (of status) WAAR is en als de waarde ‘1’ is de conditie (of status) FOUT/NIET WAAR is. Dit zullen we aan de hand van een voorbeeld duidelijker maken. Een voorbeeld van een opdracht die de Z-vlag zet is de DEX opdracht. Bekijk onderstaande programma:

OPCODE OPERAND
LDX #100     (Laad 100 in register X)
DEX          (Verlaag de waarde in het X register met 1)

De mogelijkheid om het X- en Y register te verhogen/verlagen (indexeren) heeft deze registers de naam indexregisters gegeven. Na dit programma zal het X-register de waarde ’99’ bevatten en zal de Z-vlag dus op de waarde ‘0’ staan omdat de verlaging er niet voor heeft gezorgd dat het X-register op nul is komen te staan. Om nu gelijk onze eerste voorwaardelijke vertakking te gebruiken, moeten we nog een instructie toevoegen die gaat vergelijken of een conditie WAAR danwel NIET WAAR is. hiervoor gebuiken we de BEQ instructie. Deze instructie controleert de status van de Z-vlag en vertakt als deze gezet is (waarde = ‘1’).

ADRES OPCODE OPERAND
$8000 LDX #100       (Laad 100 in register X)
$8003 DEX            (Verlaag de waarde in het X register met 1)
$8004 BEQ $8009      (X=0? dan Z-vlag gezet met een '1' en naar STX 1024)
$8006 JMP $8003      (Als X geen 0 is, springen we terug naar DEX)
$8009 STX 1024       (Zet een 0 in 1024)
$800C STX 55296      (Geef teken op lokatie 1024 de kleur zwart)
$800F RTS

Bovenstaande programma zet het X register op 100 en verlaagt dit vervolgens met de DEX instructie. De BEQ instructie wordt pas uitgevoerd als het X-register op nul staat (en daarmee de Z-vlag van het statusregister op ‘1’ komt te staan). Tot die tijd wordt de BEQ instructie niet uitgevoerd waardoor de daarop volgende JMP weer terugspringt naar het DEX commando. Als alles goed gaat, zal er een zwarte “@” verschijnen in de linker bovenhoek (postitie 1024). We hadden in plaats van het X register ook het Y register kunnen gebruiken met LDY, DEY en STY. De BNE instructie doet hetzelfde als BEQ alleen dan omgekeerd, hij vertakt als de Z-vlag NIET is gezet (en dus de waarde ‘0’ heeft) wat ons weer een JMP instructie scheelt

ADRES OPCODE OPERAND
$8000 LDX #100       (Laad 100 in register X)
$8003 DEX            (Verlaag de waarde in het X register met 1)
$8004 BNE $8009      (Z-vlag gezet met een '0'? Dan terug naar DEX)
$8006 JMP $8003      (Spring terug naar DEX)
$8009 STX 1024       (Zet een 0 in 1024)
$800C STX 55296      (Geef teken op lokatie 1024 de kleur zwart)
$800F RTS

In plaats van registers te verlagen, kunnen we ze ook verhogen doormiddel van INX, en INY. Natuurlijk is een gewone controle op nul niet mogelijk als we de registers ophogen. De registers moeten in dit geval vergeleken worden met een bestaande waarde die we van tevoren ergens hebben opgeslagen. De processor kent hiervoor drie opdrachten: CPX, CPY en CMP. Stel je maakt gebruik van het CPX. Wat je in feite doet is de inhoud van een geheugenplaats aftrekken van de waarde in het X register. Het resultaat kan vervolgens postief, negatief of nul zijn. De opdracht CPX $8003 zorgt er dus voor dat de inhoud op geheugenlocatie $8003 vergeleken wordt met de inhoud van het X-register. Indien de waarden gelijk zijn krijgt de Z-vlag in dit gevaal de waarde ‘0’ (WAAR), zo niet dan krijgt de Z-vlag de waarde ‘1’ (NIET WAAR). Tijdens de CPX instructie wordt er niets veranderd aan de waarde van zowel het X-register als de vergeleken geheugenlocatie. Het resultaat van onderstaande listing zal een witte diamant in de linkerbovenhoek zijn, of een witte ‘Z’ afhankelijk of je in uppercase of lowercase mode staat.

ADRES OPCODE OPERAND
$8000 LDA #90        (Laad 90 in de Accumulator)
$8002 STA $0890      (Sla de inhoud van A op in $0890)
$8005 LDX #0         (Laad de waarde '0' in register X)
$8007 INX            (Verhoog de waarde in het X register met 1)
$8008 CPX $0890      (Vergelijk inhoud X register met inhoud $0890)
$800B BEQ $8010      (Inhoud gelijk? Dan naar $8010)
$800D JMP $8007      (Inhoud niet gelijk? Dan terug naar INX)
$8010 STX 1024       (Zet karakter 90 op het scherm links bovenaan)
$8013 LDA #1         (Laad 1 in de Accumulator)
$8015 STA 55296      (Zet inhoud Accumlator op adres 55296 - kleur wit)
$8018 RTS

De derde verlgelijkopdracht is CMP. Deze is bijzonder handig omdat de resultaten van alle rekenkundige operaties automatisch in de Accumulator gezet worden. Met CMP kun je een gegeven waarde en een ‘antwoord’ direct met elkaar vergelijken, zoals in onderstaande voorbeeld:

ADRES OPCODE OPERAND
$8000 LDX #0         (Laad 0 in het X register)
$8002 LDA #83        (Laad 84 in de Accumulator)
$8004 INX            (Verhoog de waarde in het X register met 1)
$8005 STX $0900      (Sla de inhoud van het X register op in $0900)
$8008 CMP            (Vergelijk inhoud X register met inhoud Accumulator)
$800B BNE $8004      (Inhoud niet gelijk? Dan naar $8004)
$800D STX 1024       (Inhoud wel gelijk? Zet karakter "hartje" linksboven )
$8010 LDA #1         (Laad 1 in de Acuumulator)
$8012 STA 55296      (Geef het hartje een witte kleur)
$8015 RTS

N-vlag
De 7e bit, de N-vlag wordt ook wel de Nagetief-vlag genoemd. Deze wordt op 1 gezet als het antwoord van een operatie negatief is. Dit kan getest worden door de opdrachten BMI en BPL en laten dit nu net de vertakkingsopdrachten zijn die we in dit deel gaan behandelen! In onderstaande programma geef ik een voorbeeld van het gebruik van BMI. De inhoud van het Y register wordt net zolang met 1 verhoogd tot het CPY commando geen negatief resultaat meer geeft.

ADRES OPCODE OPERAND
$8000 LDA #90        (Laad 90 in het de Accumulator)
$8002 STA $0900      (Sla de inhoud van de Accumulator op in $0900)
$8005 LDY #0         (Laad 0 in het Y register)
$8007 INY            (Hoog de waarde in het Y register met '1' op)
$8008 CPY $0900      (Vergelijk inhoud van het Y register met inhoud $0900)
$800B BMI $8007      (Test N-vlag, is deze negatief? Dan naar $8007)
$800D STY 1024       (Inhoud wel gelijk? Zet karakter "hartje" linksboven )
$8010 LDA #1         (Laad 1 in de Accumulator)
$8012 STA 55296      (Geef het hartje een witte kleur)
$8015 RTS 

Nu zul je jezelf misschien afvragen waarom de vergelijking CPY $0900 de N-vlag zet. Het is toch niet meer dan een vergelijking die waar of niet waar is? Weet je nog hoe het CPY (of CMP/CPX) commando in feite echt werkt?  Het is niet echt een vergelijking, maar meer aftreksom. In bovenstaande voorbeeld wordt de inhoud van het Y register dus afgetrokken van de Accumulator (A-Y). Als de waarde in het Y register dus groter wordt dan de waarde in de Accumulator (90-91) geeft dit een negatieve waarde en zal het probramma verder gaan met de STY instructie op $800D omdat de N-vlag gezet is. Een CMP, CPY, CPX opdracht is dus eerder een aftreksom dan een vergelijking!

ADe vlaggen ter afsluiting
We weten nu dat elke bit (of vlag) uit het statusregister een functie heeft; het vertelt een status. Van het statusregister interesseert ons dus niet zozeer de actuele hexwaarde, maar wel de toestand of status van de individuele bits. Van de acht registerbits worden er slechts zeven gebruikt – de resterende bit (bit nummer 5) is voortdurend geset (is dus altijd “1”). We hebben bit 1 (Z-vlag) en bit 7 (N-vlag) in dit deel behandeld, en de overige vlaggen zullen later nog besproken worden. Het is wel handig om alvast aan te geven welke commando’s de vlaggen gebruiken.

Bit 7 – N-vlag (Negatief vlag)
Deze wordt gezet als een rekenkundige operatie een negatief resultaat oplevert. De vlag wordt gebruikt door de opdrachten ADC, AND, ASL, BIT, CMP, CPY CPX, DEC, DEY EOR, INC, INX, INY, LDA, LDX, LDY, LSR, ORA, PLA, PLP, ROL, ROR TAX, TAY, TXA, TYA.

Bit 6 – V-vlag (Overloop vlag)
Deze wordt gezet als een rekenoperatie resulteert in een overloop van bit 6 naar bit 7. Deze vlag vertelt dat het resultaat fout is, tenzij men met de overloop werkt. De vlag wordt gebruikt door de opdrachten ADC, BIT, CLV, PLP, RTI, SBC.

Bit 4 – B-vlag (Break vlag)
De onderbrekingsvlag wordt gezet als BRK een geprogrammeerde interrupt teweegbrengt. Als een programma dus een BRK gekregen heeft.

Bit 3 – D-vlag (Decimaal vlag)
Deze wordt gezet als rekenkundige operaties decimaal moeten worden uitgevoerd. De vlag wordt gebruikt door de opdrachten CLD, PLP, RTI, SED.

Bit 2 – I-vlag (Interrupt vlag)
Deze wordt gezet als er een interrupt wordt uitgevoerd. De vlag wordt gebruikt door de opdrachten BRK, CLI, PLP, RTI, SEI.

Bit 1 – Z-vlag (Zero vlag)
De nulvlag wordt (zoals je nu weet) gezet als een rekenkundige operatie nul als resultaat geeft. De vlag wordt gebruikt door de opdrachten: ADC, AND, ASL, BIT, CMP, CPY CPX, DEC, DEX, DEY, EOR, INC, INX, INY, LDA, LDX, LDY, LSR, ORA, PLA, PLP, ROL, ROR, RTI, SBC, TAX, TXA, TYA.

Bit 0 – C-vlag (Carry vlag)
De overdrachtsvlag geeft de aanwezigheid van een ‘overdracht’ of, in wiskundige termen een lening, aan bij een rekenkundige operatie. Deze vlag wordt bestuurd door de opdrachten ADC, ASL, CLC, CMP, CPX, CPY, LSR, PLP, ROL, ROR, RTI, SBC, SEC.

 
 
(Bron: Programmeer cursus Assembly – P. Holmes/D. Bush)