Programmeren in TI-83+ Assembly/Printversie: verschil tussen versies

Verwijderde inhoud Toegevoegde inhoud
Willem1 (overleg | bijdragen)
+ Variabelen en De stack
Willem1 (overleg | bijdragen)
Geen bewerkingssamenvatting
Regel 387:
 
Verder kan het programma crashen als je heel veel registerparen op de stack legt (bij ongeveer 100).
 
 
<div style='text-align: center;background-color: silver;border: none' height=150>
<br/>
<font size=25pt>Hoofdstuk 2 - Controle</font>
<br/><br/>
</div>
 
In dit deel leer je meer over verschillende controlestructuren die je in programma's kunt gebruiken.
 
<div style='text-align: center;background-color: #efefef;border: none' height=150>
<br/>
<font size=5pt>Springen en subroutines</font>
<br/><br/>
</div>
 
Je weet al wat labels zijn. Het is mogelijk om naar zo'n label te springen.
 
==jp==
Naar een label springen kan met
<pre> jp labelnaam</pre>
jp staat voor JumP. Als de processor zo'n regel tegenkomt, gaat hij verder met lezen bij het label met ''labelnaam''. TASM vervangt ieder label namelijk door het geheugenadres daarvan. De regel kan zou dan bijvoorbeeld kunnen worden vervangen door
<pre> jp $8000</pre>
De processor weet nu waar hij heen moet springen.
 
==jr==
Een andere manier om te springen is
<pre> jr labelnaam</pre>
jr staat voor Jump Relative. Dit is één byte kleiner dan jp, maar het kan alleen maar als het label ongeveer 128 bytes vóór of achter de jr-regel staat. Bij jr zet TASM namelijk, in plaats van het precieze geheugenadres, neer hoeveel bytes er gesprongen moet worden. Bijvoorbeeld
<pre> jr 4</pre>
Als de label te ver weg staat, krijg je een foutmelding van TASM.
 
==call==
Er is nóg een manier van springen, en dat is om subroutines te maken. Het werkt als volgt:
<pre> call Subroutine
; instructies-1
ret
 
Subroutine:
; instructies-2
ret
</pre>
Eerst springt de processor naar Subroutine. Daar voert hij dus instructies-2 uit. Als hij ret tegenkomt, gaat hij weer terug naar waar hij vandaan kwam en voert hij instructies-1 uit. Bij de volgende ret eindigt het programma (dus terug naar de TI-OS).
 
==Opdracht 3==
[[Afbeelding:Screenshot TI Assembly 4keerhallo.png|96px|thumb|Het resultaat]]
Maak een programma dat vier keer een tekst op het scherm schrijft. Gebruik daarvoor een subroutine met een bcall. Roep deze vier keer aan. Het resultaat moet er ongeveer uitzien als het plaatje hiernaast.
''Het antwoord vind je weer aan het einde van het boek.''
 
 
<div style='text-align: center;background-color: #efefef;border: none' height=150>
<br/>
<font size=5pt>Optellen en aftrekken</font>
<br/><br/>
</div>
 
Voordat we kunnen beginnen met voorwaarden, moeten we eerst iets weten over optellen en aftrekken.
 
==add==
We beginnen met optellen.
<pre> add a, b</pre>
Dit telt b op bij a en slaat het antwoord op in a.
<pre> add a, 8</pre>
Dit telt 8 op bij a en slaat het antwoord op in a.
 
Je kunt alleen maar iets optellen bij a of bij hl.
Fout is bijvoorbeeld:
<pre> add b, 8</pre>
Met het optellen bij hl zullen we ons nu even niet bezig houden, dit komt later aan de orde.
 
==sub==
Aftrekken gaat als volgt.
<pre> sub b</pre>
Dat lijkt een beetje vreemd, maar het komt erop neer dat je toch alleen maar kunt aftrekken van a, daarom wordt de a ervoor weggelaten. Deze instructie haalt dus b van a af en slaat het antwoord op in a.
 
==inc en dec==
Wil je één optellen of aftrekken, dan kun je respectievelijk inc of dec gebruiken. Dit gaat als volgt:
<pre> inc a</pre>
Dit telt één op bij a. Je kunt hier alle registers voor gebruiken.
 
 
<div style='text-align: center;background-color: #efefef;border: none' height=150>
<br/>
<font size=5pt>Het register f</font>
<br/><br/>
</div>
 
Uit het hoofdstuk Registers ken je al het register f. Dit register is echter anders dan de andere registers die je al kent; je kunt het niet rechtstreeks wijzigen.
 
==De opbouw van het register f==
Hieronder zie je een schema hoe het f-register in elkaar zit. Iedere kolom in de tabel is een vlag. Zo'n vlag is een bit in het register f.
 
{| {{prettytable}}
|-
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0
|-
| Sign || Zero || - || Half-carry || - || Parity-overflow || Add-subtract || Carry
|}
 
Er zijn twee vlaggen die nu voor ons van belang zijn. Als een vlag 1 is (ook wel '''set''' genoemd, 0 heet ook wel '''reset'''), betekent dit het volgende.
 
===Zero===
De vorige berekening had als uitkomst 0.
 
===Carry===
De vorige berekening had een uitkomst die groter was dan wat er in het register paste. Zie het volgende voorbeeld. Tel de (binaire) getallen 1101 en 1000 op. Het resultaat is 10101. Ofwel, er is één bit meer nodig om het antwoord op te slaan. Het resultaat van deze bewerking wordt dan 0101 en de Carry-vlag wordt 1 gemaakt. Als een aftreksom een antwoord kleiner dan nul opleverde, gaat de Carry-vlag ook aan.
Wil je de Carry-vlag 1 maken, dan gebruik je de instructie SCF (Set Carry Flag)
Wil je de Carry-vlag veranderen (dus 1 wordt 0 en omgedraaid), dan gebruik je de instructie CCF.
 
{{Bericht
|titel=Wijzigen van f
|bericht=Zoals hierboven gezegd is, kun je f niet zomaar wijzigen:
<pre> ld f, 5</pre>
werkt bijvoorbeeld niet. Je kunt wel af aanpassen, bijvoorbeeld door '''pop af''', f verandert dan mee. Denk eraan dat de vlaggen dan dus weg zijn.
|type=info}}
 
<div style='text-align: center;background-color: #efefef;border: none' height=150>
<br/>
<font size=5pt>Voorwaarden</font>
<br/><br/>
</div>
 
Een bekende structuur die in heel veel programma's voorkomt, is de ''if-then-structuur'', dit is een structuur die een stuk code alleen uitvoert als een voorwaarde waar is. In Assembly gaat dit iets moeilijker...
 
==cp==
Als eerste is de instructie cp van belang. Deze doet hetzelfde als sub, maar slaat het resultaat niet op. Wat hebben we er dan aan? De vlaggen worden wél ingesteld.
Zie dit voorbeeld.
<pre> sub 8</pre>
Stel je voor dat a 8 was, staat er nu 0 in a. De Zero-vlag is dus ingesteld op 1, want de uitkomst is 0.
<pre> cp 8</pre>
Stel je voor dat a 8 was, is de Zero-vlag dus ook ingesteld op 1, want de uitkomst van de som is 0, maar er staat nog steeds 8 in a. Als a bijvoorbeeld 9 was geweest, is de Zero-vlag dus 0.
 
==Voorwaarden gebruiken==
Om een voorwaarde te kunnen gebruiken, hebben we dus iets nodig dat kijkt of de Zero-vlag 0 is. Kijk eerst naar dit voorbeeld:
<pre> jp z, Label</pre>
Dit springt alleen naar Label als de Zero-vlag 1 is. Als de Zero-vlag 0 is, gaat de uitvoering gewoon verder na de instructie. Op deze manier kun je dus een voorwaarde stellen.
De voorwaarden die je kunt gebruiken:
{| class="prettytable"
|-
! Voorwaarde
! Werking
|-
| z
| Voert de actie alleen maar uit, als de Zero-vlag 1 is. Ofwel, als je een cp hebt uitgevoerd, alleen als a gelijk is aan het cijfer achter cp.
|-
| nz
| Voert de actie alleen maar uit, als de Zero-vlag 0 is. Ofwel, als je een cp hebt uitgevoerd, alleen als a niet gelijk is aan het cijfer achter cp.
|-
| c
| Voert de actie alleen maar uit, als de Carry-vlag 1 is. Ofwel, als je een cp hebt uitgevoerd, alleen als het resultaat van de aftreksom kleiner is dan 0, dus alleen als a kleiner is dan het cijfer achter cp.
|-
| nc
| Voert de actie alleen maar uit, als de Carry-vlag 0 is. Ofwel, als je een cp hebt uitgevoerd, alleen als het resultaat van de aftreksom niet kleiner is dan 0, dus alleen als a groter dan of gelijk is aan het cijfer achter cp.
|}
Deze voorwaarden kun je gebruiken achter de volgende instructies: jp, jr, call en ret.
 
 
<div style='text-align: center;background-color: #efefef;border: none' height=150>
<br/>
<font size=5pt>Loops</font>
<br/><br/>
</div>
 
Met behulp van de voorwaarden is het mogelijk om loops te maken. (Loops zijn lussen, zie de pagina '''Controlestructuren''' uit het boek ''Programmeren in TI-Basic'' als je niet weet wat dat zijn.)
 
==De While-loop==
De While-loop bouwen we door eerst te kijken hoe je deze in woorden zou uitdrukken. Stel je een While-loop voor: While a=0
# Als a niet gelijk is aan 0, spring naar het einde van de loop.
# Voer bepaalde instructies uit.
# Ga nu terug naar het begin.
# Deze instructies worden uitgevoerd als a een keer niet gelijk is aan 0 geweest.
Dit kan als volgt worden omgezet in Assembly-code:
 
<pre>; stap 1
BeginLoop:
cp 0 ; controleer of a gelijk is aan 0
jp nz, EindLoop ; als dat niet zo is, spring naar EindLoop
 
; stap 2
; instructies
 
; stap 3
jp BeginLoop
 
; stap 4
EindLoop:
; instructies</pre>
Bij While-loops moet je oppassen voor oneindige loops. Zie het volgende voorbeeld:
<pre> ld a, 1
 
BeginLoop:
cp 0 ; controleer of a gelijk is aan 0
jp nz, EindLoop ; als dat niet zo is, spring naar EindLoop
inc b
jp BeginLoop
 
EindLoop:
; instructies</pre>
Dit zorgt voor een probleem: a blijft natuurlijk 0, omdat er in de instructies binnen de While-loop niets mee gebeurt. Het resultaat is bekend: het enige wat hiertegen nog kan worden gedaan, is de batterijen uit de rekenmachine halen.
 
==De For-loop==
De For-loop is een loop waarbij het aantal keren herhalen van te voren bekend is. Het is eigenlijk een speciaal soort While-loop, namelijk een While-loop waarbij bij iedere cyclus een teller ééntje verhoogd wordt. De voorwaarde is hierbij een controle of de teller een bepaald getal is. Bijvoorbeeld: je wilt een instructie vijf keer uitvoeren.
<pre>
ld a, 0
 
BeginLoop:
cp 5 ; controleer of a gelijk is aan 5
jp nz, EindLoop ; als dat niet zo is, spring naar EindLoop
inc a
jp BeginLoop
 
EindLoop:
; instructies
</pre>
 
Dit is goede code, maar hij kan wellicht beter. Het is immers niet handig om a te gebruiken voor de teller, aangezien dit ook het rekenregister is. Het is dus beter om b te gebruiken. Maar dan is het niet mogelijk een cp te gebruiken, aangezien dit alleen bij a kan. dec kan wél bij b gebruikt worden. Deze set de zero-vlag als het resultaat 0 is. Om het gebruik van dec mogelijk te maken, is het dus nodig om de teller steeds te verlagen, in plaats van hem te verhogen. Je begint bijvoorbeeld bij 5, en telt dan af tot 0. Als de teller 0 is, dan spring je uit de loop. Dit gaat dus als volgt.
<pre>
ld b, 5
 
BeginLoop:
; instructies
dec b ; b met 1 verlagen; als b niet 0 is, gaat de zero-vlag uit
jp nz, BeginLoop ; als de zero-vlag uit is, ofwel als b niet 0 is, spring naar BeginLoop
 
EindLoop:
; instructies
</pre>
Of, korter:
<pre>
ld b, 5
 
BeginLoop:
; instructies
djnz BeginLoop ; is hetzelfde als dec b, jp nz BeginLoop
 
EindLoop:
; instructies
</pre>
 
==Opdracht 4==
[[Afbeelding:Screenshot TI Assembly 4keerhallo.png|96px|thumb|Het resultaat]]
Pas opdracht 3 aan, en gebruik nu een for-loop.
''Het antwoord staat weer achterin het boek.''
 
 
Regel 404 ⟶ 647:
 
==Opdracht 2==
 
Een mogelijk antwoord zie je hier. Vul de standaardcode zelf aan.
<pre>
Regel 415 ⟶ 657:
</pre>
Merk op dat je 2 niet direct in (Getal) kunt laden, dit moet via een register (in dit geval a).
 
==Opdracht 3==
Een mogelijk antwoord zie je hier. Vul de standaardcode zelf aan.
<pre>
call TekstSchrijven ; TekstSchrijven aanroepen
call TekstSchrijven ; ... en nog een keer ...
call TekstSchrijven
call TekstSchrijven
ret ; Terug naar de TI-OS.
 
TekstSchrijven:
; Let op, níét PenCol instellen, want dan zouden de "Hallo!"'s iedere keer op dezelfde plek komen!
ld hl, Tekst ; Laad het label in hl.
bcall(_PutS) ; Zet de tekst, die staat vanaf hl (dus het label) op het scherm.
bcall(_NewLine) ; Zet de cursor op de volgende regel op kolom 0.
ret ; Terug naar de hoofdmodule.
 
Tekst: ; Label Tekst
.db "Hallo!", 0 ; Voeg aan het programma de tekenreeks "Hallo!" toe, gevolgd door een nul.
</pre>
 
==Opdracht 4==
Een mogelijk antwoord zie je hier. Vul de standaardcode zelf aan. '''Deze oplossing is nog niet getest!'''
<pre>
ld b, 4
 
BeginLoop:
call TekstSchrijven ; TekstSchrijven aanroepen
djnz BeginLoop ; Één aftrekken van b en als het resultaat niet 0 is, naar BeginLoop springen
 
EindLoop:
ret ; Terug naar de TI-OS.
 
TekstSchrijven:
; Let op, níét PenCol instellen, want dan zouden de "Hallo!"'s iedere keer op dezelfde plek komen!
ld hl, Tekst ; Laad het label in hl.
bcall(_PutS) ; Zet de tekst, die staat vanaf hl (dus het label) op het scherm.
bcall(_NewLine) ; Zet de cursor op de volgende regel op kolom 0.
ret ; Terug naar de hoofdmodule.
 
Tekst: ; Label Tekst
.db "Hallo!", 0 ; Voeg aan het programma de tekenreeks "Hallo!" toe, gevolgd door een nul.
 
</pre>
'''Opmerking:''' in dit geval is het niet veel korter, maar vooral bij 5 of meer herhalingen is dit erg nuttig.
Informatie afkomstig van https://nl.wikibooks.org Wikibooks NL.
Wikibooks NL is onderdeel van de wikimediafoundation.