Naar inhoud springen

Programmeren in TI-83+ Assembly/Assembly-basis/Variabelen

Uit Wikibooks

Programmeren in TI-83+ Assembly

Voorblad / Inhoudsopgave

Assembly-basis

1 · 2 · 3 · 4 · 5 · T

Controle

1 · 2 · 3 · 4 · 5 · T

Geheugenbeheer

1 · 2 · 3 · 4 · 5 · T

Input en output

1 · 2 · 3 · 4 · 5 · T

Tekenen

1 · 2 · 3 · 4 · 5 · T

Registers en procedures

1 · 2 · 3 · 4 · 5 · T

Applications

1 · 2 · 3 · 4 · T

Gebruikersvariabelen

1 · T

Extra

1 · T

Speciaal

Registers zijn perfect om gegevens op te slaan die je direct weer nodig hebt. Maar gegevens die je voor langere tijd nodig hebt, moet je dus vooral niet in een register zetten (zie einde hoofdstuk 3). Daarom is er nog een andere mogelijkheid om gegevens op te slaan, namelijk variabelen: een plek in het geheugen waar je data in kunt zetten. In veel programmeertalen zijn er vaste structuren voor variabelen. In Assembly moet je een variabele echter zelf een geheugenadres toewijzen.

Een variabele toewijzen

[bewerken]

Wat is nu eigenlijk een variabele? In feite is het alleen een plek in het RAM-geheugen (voortaan hebben we het in dit boek gewoon over "het geheugen"), met daarin gegevens. Deze plek kan worden aangesproken door een geheugenadres te geven, dit is een getal dat de "cel" in het geheugen aangeeft waar de gegevens in staan.

Echter, het geheugen wordt ook gebruikt door allerlei andere dingen op de TI, zoals het besturingssysteem en de gebruikersvariabelen. We willen dit natuurlijk niet overschrijven. Er zijn twee manieren om ervoor te zorgen dat je op een 'vrije' plaats schrijft. Als eerste kun je een plek kiezen waarvan je weet dat hij niet wordt gebruikt. Dit leer je in Het gebruik van EQU in hoofdstuk 3. De tweede manier is om je programma als het ware wat langer te maken, zodat je ruimte overhoudt waar je de gegevens in kunt zetten. Dit is helemaal niet moeilijk, je moet alleen de assembler een (of meerdere) extra byte(s) laten toevoegen. Dit kan met de directive (opdracht voor de assembler) .db. De code hieronder plaatst een extra byte op de plek waar de directive in het programma staat, en plaatst er het cijfer 2 in.

    .db 2

Om het geheugenadres zodadelijk gemakkelijk te kunnen opvragen, zetten we een label voor de variabele. Dit ziet er dan als volgt uit:

Variabele:
    .db 2

De assembler onthoudt nu het geheugenadres voor ons, en we kunnen dat straks makkelijk opvragen.

Een variabele uitlezen

[bewerken]

Als we nu een variabele willen uitlezen, en de data die erin staat bijvoorbeeld in een register willen plaatsen, kunnen we dit doen:

    ld a, (Variabele)

Dit mag overigens alleen bij a, als je het resultaat in b (of een ander register) wilt zetten moet je het via hl doen:

    ld hl, Variabele
    ld b, (hl)

De processor heeft namelijk geen instructie voor ld b, (Variabele). Een andere manier is natuurlijk om het resultaat eerst in a te zetten en het daarna te verplaatsen naar b; dat zou je nu zelf moeten kunnen.

Een variabele beschrijven

[bewerken]

Een variabele schrijven gaat op dezelfde manier:

    ld (Variabele), a

Ook hier geldt dat de processor geen instructie heeft voor ld (Variabele), b, en trouwens ook niet voor ld (Variabele), 5 of iets dergelijks, dus dat moet weer via hl:

    ld Variabele, hl
    ld (hl), b

Je kunt wel rechtstreeks hl naar een variabele schrijven:

    ld (Variabele), hl

Let dan wel op: hl beslaat twee bytes en daarom wordt ook het adres Variabele + 1 beschreven. Verder wordt l in Variabele gezet, en h in Variabele + 1, een fenomeen dat big endian genoemd wordt. In het hoofdstuk Geheugenbeheer leer je meer hierover.

Tekst op het scherm schrijven

[bewerken]

Een voorbeeld van het gebruik van variabelen vind je als je tekst op het scherm wilt schrijven. Het TI-OS wil dan namelijk weten waar je tekst in het geheugen staat, en dat kun je dus met een label doen. Hier volgt een voorbeeldprogramma dat tekst op het scherm schrijft.

; Vul de standaardcode zelf aan (zie hoofdstuk 2).

    bcall(_ClrLCDFull)       ; Eerst maken we het scherm leeg.
    ld hl, 0                 ; Laad 0 in hl.
    ld (CurCol), hl          ; Laad nu hl=0 in de kolom van schrijven.
    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 het TI-OS.

Tekst:                       ; Label Tekst
    .db "Hallo!", 0          ; Voeg aan het programma de tekenreeks "Hallo!" toe, gevolgd door een nul.

Ik zal nu stukje voor stukje uitleggen wat er gebeurt.

    bcall(_ClrLCDFull)       ; Eerst maken we het scherm leeg.

Voordat we op het scherm gaan schrijven, wordt het leeggemaakt om te voorkomen dat we over iets anders heen schrijven.

    ld hl, 0                 ; Laad 0 in hl.
    ld (CurCol), hl          ; Laad nu hl=0 in de kolom van schrijven.

Dit is de code om de (CurCol) (dat is de kolom waarin we gaan schrijven) 0 te maken. Om precies te zijn is (CurCol) ook een 'variabele', maar dan

    ld    hl, Tekst          ; Laad het label in hl.

Nu wordt het geheugenadres van het label Tekst geladen in het register hl. Dit zou bijvoorbeeld $8000 kunnen zijn. Zie de volgende regel voor de reden waarom we dit doen.

    bcall(_PutS)             ; Zet de tekst, die staat vanaf hl (dus het label) op het scherm.

Dit is een nieuwe bcall. Hij zet de tekst, die begint bij hl, op het scherm. Hierbij houdt hij rekening met (CurCol). Het resultaat is dus dat "Hallo!" op het scherm wordt gezet. De bcall stopt met schrijven als hij een 0 tegenkomt (geen teken "0" maar het cijfer).

    bcall(_NewLine)          ; Zet de cursor op de volgende regel op kolom 0.

De cursor wordt nu naar de volgende regel verplaatst, zodat de tekst op de volgende regel komt, als we nog iets zouden willen schrijven. Het is altijd een goed idee om dit te doen, en bovendien verschijnt "Done" nu op de juiste plaats.

    ret                      ; Terug naar het TI-OS.

Dit moet nu duidelijk zijn. Zie anders hoofdstuk 2.

Tekst:                       ; Label Tekst
    .db "Hallo!", 0          ; Voeg aan het programma de tekenreeks "Hallo!" toe, gevolgd door een nul.

Het label Tekst is dus eigenlijk een geheugenadres. Hierop wordt dan met de opdracht .db "Hallo!" gezet. Daarachter volgt een 0, omdat de _PutS zoals gezegd stopt als hij een 0 tegenkomt. Haal de 0 maar eens weg en kijk (op de emulator!) wat er gebeurt.

Opdracht

[bewerken]

Het is belangrijk dat je dit onderwerp goed begrijpt. Daarom zijn er drie opgaven, gerangschikt van makkelijk naar moeilijk.

Opdracht 1

[bewerken]

Maak een programma met een variabele Getal, die aan het begin van het programma 0 bedraagt. Aan het eind van het programma moet de variabele 2 bedragen.

Als het niet lukt, kijk dan hieronder voor het antwoord.
Klap uit voor het antwoord

Een mogelijk antwoord zie je hier. Vul de standaardcode zelf aan.

    ld a, 2          ; 2 in a laden
    ld (Getal), a    ; het getal in a in Getal laden (haakjes!)
    ret              ; terug naar TI-OS

Getal:
    .db 0
Merk op dat je 2 niet direct in (Getal) kunt laden, dit moet via een register (in dit geval a).

Opdracht 2

[bewerken]

Maak een programma dat je naam, adres en woonplaats onder elkaar op het scherm zet.

Als het niet lukt, kijk dan hieronder voor het antwoord.
Klap uit voor het antwoord

Een mogelijk antwoord zie je hier. Vul de standaardcode zelf aan.

    ; Scherm leegmaken en initialiseren:
    bcall(_ClrLCDFull)
    ld hl, 0
    ld (CurCol), hl

    ; Schrijf naam:
    ld hl, Naam
    bcall(_PutS)
    bcall(_NewLine)

    ; Schrijf adres:
    ld hl, Adres
    bcall(_PutS)
    bcall(_NewLine)

    ; Schrijf woonplaats:
    ld hl, Woonplaats
    bcall(_PutS)
    bcall(_NewLine)

    ; Terug naar het TI-OS:
    ret

    ; Teksten om te schrijven:
Naam:
    .db "Je naam", 0
Adres:
    .db "Je adres", 0
Woonplaats:
    .db "Je plaats", 0
Vergeet de _NewLine's niet, anders komt alles op één regel te staan.

Opdracht 3

[bewerken]

Maak een programma dat vier mededelingen bevat, bijvoorbeeld op de adressen (labels) Mededeling1, Mededeling2, enzovoorts. Het is de bedoeling dat er in een variabele een van deze vier labels staat (vast ingeprogrammeerd), en dat dan de betreffende mededeling wordt weergegeven. Door de variabele te wijzigen in een ander van de vier labels, wordt dan dus een andere mededeling weergegeven. Let op: om een variabele te maken voor een geheugenadres (dus 2 bytes), moet je .dw gebruiken en niet .db (de w staat voor Word, dat is 2 bytes).

Als het niet lukt, kijk dan hieronder voor een hint en het antwoord.
Klap uit voor een hint
  • Maak een variabele Tekstpointer die standaard is ingeladen op een van de vier labels (zoals bij opdracht 1). Dit moet dus met .dw.
  • Zorg ervoor dat de waarde in Tekstpointer in hl komt te staan voordat je _PutS aanroept.
Klap uit voor het antwoord

Een mogelijk antwoord zie je hier. Vul de standaardcode zelf aan.

    ; Scherm leegmaken en initialiseren:
    bcall(_ClrLCDFull)
    ld hl, 0
    ld (CurCol), hl

    ; Zet Tekstpointer in hl zodat _PutS de mededeling kan vinden
    ld hl, (Tekstpointer)

    ; Schrijf de mededeling:
    bcall(_PutS)
    bcall(_NewLine)

    ; Terug naar het TI-OS:
    ret

    ; De Tekstpointer wijst naar de plek in het geheugen die we willen gaan schrijven
    ; Verander dit in Mededeling2, Mededeling3 of Mededeling4 om de andere mededelingen te zien
Tekstpointer:
    .dw Mededeling1

    ; Mededelingen om te schrijven:
Mededeling1:
    .db "Mededeling 1", 0
Mededeling2:
    .db "Mededeling 2", 0
Mededeling3:
    .db "Mededeling 3", 0
Mededeling4:
    .db "Mededeling 4", 0
Bekijk het programma goed. Als je het helemaal snapt, dan heb je variabelen begrepen.

De antwoorden staan achterin het boek.

← Registers Variabelen De stack →
Informatie afkomstig van https://nl.wikibooks.org Wikibooks NL.
Wikibooks NL is onderdeel van de wikimediafoundation.