Hoofdstuk 4: De 6502 Assemblagetaal-tutorial voor microprocessors

Hoofdstuk 4 De 6502 Assemblagetaal Tutorial Voor Microprocessors



Hoofdstuk 4: De 6502 Assemblagetaal-tutorial voor microprocessors

4.1 Inleiding

De 6502-microprocessor werd uitgebracht in 1975. Hij werd toen gebruikt als microprocessor voor sommige personal computers, zoals Apple II, Commodore 64 en BBC Micro.







De 6502-microprocessor wordt nog steeds in grote aantallen geproduceerd. Het is niet langer een centrale verwerkingseenheid die tegenwoordig in personal computers (laptops) wordt gebruikt, maar wordt nog steeds in grote aantallen geproduceerd en tegenwoordig in elektronische en elektrische apparaten gebruikt. Om de modernere computerarchitecturen te begrijpen, is het erg nuttig om een ​​oudere maar behoorlijk succesvolle microprocessor zoals de 6502 te onderzoeken.



Omdat het eenvoudig te begrijpen en te programmeren is, is het een van de beste (zo niet de beste) microprocessors om te gebruiken voor het onderwijzen van assembleertaal. Assembleertaal is een taal op laag niveau die kan worden gebruikt om een ​​computer te programmeren. Merk op dat de assembleertaal voor één microprocessor verschilt van de assembleertaal van een andere microprocessor. In dit hoofdstuk wordt de assembleertaal voor de microprocessor 6502 onderwezen. Om precies te zijn, het is de 65C02 die wordt aangeleerd, maar waarnaar eenvoudigweg wordt verwezen als de 6502.



Een beroemde computer uit het verleden heet de commodore_64. De 6502 is een microprocessor uit de 6500-familie. De commodore_64 computer gebruikt de 6510 microprocessor. De 6510 microprocessor is van de 6500 µP. De instructieset van de 6502 µP bestaat uit bijna alle instructies van de 6510 µP. De kennis van dit hoofdstuk en het volgende is gebaseerd op de commodore_64 computer. Deze kennis wordt gebruikt als basis om de moderne computerarchitecturen en moderne besturingssystemen uit te leggen in dit deel van de online carrièrecursus.





Computerarchitectuur verwijst naar de componenten van het moederbord van de computer en een uitleg van hoe de gegevens binnen elke component stromen, vooral de microprocessor, hoe de gegevens tussen de componenten stromen, en ook hoe de gegevens op elkaar inwerken. Het enkelvoud voor data is datum. Een effectieve manier om de computerarchitectuur van een computer te bestuderen, is door de assembleertaal van het moederbord te bestuderen.

Er wordt gezegd dat de commodore_64 computer een computer is met 8-bits computerwoorden. Dit betekent dat de informatie wordt opgeslagen, overgedragen en gemanipuleerd in de vorm van acht-bits binaire codes.



Blokdiagram van het Commodore 64 moederbord
Het blokschema van het Commodore 64 moederbord is:


Fig 4.1 Blokdiagram van de Commodore_64 systeemeenheid

Stel je de 6510-microprocessor voor als de 6502-microprocessor. Het totale geheugen is een reeks bytes (8 bits per byte). Er is een willekeurig toegankelijk (lees-/schrijf)geheugen waarnaar de bytes kunnen worden geschreven of gewist. Wanneer de stroom van de computer wordt uitgeschakeld, wordt alle informatie in het Random Access Memory (RAM) gewist. Er is ook het alleen-lezen geheugen (ROM). Wanneer de stroom van de computer wordt uitgeschakeld, blijft de informatie in het ROM aanwezig (wordt niet gewist).

Er is een invoer-/uitvoerpoort (circuit), die in het diagram de invoer-/uitvoerapparaten wordt genoemd. Deze poort moet niet worden verward met de poorten die zichtbaar zijn aan de linker-en-rechts of voor-en-achter verticale oppervlakken van de computersysteemeenheid. Dat zijn twee verschillende dingen. De verbindingen van deze binnenpoort naar de randapparatuur zoals de harde schijf (of diskette), toetsenbord en monitor zijn niet weergegeven in het diagram.

Er zijn drie bussen (groepen elektrische zeer kleine draadgeleiders) in het diagram. Elke draad kan een bit 1 of bit 0 overbrengen. De databus, voor de overdracht van acht bits per keer (één klokpuls) naar het RAM en de invoer-/uitvoerpoort (invoer-/uitvoerapparaten) is bidirectioneel. De databus is acht bits breed.

Alle componenten zijn aangesloten op de adresbus. De adresbus is unidirectioneel vanaf de microprocessor. Er zijn zestien geleiders voor de adresbus, die elk één bit (1 of 0) dragen. In één klokpuls worden zestien bits verzonden.

Daar is de controlebus. Sommige geleiders van de besturingsbus zouden elk een bit van de microprocessor naar de andere componenten overbrengen. Een paar besturingslijnen transporteren de bits van de invoer/uitvoer (IO)-poort naar de microprocessor.

Computer geheugen
Het RAM en ROM worden beschouwd als één geheugensamenstel. Dit samenstel wordt schematisch als volgt weergegeven, waarbij hexadecimale getallen het voorvoegsel “$” hebben:


Fig 4.11 Geheugenindeling voor de Commodore 64 computer

Het RAM-geheugen is van 0000 16 naar DFFF 16 die wordt geschreven vanaf $0000 tot $DFFF. Bij de 6502 µP-assembleertaal wordt een hexadecimaal getal voorafgegaan door “$” en niet voorzien van een achtervoegsel (met subscript) met 16 of H of hex. Alle informatie in het RAM-geheugen verdwijnt als de computer wordt uitgeschakeld. De ROM begint van $E000 tot $FFFF. Het heeft subroutines die niet afgaan als de computer wordt uitgeschakeld. Deze subroutines zijn de veelgebruikte routines die helpen bij het programmeren. Het gebruikersprogramma roept ze op (zie volgend hoofdstuk).

De ruimte (bytes) van $0200 tot $D000 is voor de gebruikersprogramma's. De ruimte tussen $D000 en $DFFF is voor informatie die rechtstreeks verband houdt met de randapparatuur (invoer-/uitvoerapparaten). Dit is onderdeel van het besturingssysteem. Het besturingssysteem van de Commodore-64 computer bestaat dus uit twee hoofddelen: het deel in het ROM dat nooit uitgaat en het deel van $D000 tot $DFFF dat uitgaat als de stroom wordt uitgeschakeld. Deze IO-gegevens (invoer/uitvoer) moeten elke keer dat de computer wordt ingeschakeld van een schijf worden geladen. Tegenwoordig worden dergelijke gegevens perifere factoren genoemd. De randapparatuur begint bij de Input/Output Device-poort via de aansluitingen op het moederbord naar de identificeerbare poorten op de verticale oppervlakken van de computer waarop de monitor, het toetsenbord, enz. zijn aangesloten en op de randapparatuur zelf (monitor, toetsenbord, enz. .).

Het geheugen bestaat uit 2 16 = 65.536 bytelocaties. In hexadecimale vorm zijn dit 10.000 16 = 10000 H = 10000 hex = $ 10.000 locaties. Bij computergebruik begint het tellen in grondtal twee, grondtal tien, grondtal zestien, etc. vanaf 0 en niet vanaf 1. De eerste locatie is dus eigenlijk het locatienummer 0000000000000000 2 = 0 10 = 0000 16 = $0000. In de 6502 µP-assembleertaal wordt de identificatie van een adreslocatie voorafgegaan door $ en is er geen achtervoegsel of subscript. De laatste locatie is het locatienummer 1111111111111111 2 = 65.535 10 = FFFF 16 = $FFFF en niet 10000000000000000 2 , of 65.536 10 , of 10000 16 , of $ 10.000. De 10000000000000000 2 , 65.536 10 , 10000 16 , of $10000 geeft het totale aantal bytelocaties.

Hier, 2 16 = 65.536 = 64 x 1024 = 64 x 2 10 = 64 Kbytes (Kilobytes). Het achtervoegsel 64 in de naam Commodore-64 betekent 64 KB totaal geheugen (RAM en ROM). Een byte bestaat uit 8 bits en de 8 bits worden op één bytelocatie in het geheugen geplaatst.

De 64 Kbyte geheugen is verdeeld in pagina's. Elke pagina heeft 0100 16 = 256 10 byte-locaties. De eerste 256 10 = eerste 0100 16 locaties is pagina 0. De tweede is pagina 1, de derde is pagina 2, enzovoort.

Om de 65.536 locaties te kunnen adresseren zijn per locatie (adres) 16 bits nodig. De adresbus van de microprocessor naar het geheugen bestaat dus uit 16 lijnen; één regel voor één bit. Een bit is 1 of 0.

De 6502 µP-registers
Een register lijkt op de bytecellen voor een bytegeheugenlocatie. De 6502 µP heeft zes registers: vijf 8-bit registers en één 16-bit register. Het 16-bits register wordt de programmateller genoemd, afgekort als PC. Het bevat het geheugenadres voor de volgende instructie. Een assembleertaalprogramma bestaat uit instructies die in het geheugen worden geplaatst. Er zijn zestien (16) verschillende bits nodig om een ​​bepaalde bytelocatie in het geheugen te adresseren. Bij een bepaalde klokpuls worden deze bits naar de 16-bits adreslijnen van de adresbus gestuurd voor het lezen van een instructie. Alle registers voor de 6502 µP worden als volgt weergegeven:


Afb. 4.12 6502 µP-registers

De programmateller of pc kan in het diagram worden gezien als een 16-bits register. De lagere significante acht bits worden aangeduid als PCL voor Program Counter Low. De hogere significante acht bits worden aangeduid als PCH voor Program Counter High. Een instructie in het geheugen voor Commodore-64 kan uit één, twee of drie bytes bestaan. De 16 bits in de PC verwijzen naar de volgende uit te voeren instructie in het geheugen. Van de circuits in de microprocessor worden er twee Arithmetic Logic Unit en Instruction Decoder genoemd. Als de huidige instructie die in de µP (microprocessor) wordt verwerkt één byte lang is, verhogen deze twee circuits de PC voor de volgende instructie met 1 eenheid. Als de huidige instructie die in de µP wordt verwerkt twee bytes lang is, wat betekent dat deze twee opeenvolgende bytes in het geheugen in beslag neemt, vergroten deze twee circuits de pc voor de volgende instructie met 2 eenheden. Als de huidige instructie die in de µP wordt verwerkt drie bytes lang is, wat betekent dat deze drie opeenvolgende bytes in het geheugen in beslag neemt, vergroten deze twee circuits de pc voor de volgende instructie met 3 eenheden.

De accumulator “A” is een acht-bits register voor algemene doeleinden waarin het resultaat van de meeste rekenkundige en logische bewerkingen wordt opgeslagen.

De registers “X” en “Y” worden elk gebruikt om de programmastappen te tellen. Het tellen bij het programmeren begint vanaf 0. Ze worden dus indexregisters genoemd. Ze hebben nog een paar andere doeleinden.

Hoewel het Stack Pointer-register, 'S' 9 bits heeft, wat wordt beschouwd als een acht-bits register. De inhoud ervan verwijst naar een bytelocatie op pagina 1 van het Random Access Memory (RAM). Pagina 1 begint vanaf byte $0100 (256 10 ) naar byte $01FF (511 10 ). Wanneer een programma actief is, gaat het van de ene instructie naar de volgende opeenvolgende instructie in het geheugen. Dit is echter niet altijd het geval. Er zijn momenten waarop het van het ene geheugengebied naar het andere geheugengebied springt om daar de instructies achtereenvolgens uit te voeren. Pagina 1 in RAM wordt gebruikt als stapel. De stapel is een groot RAM-geheugengebied met de volgende adressen voor de voortzetting van de code van waaruit een sprong plaatsvindt. De codes met springinstructies staan ​​niet in de stapel; ze bevinden zich elders in het geheugen. Nadat de jump-to-instructies zijn uitgevoerd, bevinden de vervolgadressen (geen codesegmenten) zich echter in de stapel. Ze werden daarheen geduwd als gevolg van de sprong- of aftakkingsinstructies.

Het acht-bits processorstatusregister van P is een speciaal soort register. De afzonderlijke bits zijn niet gerelateerd of met elkaar verbonden. Elk bit daar wordt een vlag genoemd en wordt onafhankelijk van de andere gewaardeerd. De betekenis van de vlaggen wordt hieronder gegeven als dat nodig is.

De eerste en laatste bitindex voor elk register zijn boven elk register in het vorige diagram aangegeven. Het tellen van de bitindex (positie) in een register begint vanaf 0 aan de rechterkant.

Geheugenpagina's in binair, hexadecimaal en decimaal
De volgende tabel toont het begin van de geheugenpagina's in binair, hexadecimaal en decimaal:

Elke pagina heeft 1.000.0000 2 aantal bytes dat gelijk is aan 100 H aantal bytes dat hetzelfde is als 256 10 aantal bytes. In het vorige geheugendiagram worden de pagina's aangegeven vanaf pagina 0, en niet vanaf pagina 0, zoals aangegeven in de tabel.

De binaire, hexadecimale en decimale kolommen van deze tabel geven de geheugenbytelocatieadressen in hun verschillende bases. Merk op dat voor pagina nul alleen de bits voor de onderste byte nodig zijn om te typen bij het coderen. De bits voor de hogere byte kunnen worden weggelaten omdat deze altijd nullen zijn (voor pagina nul). Voor de rest van de pagina's moeten de bits voor de hogere byte worden gebruikt.

In de rest van dit hoofdstuk wordt de 6502 µP-assembleertaal uitgelegd met behulp van alle voorgaande informatie. Om de taal snel te begrijpen, moet de lezer optellen en aftrekken met grondtal zestien in plaats van grondtal tien. Eigenlijk zou het grondtal twee moeten zijn, maar het berekenen in grondtal twee is omslachtig. Onthoud dat wanneer je twee getallen optelt in basis twee, een carry nog steeds 1 is, net als in basis tien. Maar als je twee getallen in basis twee aftrekt, is een lening twee en niet tien zoals in basis tien. Als je twee getallen optelt in basis zestien, is een carry nog steeds 1, net als in basis tien. Maar als je twee getallen in basis zestien aftrekt, is een lening zestien en niet tien zoals in basis tien.

4.2 Instructies voor gegevensoverdracht

Bekijk de volgende tabel met instructies voor gegevensoverdracht in de assembleertaal voor de 6502 µP:

Wanneer een byte (8 bits) wordt gekopieerd van een geheugenbytelocatie naar het accumulatorregister, het X-register of het Y-register, wordt dat geladen. Wanneer een byte uit een van deze registers naar een geheugenbytelocatie wordt gekopieerd, is er sprake van overdracht. Wanneer een byte van het ene register naar het andere wordt gekopieerd, is er nog steeds sprake van overdracht. In de tweede kolom van de tabel geeft de pijl de richting van de kopie voor een byte aan. De rest van de vier kolommen tonen verschillende adresseringsmodi.

Een vermelding in de adresseringsmoduskolom is de feitelijke bytecode voor het overeenkomstige geheugensteuntje van de instructie in hexadecimaal. AE is bijvoorbeeld de feitelijke bytecode voor LDX, die een byte uit het geheugen naar het X-register moet laden in absolute adresseringsmodus zoals AE 16 = 10101110 2 . De bits voor LDX op een geheugenbytelocatie zijn dus 10101110.

Merk op dat er voor het LDX-geheugengedeelte van de instructie drie mogelijke bytes zijn: A2, AE en A6, en elk is voor een bepaalde adresseringsmodus. Wanneer de byte die in het X-register wordt geladen, niet van een geheugenbytelocatie mag worden gekopieerd, moet de waarde (net na) het LDX-mnemonic in de instructie in hexadecimaal of decimaal worden getypt. In dit hoofdstuk worden dergelijke waarden in hexadecimaal getypt. Dit is directe adressering, dus de werkelijke byte in het geheugen die LDX vertegenwoordigt, is A2 16 = 10100010 2 en niet AE 16 wat gelijk is aan 10101110 2 .

In de tabel worden alle bytes onder de adresseringsmoduskoppen Operatiecodes genoemd, afgekort als opcodes. Er kan meer dan één opcode voor één geheugensteuntje zijn, afhankelijk van de adresseringsmodus.

Opmerking: Het woord 'laden' in de computersysteemeenheid kan twee betekenissen hebben: het kan verwijzen naar het laden van een bestand van een schijf naar het geheugen van de computer, of het kan verwijzen naar het overbrengen van een byte van een geheugenbytelocatie naar een microprocessorregister. .

Er zijn meer adresseringsmodi dan de vier in de tabel voor de 6502 µP.

Tenzij anders vermeld, begint alle gebruikersprogrammeringscode in dit hoofdstuk vanaf adres 0200 16 dit is het begin van het gebruikersgebied in het geheugen.

Geheugen M en accu A

Geheugen naar accu

Onmiddellijke adressering
De volgende instructie slaat het nummer FF op 16 = 255 10 in de accu:

LDA#$FF

De “$” wordt niet alleen gebruikt om een ​​geheugenadres te identificeren. Over het algemeen wordt het gebruikt om aan te geven dat het volgende getal dat volgt hexadecimaal is. In dit geval is $FF niet het adres van een geheugenbytelocatie. Het is het nummer 255 10 in hexadecimaal. De basis 16 of een van de andere equivalente subscripts mag niet in de assembleertaalinstructie worden geschreven. De “#” geeft aan dat wat daarna volgt de waarde is die in het accumulatorregister moet worden geplaatst. De waarde kan ook in het grondtal tien worden geschreven, maar dat wordt in dit hoofdstuk niet gedaan. De “#” betekent onmiddellijke adressering.

Een ezelsbruggetje heeft enige gelijkenis met de overeenkomstige Engelse uitdrukking. “LDA #$FF” betekent: laad het nummer 255 10 in de accumulator A. Aangezien dit een directe adressering uit de vorige tabel is, is LDA A9 en niet AD of A5. A9 in binair getal is 101010001. Dus als A9 voor LDA zich in het $0200-adres in het geheugen bevindt, is $FF $0301 = 0300 + 1 adres. De #$FF is precies de operand voor het LDA-ezelsbruggetje.

Absolute adressering
Als de waarde van $FF zich op de locatie $0333 in het geheugen bevindt, is de vorige instructie:

LDA $ 0333

Let op de afwezigheid van #. In dit geval betekent de afwezigheid van # dat wat volgt een geheugenadres is en niet de waarde van belang (niet de waarde die in de accumulator moet worden geplaatst). Dus de opcode voor LDA is deze keer AD en niet A9 of A5. De operand voor LDA is hier het adres $0333 en niet de waarde $FF. $FF bevindt zich op een locatie van $0333, wat nogal ver weg is. De instructie “LDA $0333” neemt drie opeenvolgende locaties in het geheugen in beslag, en niet twee, zoals in de vorige illustratie. “AD” voor LDA bevindt zich op de $0200-locatie. De onderste byte van 0333, namelijk 33, bevindt zich op de locatie $0301. De hogere byte van $0333, namelijk 03, bevindt zich op de locatie $0302. Dit is weinig endianness dat wordt gebruikt door de 6502-assembleertaal. De assembleertalen van verschillende microprocessors zijn verschillend.

Dit is een voorbeeld van absolute adressering. De $0333 is het adres van de locatie met $FF. De instructie bestaat uit drie opeenvolgende bytes en bevat niet de $FF of de werkelijke bytelocatie ervan.

Zero-Page-adressering

Stel dat de waarde $FF zich in de geheugenlocatie $0050 op pagina nul bevindt. De bytelocaties voor de nulpagina beginnen bij $0000 en eindigen bij $00FF. Dit zijn 256 10 locaties in totaal. Elke pagina van het Commodore-64-geheugen is 256 10 lang. Merk op dat de hogere byte nul is voor alle mogelijke locaties in de nulpaginaruimte in het geheugen. De nulpagina-adresseringsmodus is hetzelfde als de absolute adresseringsmodus, maar de hogere byte van 00 wordt niet in de instructie getypt. Dus om de $FF van de $0050-locatie in de accumulator te laden, is de nulpagina-adresseringsmodusinstructie:

LDA $ 50

Omdat LDA A5 is en niet A9 of AD, A5 16 = 10100101 2 . Onthoud dat elke byte in het geheugen uit 8 cellen bestaat en dat elke cel een bit bevat. De instructie bestaat hier uit twee opeenvolgende bytes. A5 voor LDA bevindt zich op de geheugenlocatie $0200 en het adres van $50, zonder de hogere byte van 00, bevindt zich op de locatie $0301. De afwezigheid van 00, die een byte in het totale geheugen van 64K zou hebben verbruikt, bespaart de geheugenruimte.

Accumulator naar geheugen

Absolute adressering
De volgende instructie kopieert een bytewaarde, wat deze ook is, van de accumulator naar de geheugenlocatie van $1444:

ZE ZIJN $ 1444

Er wordt gezegd dat dit wordt overgedragen van de accu naar het geheugen. Het wordt niet geladen. Laden is het tegenovergestelde. De opcodebyte voor STA is 8D 16 = 10001101 2 . Deze instructie bestaat uit drie opeenvolgende bytes in het geheugen. De 8D 16 bevindt zich op de locatie van $ 0200. De 44 16 van het adres $1444 bevindt zich op locatie $0201. En 14 16 bevindt zich op de locatie $0202 – weinig endianness. De feitelijke byte die wordt gekopieerd, maakt geen deel uit van de instructie. Voor STA wordt hier 8D en niet 85 voor nulpagina-adressering (in de tabel) gebruikt.

Nulpagina-adressering
De volgende instructie kopieert een bytewaarde, wat deze ook is, van de accumulator naar de geheugenlocatie van $0050 op pagina nul:

STA $0050

De opcodebyte voor STA is hier 85 16 = 10000101 2 . Deze instructie bestaat uit twee opeenvolgende bytes in het geheugen. De 85 16 bevindt zich op locatie $0200. De 50 16 van het adres $0050 bevindt zich op locatie $0201. De kwestie van endianness doet zich hier niet voor omdat het adres slechts één byte heeft, namelijk de lagere byte. De feitelijke byte die wordt gekopieerd, maakt geen deel uit van de instructie. Voor STA worden hier 85 en niet 8D voor nulpagina-adressering gebruikt.

Het heeft geen zin om de onmiddellijke adressering te gebruiken om een ​​byte van de accumulator naar een locatie in het geheugen over te brengen. Dit komt omdat de werkelijke waarde, zoals $FF, in de instructie bij onmiddellijke adressering moet worden vermeld. Een directe adressering is dus niet mogelijk bij de overdracht van een bytewaarde van een register in de µP naar een willekeurige geheugenlocatie.

LDX-, STX-, LDY- en STY-ezelsbruggetjes
LDX en STX zijn vergelijkbaar met respectievelijk LDA en STA. Maar hier wordt het X-register gebruikt en niet het A-register (accumulator). LDY en STY zijn respectievelijk vergelijkbaar met LDA en STA. Maar hier wordt het Y-register gebruikt en niet het A-register. Raadpleeg Tabel 4.21 voor elke opcode in hexadecimaal die overeenkomt met een bepaald geheugensteuntje en een bepaalde adresseringsmodus.

Overdrachten van register naar register
De voorgaande twee sets instructies in Tabel 4.21 hebben betrekking op het kopiëren van geheugen/microprocessor-register (overdracht) en register/register kopiëren (overdracht). De TAX-, TXA-, TAY-, TYA-, TSX- en TXS-instructies verzorgen het kopiëren (overbrengen) van het register in de microprocessor naar een ander register van dezelfde microprocessor.

Om de byte van A naar X te kopiëren, is de instructie:

BELASTING

Om de byte van X naar A te kopiëren, is de instructie:

TX

Om de byte van A naar Y te kopiëren, is de instructie:

HAND

Om de byte van Y naar A te kopiëren, is de instructie:

TYA

Voor de Commodore 64 computer is de stapel pagina 1 net na pagina 0 in het geheugen. Net als elke andere pagina bestaat deze uit 25610 10 bytelocaties, van $0100 tot $01FF. Normaal gesproken wordt een programma van de ene instructie naar de volgende opeenvolgende instructie in het geheugen uitgevoerd. Van tijd tot tijd is er een sprong naar een ander geheugencodesegment (set instructies). Het stapelgebied in het geheugen (RAM) heeft de volgende instructieadressen vanaf waar de sprongen (of vertakkingen) ophielden voor de voortzetting van het programma.

De stapelwijzer “S” is een 9-bits register in de 6502 µP. Het eerste bit (meest linkse) is altijd 1. Alle bytelocatieadressen op pagina één beginnen met 1, gevolgd door 8 verschillende bits voor de 256 10 locaties. De stackpointer heeft het adres van de locatie op pagina 1, die het adres heeft van de volgende instructie die het programma moet retourneren en waarmee verder moet gaan na het uitvoeren van het huidige (waar naartoe gesprongen) codesegment. Omdat het eerste bit van alle adressen van de stapel (pagina één) met 1 begint, hoeft het stapelwijzerregister alleen de resterende acht bits te bevatten. Het eerste bit, het meest linkse bit (het negende bit vanaf de rechterkant), is immers altijd 1.

Om de byte van S naar X te kopiëren, is de instructie:

TSX

Om de byte van X naar S te kopiëren, is de instructie:

tekst

De register-naar-register-instructies gebruiken geen enkele operand. Ze bestaan ​​alleen uit het geheugensteuntje. Elk ezelsbruggetje heeft zijn opcode in hexadecimaal. Dit bevindt zich in de impliciete adresseringsmodus omdat er geen operand is (geen geheugenadres, geen waarde).

Opmerking: Er vindt geen overdracht van X naar Y of Y naar X plaats (kopiëren).

4.3 Rekenkundige bewerkingen

Het circuit, Arithmetic Logic Unit in de 6502 µP, kan slechts twee getallen van 8 bits tegelijk optellen. Er wordt niet afgetrokken, er wordt niet vermenigvuldigd en er wordt niet gedeeld. De volgende tabel toont de opcodes en adresseringsmodi voor rekenkundige bewerkingen:

Opmerking: Alle geheugensteuntjes voor rekenkundige bewerkingen en andere soorten bewerkingen (dat wil zeggen alle 6502 geheugensteuntjes) nemen één byte bewerkingscode (op) in beslag. Als er meer dan één adresseringsmodus is voor het geheugensteuntje, zouden er verschillende opcodes zijn voor hetzelfde geheugensteuntje: één per adresseringsmodus. De C, D en V in de tabel zijn de vlaggen van het statusregister. Hun betekenis zal later worden gegeven als dat nodig is.

Toevoeging van niet-ondertekende nummers
Bij de 6502 µP zijn de getallen met teken twee-complementgetallen. De niet-ondertekende getallen zijn gewone positieve getallen die vanaf nul beginnen. Dus voor een byte van acht bits is het kleinste getal zonder teken 00000000 2 = 0 10 = 00 16 en het grootste niet-ondertekende nummer is 11111111 2 = 255 10 = FF 16 . Voor twee niet-ondertekende nummers is de toevoeging:

A+M+C →A

Dat betekent dat de 8-bits inhoud van de accumulator door de rekenkundige logische eenheid wordt opgeteld bij een byte (8-bits) uit het geheugen. Na de toevoeging van A en M gaat de overdracht naar de negende bit naar de overdrachtvlagcel in het statusregister. Elke eerdere carry-bit van een eerdere optelling die zich nog in de carry-vlagcel in het statusregister bevindt, wordt ook opgeteld bij de som van A en M, waardoor A+M+C →A ontstaat. Het resultaat wordt terug in de accumulator gestopt.

Als de bijtelling van rente:

A + M

En het is niet nodig om een ​​eerdere carry toe te voegen, de carry-vlag moet worden gewist en wordt op 0 gezet, zodat de toevoeging is:

A+M+0 →A hetzelfde als A+M →A

Opmerking: Als M wordt opgeteld bij A, vindt er een overdracht van 1 plaats omdat het resultaat groter is dan 255 10 = 11111111 2 = FF 16 , dit is een nieuwe uitvoering. Deze nieuwe carry van 1 wordt automatisch naar de carry-vlagcel gestuurd voor het geval dit nodig is voor het volgende paar van acht bits dat moet worden opgeteld (nog een A + M).

Code om twee niet-ondertekende acht-bits toe te voegen
00111111 2 +00010101 2 is hetzelfde als 3F 16 + 15 16 dat is hetzelfde als 63 10 +21 10 . Het resultaat is 010101002 2 dat is hetzelfde als 54 16 en 84 10 . Het resultaat komt niet boven het maximale aantal voor acht bits, namelijk 255 10 = 11111111 2 = FF 16 . Er is dus geen resulterende carry van 1. Anders gezegd: de resulterende carry is 0. Vóór de optelling is er geen eerdere carry van 1. Met andere woorden: de vorige carry is 0. De code om deze optelling uit te voeren kan zijn:

CLC
LDA#$3F
ADC#$15

Opmerking: Tijdens het typen van de assembleertaal wordt aan het einde van elke instructie de “Enter”-toets van het toetsenbord ingedrukt. Er zijn drie instructies in deze code. De eerste instructie (CLC) wist de carry-vlag in het geval dat een eerdere optelling 1 heeft. CLC kan alleen worden uitgevoerd in de impliciete adresseringsmodus. Het geheugensteuntje voor de impliciete adresseringsmodus heeft geen operand. Dit maakt de carry-cel van het statusregister van P leeg. Clearing betekent dat de bit 0 aan de carry-vlagcel wordt gegeven. De volgende twee instructies in de code gebruiken de directe adresseringsmodus. Bij onmiddellijke adressering is er slechts één operand voor het geheugensteuntje, namelijk een getal (en noch een geheugen- noch een registeradres). En dus moet het nummer worden voorafgegaan door '#'. De “$” betekent dat het volgende getal hexadecimaal is.

De tweede instructie laadt het getal 3F 16 in de accu. Voor de derde instructie neemt het rekenkundige logische eenheidscircuit van de µP de vorige (gewiste) carry van 0 (geforceerd naar 0) van de carry-vlagcel van het statusregister en telt deze op bij 15 16 evenals op de waarde die al in de 3F zit 16 accumulator en plaatst het volledige resultaat terug in de accumulator. In dit geval is er een resulterende carry van 0. De ALU (Arithmetic Logic Unit) verzendt (zet) 0 naar de carry-vlagcel van het statusregister. Het processorstatusregister en het statusregister betekenen hetzelfde. Als een carry van 1 resulteerde, stuurt de ALU 1 naar de carry-vlag van het statusregister.

De drie regels voorgaande code moeten in het geheugen staan ​​voordat ze worden uitgevoerd. De opcode 1816 voor CLC (impliciete adressering) bevindt zich op een bytelocatie van $0200. De opcode A9 16 voor LDA (onmiddellijke adressering) bevindt zich op een bytelocatie van $0201. Het getal 3F 10 bevindt zich op een bytelocatie van $0202. De opcode 69 16 voor LDA (onmiddellijke adressering) bevindt zich op een bytelocatie van $0203. Het getal 15 10 bevindt zich op een bytelocatie van $0204.

Opmerking: LDA is een overdrachtsinstructie (laadinstructie) en geen rekeninstructie (ezelsbruggetje).

Code om twee niet-ondertekende zestien bits toe te voegen
Alle registers in de 6502 µP zijn in essentie 8-bits registers, behalve de PC (Program Counter), die 16-bits is. Zelfs het statusregister is 8 bits breed, hoewel de acht bits niet samen werken. In deze sectie wordt de toevoeging van twee 16 bits zonder teken, met een overdracht van het eerste paar van acht bits naar het tweede paar van acht bits, beschouwd. De van belang zijnde carry is de carry van de achtste bitpositie naar de negende bitpositie.

Laat de cijfers 0010101010111111 zijn 2 = 2ABF16 16 = 10.943 10 en 0010101010010101 2 = 2A95 16 = 10.901 10 . De som is 0101010101010100 2 = 5554 16 = 21.844 10 .

Het toevoegen van deze twee niet-ondertekende getallen in basis twee gaat als volgt:

De volgende tabel toont dezelfde toevoeging met de overdracht van 1 van de achtste bit naar de negende bitpositie, beginnend van rechts:

Bij het coderen hiervan worden de twee lagere bytes eerst toegevoegd. Vervolgens verzendt de ALU (Arithmetic Logic Unit) de overdracht van 1 van de achtste bitpositie naar de negende bitpositie naar de overdrachtvlagcel in het statusregister. Het resultaat van 0 1 0 1 0 1 0 0 zonder de carry gaat naar de accumulator. Vervolgens wordt het tweede paar bytes toegevoegd met de carry. Het ADC-ezelsbruggetje betekent dat automatisch wordt toegevoegd aan de vorige carry. In dit geval mag de vorige carry, die 1 is, niet worden gewijzigd vóór de tweede toevoeging. Voor de eerste optelling moet, aangezien een eerdere carry geen deel uitmaakt van deze volledige optelling, deze worden gewist (op 0 gezet).

Voor de volledige optelling van de twee paren bytes is de eerste toevoeging:

A + M + 0 -> EEN

De tweede toevoeging is:

A + M + 1 -> EEN

De carry-vlag moet dus vlak voor de eerste toevoeging worden gewist (gegeven waarde 0). Het volgende programma waarvan de lezer de onderstaande uitleg moet lezen, gebruikt voor deze optelling de absolute adresseringsmodus:

CLC
LDA $ 0213
ADC $ 0215
; geen clearing omdat de carry-vlagwaarde nodig is
STA $0217
LDA $ 0214
ADC $ 0216
STA $0218

Merk op dat bij de 6502-assembleertaal een puntkomma een commentaar begint. Dit betekent dat bij de uitvoering van het programma de puntkomma en alles aan de rechterkant ervan worden genegeerd. Het programma dat eerder is geschreven, wordt in een tekstbestand opgeslagen met de naam van de programmeur naar keuze en met de extensie “.asm”. Het vorige programma is niet het exacte programma dat naar het geheugen gaat voor uitvoering. Het corresponderende programma in het geheugen wordt het vertaalde programma genoemd, waarbij de geheugensteuntjes worden vervangen door de opcodes (bytes). Eventuele opmerkingen blijven in het tekstbestand in de assembleertaal staan ​​en worden verwijderd voordat het vertaalde programma het geheugen bereikt. In feite zijn er vandaag de dag twee bestanden op de schijf opgeslagen: het “.asm”-bestand en het “.exe”-bestand. Het “.asm”-bestand is het bestand in de vorige afbeelding. Het “.exe”-bestand is het “.asm”-bestand waarvan alle opmerkingen zijn verwijderd en alle geheugensteuntjes zijn vervangen door hun opcodes. Wanneer het in een teksteditor wordt geopend, is het bestand “.exe” onherkenbaar. Tenzij anders vermeld, wordt voor de doeleinden van dit hoofdstuk het “.exe”-bestand naar het geheugen gekopieerd, beginnend vanaf de $0200-locatie. Dit is de andere betekenis van laden.

De twee toe te voegen 16-bits getallen bezetten vier bytes in het geheugen voor absolute adressering: twee bytes per getal (geheugen is een reeks bytes). Bij absolute adressering bevindt de operand van de opcode zich in het geheugen. Het optelresultaat is twee bytes breed en moet ook in het geheugen worden geplaatst. Dit geeft een totaal van 6 10 = 6 16 bytes voor invoer en uitvoer. De invoer komt niet van het toetsenbord en de uitvoer komt niet van de monitor of printer. De invoer bevindt zich in het geheugen (RAM) en de uitvoer (sommeringsresultaat) gaat in deze situatie terug naar het geheugen (RAM).

Voordat een programma wordt uitgevoerd, moet de vertaalde versie eerst in het geheugen staan. Als je naar de vorige programmacode kijkt, kun je zien dat de instructies zonder commentaar 19 vormen 10 = 13 16 bytes. Het programma neemt dus van $0200 bytelocatie in het geheugen naar $0200 + $13 – $1 = $0212 bytelocaties (beginnend bij $0200 en niet $0201, wat impliceert – $1). Door de 6 bytes voor de invoer- en uitvoernummers op te tellen, eindigt het hele programma op $0212 + $6 = $0218. De totale lengte van het programma is 19 16 = 25 10 .

De lagere byte van de augend moet zich in het $0213-adres bevinden, en de hogere byte van dezelfde augend moet zich in het $0214-adres bevinden - weinig endianness. Op dezelfde manier zou de lagere byte van de addend zich in het $0215-adres moeten bevinden, en de hogere byte van dezelfde addend zou zich in het $0216-adres moeten bevinden - weinig endianness. De lagere byte van het resultaat (som) moet in het $0217-adres staan, en de hogere byte van hetzelfde resultaat moet in het $0218-adres staan ​​– weinig endianness.

De opcode 18 16 voor CLC (impliciete adressering) bevindt zich op de bytelocatie $0200. De opcode voor “LDA $0213”, d.w.z. AD 16 voor LDA (absolute adressering), bevindt zich op de bytelocatie $0201. De onderste byte van de augend, die 10111111 is, bevindt zich in de geheugenbytelocatie $0213. Houd er rekening mee dat elke opcode één byte in beslag neemt. Het “$0213”-adres van “LDA $0213” bevindt zich op de bytelocaties $0202 en $0203. De instructie “LDA $0213” laadt de onderste byte van de augend naar de accumulator.

De opcode voor “ADC $0215”, d.w.z. 6D 16 voor ADC (absolute adressering), bevindt zich op de bytelocatie $0204. De onderste byte van de addend, namelijk 10010101, bevindt zich op de bytelocatie $0215. Het adres “$0215” van “ADC $0215” bevindt zich op de bytelocaties $0205 en $0206. De instructie “ADC $0215” voegt de onderste byte van de addend toe aan de onderste byte van de augend die zich al in de accumulator bevindt. Het resultaat wordt terug in de accu geplaatst. Elke carry na het achtste bit wordt naar de carry-vlag van het statusregister gestuurd. De carry-vlagcel mag niet worden gewist vóór de tweede toevoeging van de hogere bytes. Deze carry wordt automatisch opgeteld bij de som van de hogere bytes. In feite wordt aan het begin automatisch een carry van 0 toegevoegd aan de som van de lagere bytes (equivalent aan het toevoegen van geen carry) vanwege CLC.

De opmerking duurt de volgende 48 10 = 30 16 bytes. Dit blijft echter alleen in het tekstbestand “.asm”. Het bereikt het geheugen niet. Het wordt verwijderd door de vertaling die wordt gedaan door de assembler (een programma).

Voor de volgende instructie, die “STA $0217” is, is de opcode van STA 8D 16 (absolute adressering) bevindt zich op de bytelocatie $0207. Het adres “$0217” van “STA $0217” bevindt zich in de geheugenlocaties $0208 en $0209. De instructie “STA $0217” kopieert de acht-bits inhoud van de accumulator naar de geheugenlocatie $0217.

De hogere byte van de augend, die 00101010 is, bevindt zich in de geheugenlocatie van $0214, en de hogere byte van de addend, die 00101010 is, bevindt zich in de bytelocatie van $02 16 . De opcode voor “LDA $0214”, wat AD16 is voor LDA (absolute adressering), bevindt zich in de bytelocatie $020A. Het adres “$0214” van “LDA $0214” bevindt zich op de locaties $020B en $020C. De instructie “LDA $0214” laadt de hogere byte van de augend naar de accumulator, waardoor alles wat zich in de accumulator bevindt wordt gewist.

De opcode voor “ADC $0216” is 6D 16 voor ADC (absolute adressering) bevindt zich op de bytelocatie $020D. Het adres “$0216” van “ADC 0216” bevindt zich op de bytelocaties $020E en $020F. De instructie “ADC $0216” voegt de hogere byte van de addend toe aan de hogere byte van de augend die zich al in de accumulator bevindt. Het resultaat wordt terug in de accumulator geplaatst. Als er een carry van 1 is, wordt deze voor deze tweede toevoeging automatisch in de carrycel van het statusregister geplaatst. Hoewel de carry voorbij het zestiende bit (links) niet vereist is voor dit probleem, is het leuk om te controleren of er een carry van 1 heeft plaatsgevonden door te controleren of de carry-vlag 1 is geworden.

Voor de volgende en laatste instructie, die “STA $0218” is, bevindt de opcode van STA, die 8D16 is (absolute adressering), zich in de bytelocatie van $0210. Het adres “$0218” van “STA $0218” bevindt zich in de geheugenlocaties $0211 en $0212. De instructie “STA $0218” kopieert de acht-bits inhoud van de accumulator naar de geheugenlocatie $0218. Het resultaat van de optelling van de twee zestien-bits getallen is 0101010101010100, waarbij de lagere byte van 01010100 op de geheugenlocatie $0217 is en de hogere byte van 01010101 op de geheugenlocatie $0218 – weinig endianness.

Aftrekken
Bij de 6502 µP zijn de getallen met teken twee-complementgetallen. Een twee-complementgetal kan acht bits, zestien bits of een veelvoud van acht bits zijn. Bij twee-complement is het eerste bit van links het tekenbit. Voor een positief getal is dit eerste bit 0 om het teken aan te geven. De overige bits vormen op de normale manier het getal. Om het twee-complement van een negatief getal te verkrijgen, keert u alle bits voor het overeenkomstige positieve getal om en telt u vervolgens 1 op bij het resultaat vanaf de rechterkant.

Om een ​​positief getal van een ander positief getal af te trekken, wordt de aftrekker omgezet in een twee-complement negatief getal. Vervolgens worden de minuend en het nieuwe negatieve getal op de normale manier toegevoegd. De aftrekking van acht bits wordt dus:

Waarbij wordt aangenomen dat de carry 1 is. Het resultaat in de accumulator is het verschil in twee-complement. Om dus twee getallen af ​​te trekken, moet de carry-vlag ingesteld worden (op 1 gezet).

Bij het aftrekken van twee zestien-bits getallen wordt het aftrekken tweemaal uitgevoerd, net als bij het optellen van twee zestien-bits getallen. Omdat aftrekken een vorm van optellen is bij de 6502 µP, wordt bij het aftrekken van twee zestien-bits getallen de carry-vlag slechts één keer ingesteld voor de eerste aftrekking. Voor de tweede aftrekking wordt elke instelling van de carry-vlag automatisch uitgevoerd.

Het programmeren van de aftrekking voor getallen van acht of zestien bits gebeurt op dezelfde manier als het programmeren van de optelling. De carry-vlag moet echter helemaal aan het begin worden geplaatst. Het geheugensteuntje om dit te doen is:

Aftrekken met zestien-bits positieve getallen
Beschouw de aftrekking met de volgende getallen:

Bij deze aftrekking is geen twee-complement betrokken. Omdat de aftrekking in 6502 µP in twee-complement gebeurt, gebeurt de aftrekking in basis twee als volgt:

Het resultaat van het twee-complement is hetzelfde als het resultaat dat wordt verkregen uit de gewone aftrekking. Houd er echter rekening mee dat de 1 die van rechts naar de zeventiende bitpositie gaat, wordt genegeerd. Het minuiteinde en het aftrekkertje worden elk in twee achtbits gesplitst. Het twee-complement van 10010110 van de lagere byte van de aftrekker wordt onafhankelijk van de hogere byte en van eventuele carry bepaald. Het twee-complement van 11101011 van de hogere byte van de aftrekker wordt onafhankelijk van de lagere byte en van eventuele carry bepaald.

De 16 bits van de minuend staan ​​al in twee-complement, beginnend met 0 vanaf links. Er zijn dus geen aanpassingen in bits nodig. Met de 6502 µP wordt de onderste byte van de minuend zonder enige wijziging toegevoegd aan de onderste byte van het twee-complement van de aftrekker. De onderste byte van de minuend wordt niet omgezet in twee-complement, omdat de zestien bits van de hele minuend al in twee-complement moeten staan ​​(met een 0 als eerste bit aan de linkerkant). Bij deze eerste toevoeging wordt een verplichte carry van 1 toegevoegd vanwege de 1=0 SEC-instructie.

Bij de huidige effectieve aftrekking is er een overdracht van 1 (van optelling) van het achtste bit naar het negende bit (van rechts). Omdat dit in feite een aftrekking is, wordt het bit dat zich in de carry-vlag in het statusregister zou moeten bevinden, aangevuld (geïnverteerd). Dus de carry van 1 wordt 0 in de C-vlag. Bij de tweede bewerking wordt de hogere byte van de minuend opgeteld bij de hogere twee-complementbyte van de aftrekker. De automatisch aangevulde carry-vlagbit van het statusregister (in dit geval is 0) wordt ook toegevoegd (aan de hogere bytes). Elke 1 die verder gaat dan de zestiende bit van rechts wordt genegeerd.

Het volgende is om al dat schema als volgt te coderen:

SEC
LDA $ 0213
SBC $ 0215
; geen clearing omdat de omgekeerde carry-vlagwaarde nodig is
STA $0217
LDA $ 0214
SBC $ 0216
STA $0218

Houd er rekening mee dat bij de 6502-assembleertaal een puntkomma begint met een commentaar dat niet is opgenomen in de vertaalde programmaversie in het geheugen. De twee 16-bits getallen voor aftrekking nemen vier bytes geheugen in beslag met absolute adressering; twee per nummer (geheugen is een reeks bytes). Deze invoer komt niet van het toetsenbord. Het optelresultaat is twee bytes en moet ook op een andere plaats in het geheugen worden geplaatst. Deze uitvoer gaat niet naar de monitor of printer; het gaat naar het geheugen. Dit geeft een totaal van 6 10 = 6 16 bytes voor invoer en uitvoer die in het geheugen (RAM) moeten worden geplaatst.

Voordat een programma wordt uitgevoerd, moet het eerst in het geheugen staan. Als je naar de programmacode kijkt, kun je zien dat de instructies zonder commentaar 19 vormen 10 = 13 16 bytes. Omdat alle programma's in dit hoofdstuk beginnen vanaf de geheugenlocatie $0200, gaat het programma van de $0200 bytelocatie in het geheugen naar de $0200 + $13 – $1 = $0212 bytelocatie (beginnend vanaf $0200 en niet $0201). Dit bereik omvat niet de regio voor de invoer- en uitvoerbytes. De twee invoernummers nemen 4 bytes in beslag en het ene uitvoernummer 2 bytes. Door de 6 bytes voor de invoer- en uitvoernummers op te tellen, ontstaat het bereik voor het programma dat eindigt op $0212 + $6 = $0218. De totale lengte van het programma is 19 16 = 25 10 .

De onderste byte van het minuend zou in het $0213 adres moeten staan, en de hogere byte van hetzelfde minuend zou in het $0214 adres moeten staan ​​– weinig endianness. Op dezelfde manier zou de lagere byte van de aftrekker zich in het $0215-adres moeten bevinden, en de hogere byte van dezelfde aftrekker zou zich in het $0216-adres moeten bevinden - weinig endianness. De lagere byte van het resultaat (verschil) moet in het $0217-adres staan, en de hogere byte van hetzelfde resultaat moet in het $0218-adres staan ​​– weinig endianness.

De opcode van 38 16 voor SEC (impliciete adressering) bevindt zich in het adres $0200. Van alle programma's in dit hoofdstuk wordt aangenomen dat ze beginnen op de geheugenlocatie $0200, waardoor elk programma dat daar zou hebben gestaan, wordt geannuleerd; tenzij anders vermeld. De opcode voor “LDA $0213”, d.w.z. AD 16 , want LDA (absolute adressering) bevindt zich op de bytelocatie $0201. De onderste byte van de minuend, namelijk 10111111, bevindt zich in de geheugenbytelocatie $0213. Houd er rekening mee dat elke opcode één byte in beslag neemt. Het “$0213”-adres van “LDA $0213” bevindt zich op de bytelocaties $0202 en $0203. De instructie “LDA $0213” laadt de onderste byte van de minuend naar de accumulator.

De opcode voor “SBC $0215”, d.w.z. ED 16 , want SBC (absolute adressering) bevindt zich op de bytelocatie $0204. De onderste byte van de aftrekker, die 01101010 is, bevindt zich op de bytelocatie $0215. Het adres “$0215” van “ADC $0215” bevindt zich op de bytelocaties $0205 en $0206. De instructie “SBC $0215” trekt de onderste byte van de aftrekker af van de onderste byte van de minude die zich al in de accumulator bevindt. Dit is twee-complement-aftrekking. Het resultaat wordt terug in de accu geplaatst. Het complement (inversie) van elke carry na het achtste bit wordt naar de carry-vlag van het statusregister gestuurd. Deze carry-vlag mag niet worden gewist vóór de tweede aftrekking met de hogere bytes. Deze carry wordt automatisch opgeteld bij het aftrekken van de hogere bytes.

De opmerking duurt de volgende 57 10 = 3916 16 bytes. Dit blijft echter alleen in het tekstbestand “.asm”. Het bereikt het geheugen niet. Het wordt verwijderd door de vertaling die wordt gedaan door de assembler (een programma).

Voor de volgende instructie, die “STA $0217” is, is de opcode van STA, d.w.z. 8D 16 (absolute adressering), bevindt zich op de bytelocatie $0207. Het adres “$0217” van “STA $0217” bevindt zich in de geheugenlocaties $0208 en $0209. De instructie “STA $0217” kopieert de acht-bits inhoud van de accumulator naar de geheugenlocatie $0217.

De hogere byte van de minuend die 00101010 is, bevindt zich in de geheugenlocatie van $0214, en de hogere byte van de aftrekker die 00010101 is, bevindt zich in de bytelocatie van $0216. De opcode voor “LDA $0214”, d.w.z. AD 16 voor LDA (absolute adressering), bevindt zich op de $020A bytelocatie. Het adres “$0214” van “LDA $0214” bevindt zich op de locaties $020B en $020C. De instructie “LDA $0214” laadt de hogere byte van de minuend naar de accumulator, waardoor alles wat zich in de accumulator bevindt, wordt gewist.

De opcode voor “SBC $0216”, d.w.z. ED 16 voor SBC (absolute adressering), bevindt zich op de $020D bytelocatie. Het adres “$0216” van “SBC $0216” bevindt zich op de bytelocaties $020E en $020F. De instructie “SBC $0216” trekt de hogere byte van de aftrekker af van de hogere byte van de minuend (twee-complement) die zich al in de accumulator bevindt. Het resultaat wordt terug in de accumulator geplaatst. Als er voor deze tweede aftrekking een carry van 1 is, wordt het complement ervan automatisch in de carrycel van het statusregister geplaatst. Hoewel de carry voorbij de zestiende bit (links) niet vereist is voor dit probleem, is het handig om te controleren of de complement-carry plaatsvindt door de carry-vlag te controleren.

Voor de volgende en laatste instructie, die de “STA $0218” is, de opcode van STA, d.w.z. 8D 16 (absolute adressering), bevindt zich op de bytelocatie $0210. Het adres “$0218” van “STA $0218” bevindt zich in de geheugenlocaties $0211 en $0212. De instructie “STA $0218” kopieert de acht-bits inhoud van de accumulator naar de geheugenlocatie $0218. Het resultaat van het aftrekken met de twee zestien-bits getallen is 0001010101010101 met de lagere byte van 01010101 op de geheugenlocatie van $0217 en de hogere byte van 00010101 op de geheugenlocatie van $0218 – weinig endianness.

De 6502 µP heeft alleen circuits voor optelling en indirect voor de twee-complementaftrekking. Het heeft geen circuits voor vermenigvuldigen en delen. Om de vermenigvuldiging en deling uit te voeren, moet een assembleertaalprogramma met details, inclusief het verschuiven van deelproducten en gedeeltelijke dividenden, worden geschreven.

4.4 Logische bewerkingen

In de 6502 µP is het geheugensteuntje voor OR ORA en het geheugensteuntje voor exclusieve OR is EOR. Merk op dat de logische bewerkingen niet de impliciete adressering hebben. De impliciete adressering heeft geen operand nodig. Elk van de logische operatoren moet twee operanden hebben. De eerste bevindt zich in de accumulator en de tweede bevindt zich in het geheugen of in de instructie. Het resultaat (8 bits) gaat terug naar de accumulator. De eerste in de accumulator wordt daar geplaatst door een onmiddellijke instructie of wordt met absolute adressering uit het geheugen gekopieerd. In dit gedeelte wordt ter illustratie alleen de nulpagina-adressering gebruikt. Deze logische operatoren zijn allemaal Bitwise-operatoren.

EN
De volgende tabel illustreert de Bitwise AND in binair, hexadecimaal en decimaal:

Alle programma's in dit hoofdstuk moeten starten op de geheugenbytelocatie $0200. De programma's in deze sectie bevinden zich echter op pagina nul, met als doel het gebruik van pagina nul te illustreren zonder de hogere byte van 00000000 2 . De vorige AND-bewerking kan als volgt worden gecodeerd:

LDA#$9A; niet uit het geheugen – onmiddellijke adressering
EN #$CD ; niet uit het geheugen – onmiddellijke adressering
STA $30; slaat $ 88 op bij een op nul gebaseerde $ 0030

OF
De volgende tabel illustreert de Bitwise OR in binair, hexadecimaal en decimaal:

LDA#$9A; niet uit het geheugen – onmiddellijke adressering
ORA #$CD ; niet uit het geheugen – onmiddellijke adressering
STA $30; slaat $CF op op nul gebaseerde $0030

VRIJ
De volgende tabel illustreert de Bitwise XOR in binair, hexadecimaal en decimaal:

LDA#$9A; niet uit het geheugen – onmiddellijke adressering
EOR #$CD ; niet uit het geheugen – onmiddellijke adressering
STA $30; slaat $ 57 op bij een op nul gebaseerde $ 0030

4.5 Schakel- en draaibewerkingen

De geheugensteuntjes en opcodes voor de operatoren voor verschuiven en roteren zijn:

ASL: Verschuif één bit van de accumulator- of geheugenlocatie naar links en plaats 0 in de vrijgekomen rechtse cel.

LSR: Verschuif één bit van de accumulator- of geheugenlocatie naar rechts en plaats 0 in de meest linkse cel.
ROL: Roteer één bit links van de accumulator- of geheugenlocatie en plaats het bit dat aan de linkerkant is weggevallen in de vrijgekomen meest rechtse cel.
ROR: Draai één bit rechts van de accumulator of geheugenlocatie, waarbij het bit dat aan de rechterkant is weggevallen, in de meest linkse cel wordt geplaatst.

Om een ​​verschuiving of rotatie met de accumulator uit te voeren, is de instructie ongeveer als volgt:

LSR A

Dit maakt gebruik van een andere adresseringsmodus, de accumulator-adresseringsmodus.

Om een ​​verschuiving of rotatie uit te voeren met een byte-geheugenlocatie, is de instructie ongeveer als volgt:

ROR$2BCD

Waarbij 2BCD de geheugenlocatie is.

Merk op dat er geen directe of impliciete adresseringsmodus is voor verschuiven of roteren. Er is geen directe adresseringsmodus, omdat het geen zin heeft een getal te verschuiven of te roteren dat alleen in de instructie overblijft. Er is geen impliciete adresseringsmodus omdat de ontwerpers van de 6502 µP alleen de inhoud van de accumulator (A-register) of een geheugenbytelocatie willen verschuiven of roteren.

4.6 Relatieve adresseringsmodus

De microprocessor verhoogt altijd (met 1, 2 of 3 eenheden) de Programmateller (PC) om naar de volgende instructie te wijzen die moet worden uitgevoerd. De 6502 µP heeft een instructie waarvan het geheugensteuntje BVS is, wat Branch on Overflow Set betekent. De PC bestaat uit twee bytes. Deze instructie zorgt ervoor dat de pc een ander geheugenadres heeft voor de volgende instructie die moet worden uitgevoerd, wat niet het gevolg is van een normale toename. Dit gebeurt door een waarde, een zogenaamde offset, toe te voegen aan of af te trekken van de inhoud van de pc. En dus wijst de pc vervolgens naar een andere (vertakte) geheugenlocatie waar de computer van daaruit verder kan werken. De offset is een geheel getal van -128 10 tot +127 10 (twee-complement). De offset kan er dus voor zorgen dat de sprong in het geheugen doorgaat. Als het positief is of achterblijft in het geheugen, of als het negatief is.

De BVS-instructie heeft slechts één operand nodig, namelijk de offset. BVS gebruikt de relatieve adressering. Overweeg de volgende instructie:

BVS $ 7F

In basis twee, 7F H is 01111111 2 = 127 10 . Stel dat de inhoud op de pc voor de volgende instructie $0300 bedraagt. De BVS-instructie zorgt ervoor dat $7F (een positief getal dat al in het twee-complement zit) wordt opgeteld bij $0300, wat $037F oplevert. Dus in plaats van dat de volgende instructie moet worden uitgevoerd op de geheugenlocatie van $0300, bevindt deze zich op de geheugenlocatie van $037F (ongeveer een halve pagina verschil).

Er zijn andere vertakkingsinstructies, maar BVS is een zeer goede om te gebruiken om de relatieve adressering te illustreren. Relatieve adressering heeft betrekking op vertakkingsinstructies.

4.7 Geïndexeerde adressering en indirecte adressering afzonderlijk

Dankzij deze adresseringsmodi kan de 6502 µP de enorme hoeveelheden gegevens in korte tijd verwerken met een beperkt aantal instructies. Er zijn 64 KB locaties voor het gehele Comodore-64-geheugen. Om toegang te krijgen tot elke bytelocatie van 16 bits zijn er dus twee bytes nodig. De enige uitzondering op de noodzaak van twee bytes is voor pagina nul, waar de hogere byte van $00 wordt weggelaten om de ruimte te besparen die wordt ingenomen door de instructie in het geheugen. Met een adresseringsmodus zonder pagina-nul worden zowel de hogere als de lagere bytes van het 16-bits geheugenadres meestal op de een of andere manier aangegeven.

Basis geïndexeerde adressering

Absolute indexadressering
Houd er rekening mee dat het X- of Y-register het indexregister wordt genoemd. Overweeg de volgende instructie:

LDA $C453,X

Neem aan dat de waarde van 6 H staat in het X-register. Merk op dat 6 nergens in de instructie wordt getypt. Deze instructie voegt de waarde van 6H toe aan C453 H die deel uitmaakt van de getypte instructie in het tekstbestand dat nog moet worden samengesteld – C453 H + 6 H = C459 H . LDA betekent een byte naar de accu laden. De byte die in de accumulator moet worden geladen, is afkomstig van het adres $C459. De $C459, wat de som is van $C453 die is getypt met de instructie en 6 H dat in het X-register wordt gevonden, wordt het effectieve adres waar de in de accumulator te laden byte vandaan komt. Als 6 H in het Y-register stond, wordt Y in de instructie getypt in plaats van X.

In de getypte instructie-instructie staat $C453 bekend als het basisadres en de 6 H in het X- of Y-register staat bekend als het tel- of indexgedeelte voor het effectieve adres. Het basisadres kan verwijzen naar elk byteadres in het geheugen, en de volgende 256 10 adressen zijn toegankelijk, ervan uitgaande dat de gestarte index (of telling) in het X- of Y-register 0 is. Onthoud dat één byte een continu bereik van maximaal 256 kan opleveren 10 nummers (d.w.z. 00000000 2 naar 11111111 2 ).

De absolute adressering voegt dus alles toe wat al in het X- of Y-register is geplaatst (door een andere instructie geplaatst) bij de 16 adressen die zijn getypt met de instructie om het effectieve adres te verkrijgen. In de getypte instructie worden de twee indexregisters onderscheiden door X of Y, die na een komma worden getypt. X of Y wordt getypt; niet beide.

Nadat het hele programma in een teksteditor is getypt en opgeslagen met de bestandsnaamextensie “.asm”, moet de assembler, wat een ander programma is, het getypte programma vertalen naar wat er in het geheugen staat (geladen). De vorige instructie, namelijk “LDA $C453,X”, beslaat drie bytelocaties in het geheugen, en niet vijf.

Houd er rekening mee dat een geheugensteuntje zoals LDA meer dan één opcode (verschillende bytes) kan hebben. De opcode voor de instructie die het X-register gebruikt, verschilt van de opcode die het Y-register gebruikt. De assembler weet welke opcode hij moet gebruiken op basis van de getypte instructie. De één-byte-opcode voor “LDA $C453,X” verschilt van de één-byte-opcode voor “LDA $C453,Y”. In feite is de opcode voor LDA in “LDA $C453,X” BD, en de opcode voor LDA in “LDA $C453,9” is BD.

Als de opcode voor LDA zich op de $0200 bytelocatie bevindt. Vervolgens neemt het 16-bits adres van $C453 de volgende bytelocaties in het geheugen, namelijk $0201 en $0202. De specifieke opcodebyte geeft aan of het om het X-register of om het Y-register gaat. En dus neemt de samengestelde taalinstructie, die “LDA $C453,X” of “LDA $C453,Y” is, drie opeenvolgende bytes in het geheugen in beslag, en niet vier of vijf.

Zero-Page geïndexeerde adressering
De indexadressering van nulpagina's lijkt op de absolute indexadressering die eerder is beschreven, maar de doelbyte mag zich alleen op pagina nul bevinden (van $0000 tot $00FF). Als het nu om de nulpagina gaat, is de hogere byte altijd 00 H voor de geheugenlocaties wordt meestal vermeden. Normaal gesproken wordt dus vermeld dat pagina nul begint van $00 tot FF. En dus is de vorige instructie van “LDA $C453,X”:

LDA $ 53,X

De $C4, een hogere byte die verwijst naar een pagina boven de pagina nul, kan niet worden gebruikt in deze instructie, omdat deze de verwachte doelbyte die moet worden geladen in de geaccumuleerde byte buiten en boven de pagina nul plaatst.

Wanneer de waarde die in de instructie is getypt, wordt opgeteld bij de waarde in het indexregister, mag de som geen resultaat opleveren boven de pagina nul (FF H ). Er is dus geen sprake van een instructie als “LDA $FF, X” en een waarde als FF H in het indexregister omdat FF H +FF H = 200 H Dit is de eerste byte ($0200) locatie van pagina 2 (derde pagina) in het geheugen en bevindt zich op een grote afstand van pagina 0. Bij nulpagina-geïndexeerde adressering moet het effectieve adres dus op pagina nul liggen.

Indirecte adressering

Jump absolute adressering
Voordat we de Absolute Indirecte Adressering bespreken, is het goed om eerst naar de JMP absolute adressering te kijken. Stel dat het adres met de gewenste waarde (doelbyte) $8765 is. Dit zijn 16 bits bestaande uit twee bytes: de hogere byte is 87 H en de onderste byte die 65 is H . De twee bytes voor $8765 worden dus in de pc (programmateller) geplaatst voor de volgende instructie. Wat in het assembleertaalprogramma (bestand) wordt getypt, is:

JMP $ 8765

Het uitvoerende programma in het geheugen springt van welk adres dan ook naar $8765. Het JMP-ezelsbruggetje heeft drie opcodes: 4C, 6C en 7C. De opcode voor deze absolute adressering is 4C. De opcode voor de JMP absolute indirecte adressering is 6C (zie de volgende illustraties).

Absoluut indirecte adressering
Dit wordt alleen gebruikt bij de spronginstructie (JMP). Stel dat het adres met de betreffende byte (doelbyte) $8765 is. Dit zijn 16 bits bestaande uit twee bytes: de hogere byte is 87 H en de onderste byte die 65 is H . Bij absolute indirecte adressering bevinden deze twee bytes zich feitelijk op twee opeenvolgende bytelocaties elders in het geheugen.

Neem aan dat ze zich op de geheugenlocaties $0210 en $0211 bevinden. Vervolgens de onderste byte van het interessante adres, namelijk 65 H bevindt zich in het adres $0210, en de hogere byte is 87 H bevindt zich op het adres $0211. Dat betekent dat de lagere geheugenbyte van belang naar het lagere opeenvolgende adres gaat, en de hogere geheugenbyte van belang naar het hogere opeenvolgende adres gaat – weinig endianness.

Het 16-bits adres kan verwijzen naar twee opeenvolgende adressen in het geheugen. In dat licht verwijst het adres $0210 naar de adressen $0210 en $0211. Het adrespaar $0210 en $0211 bevat het uiteindelijke adres (16 bits van twee bytes) van de doelbyte, met de onderste byte van 65 H in $0210 en de hogere byte van 87 H voor $ 0211. De spronginstructie die wordt getypt is dus:

JMP ($0210)

Het JMP-ezelsbruggetje heeft drie opcodes: 4C, 6C en 7C. De opcode voor absolute indirecte adressering is 6C. Wat in het tekstbestand wordt getypt, is 'JMP ($0210)'. Vanwege de haakjes gebruikt de assembler (vertaler) de opcode 6C voor JMP, en niet 4C of 7C.

Bij absolute indirecte adressering zijn er feitelijk drie geheugengebieden. Het eerste gebied kan bestaan ​​uit de bytelocaties $0200, $0201 en $0202. Dit heeft de drie bytes voor de instructie 'JMP ($0210)'. Het tweede gebied, dat niet noodzakelijkerwijs naast het eerste ligt, bestaat uit de twee opeenvolgende bytelocaties $0210 en $0211. Het is hier de lagere byte ($0210) die is getypt in de programma-instructie in de assembleertaal. Als het adres van interesse $8765 is, is de onderste byte 65 H bevindt zich op de bytelocatie $0210 en de hogere byte van 87 H bevindt zich op de bytelocatie $0211. Het derde gebied bestaat uit slechts één bytelocatie. Het is een adres van $8765 voor de beoogde byte (ultieme byte van belang). Het paar opeenvolgende adressen, $0210 en $0211, bevat de $8765-aanwijzer, het adres van interesse. Na de computerinterpretatie gaat er $8765 naar de pc (programmateller) om toegang te krijgen tot de doelbyte.

Zero Page Indirecte adressering
Deze adressering is hetzelfde als de absolute indirecte adressering, maar de aanwijzer moet op pagina nul staan. Het lagere byte-adres van het pointergebied is wat er als volgt in de getypte instructie staat:

JMP ($ 50)

De hogere byte van de pointer bevindt zich op de $51-bytelocatie. Het effectieve adres (puntig) hoeft niet op pagina nul te staan.

Bij indexadressering wordt dus de waarde in een indexregister opgeteld bij het basisadres dat is opgegeven in de instructie om het effectieve adres te verkrijgen. Bij indirecte adressering wordt gebruik gemaakt van een pointer.

4.8 Geïndexeerde indirecte adressering

Absoluut geïndexeerde indirecte adressering
Deze adresseringsmodus wordt alleen gebruikt met de JMP-instructie.
Bij absolute indirecte adressering is er de puntige waarde (byte) met zijn eigen twee opeenvolgende byte-adressen. Deze twee opeenvolgende adressen vormen de pointer die zich in het pointergebied van twee opeenvolgende bytes in het geheugen bevindt. De onderste byte van het pointergebied is wat tussen haakjes in de instructie wordt getypt. De aanwijzer is het adres van de puntige waarde. In de vorige situatie is $8765 het adres van de puntwaarde. De $0210 (gevolgd door $0211) is het adres waarvan de inhoud $8765 is, wat de aanwijzer is. Bij de absolute indirecte adresseringsmodus wordt ($0210) in het programma getypt (tekstbestand), inclusief de haakjes.

Aan de andere kant wordt bij de Absolute Indexed Indirect Addressing Mode de onderste adresbyte voor het pointergebied gevormd door de waarde in het X-register op te tellen bij het getypte adres. Als de aanwijzer zich bijvoorbeeld op de adreslocatie $0210 bevindt, kan de getypte instructie er ongeveer zo uitzien:

JMP ($020A,X)

Waarbij het X-register de waarde 6 heeft H . 020A H + 6 H = 0210 H . Het Y-register wordt bij deze adresseringsmodus niet gebruikt.

Zero Page geïndexeerde indirecte adressering
Deze adresseringsmodus gebruikt het X-register en niet het Y-register. Met deze adresseringsmodus zijn er nog steeds de puntige waarde en de aanwijzer in het adresaanwijzergebied van twee bytes. Er moeten twee opeenvolgende bytes op pagina nul staan ​​voor de aanwijzer. Het adres dat in de instructie wordt getypt, is een adres van één byte. Deze waarde wordt opgeteld bij de waarde in het X-register en eventuele carry wordt weggegooid. Het resultaat verwijst naar het pointergebied op pagina 0. Als het betreffende adres (puntig) bijvoorbeeld $8765 is en het zich in de bytelocaties $50 en $51 van pagina 0 bevindt, en de waarde in het X-register $30 is, getypte instructie is ongeveer zo:

LDA ($ 20,X)

Omdat $20 + $30 = $50.

Indirect geïndexeerde adressering
Deze adresseringsmodus gebruikt het Y-register en niet het X-register. Met deze adresseringsmodus is er nog steeds de puntige waarde en het pointergebied, maar de inhoud van het pointergebied werkt anders. Er moeten twee opeenvolgende bytes op pagina nul staan ​​voor het pointergebied. Het onderste adres van het pointergebied wordt in de instructie getypt. Dit aantal (paar bytes) dat zich in het pointergebied bevindt, wordt opgeteld bij de waarde in het Y-register om de echte pointer te krijgen. Stel dat het adres van interesse (puntig) bijvoorbeeld $8765 is, de waarde van 6H in het Y-register staat en het getal (twee bytes) op het adres 50 staat. H en 51 H . De twee bytes samen zijn $875F aangezien $875F + $6 = $8765. De getypte instructie is ongeveer zo:

LDA ($50),Y

4.9 Instructies voor het verhogen, verlagen en testen van BIT's

De volgende tabel toont de bewerkingen van de instructies voor verhogen en verlagen:

De INA en DEA verhogen respectievelijk de accumulator. Dat heet accumulatoradressering. INX, DEX, INY en DEY zijn respectievelijk voor de X- en Y-registers. Ze nemen geen enkele operand. Ze gebruiken dus de impliciete adresseringsmodus. Verhogen betekent het toevoegen van 1 aan het register of de geheugenbyte. Afnemen betekent het aftrekken van 1 van het register of de geheugenbyte.

De INC en DEC verhogen en verlagen respectievelijk een geheugenbyte (en niet een register). Door gebruik te maken van de nulpagina-adressering in plaats van de absolute adressering wordt het geheugen voor de instructie bespaard. Nulpagina-adressering is één byte minder dan de absolute adressering voor de instructie in het geheugen. De nulpagina-adresseringsmodus heeft echter alleen invloed op de pagina nul.

De BIT-instructie test de bits van een byte in het geheugen met de 8 bits in de accumulator, maar verandert geen van beide. Er zijn slechts enkele vlaggen van het processorstatusregister “P” ingesteld. De bits van de opgegeven geheugenlocatie worden logisch ge-AND met die van de accumulator. Vervolgens worden de volgende statusbits ingesteld:

  • N, wat bit 7 is en de laatste bit (links) van het statusregister, ontvangt bit 7 van de geheugenlocatie vóór de AND-bewerking.
  • V, dat bit 6 van het statusregister is, ontvangt bit 6 van de geheugenlocatie vóór de AND-bewerking.
  • De Z-vlag van het statusregister wordt ingesteld (1 gemaakt) als het resultaat van de AND nul is (00000000 2 ). Anders wordt het gewist (0 gemaakt).

4.10 Instructies vergelijken

De vergelijkingsinstructies voor de 6502 µP zijn CMP, CPX en CPY. Na elke vergelijking worden de N-, Z- en C-vlaggen van het processorstatusregister “P” beïnvloed. De N-vlag wordt ingesteld (1 gemaakt) als het resultaat een negatief getal is. De Z-vlag wordt ingesteld (1 gemaakt) wanneer het resultaat een nul is (000000002). De C-vlag wordt ingesteld (1 gemaakt) wanneer er een overdracht plaatsvindt van het achtste naar het negende bit. De volgende tabel geeft een gedetailleerde illustratie

Het betekent ‘groter dan’. Daarmee zou de vergelijkingstabel voor zichzelf moeten spreken.

4.11 Instructies voor sprongen en vertakkingen

De volgende tabel vat de sprong- en vertakkingsinstructies samen:

De JMP-instructie gebruikt de absolute en indirecte adressering. De rest van de instructies in de tabel zijn vertakkingsinstructies. Bij de 6502 µP gebruiken ze alleen de relatieve adressering. Daarmee wordt de tabel vanzelfsprekend als deze van links naar rechts en van boven naar beneden wordt gelezen.

Merk op dat de vertakkingen alleen kunnen worden toegepast op adressen binnen -128 tot +127 bytes van het opgegeven adres. Dit is relatieve adressering. Voor zowel de JMP- als de vertakkingsinstructies wordt de Programmateller (PC) rechtstreeks beïnvloed. De 6502 µP staat geen vertakkingen naar een absoluut adres toe, hoewel de sprong wel voor de absolute adressering kan zorgen. De JMP-instructie is geen vertakkingsinstructie.

Opmerking: Relatieve adressering wordt alleen gebruikt bij vertakkingsinstructies.

4.12 Het stapelgebied

Een subroutine lijkt op een van de vorige korte programma's om twee getallen op te tellen of twee getallen af ​​te trekken. Het stapelgebied in het geheugen begint van $0100 tot en met $01FF. Dit gebied wordt eenvoudigweg de stapel genoemd. Wanneer de microprocessor een sprong naar de subroutine-instructie (JSR – zie de volgende bespreking) uitvoert, moet hij weten waar hij moet terugkeren als hij klaar is. De 6502 µP bewaart deze informatie (retouradres) in een laag geheugen van $0100 tot $01FF (het stapelgebied) en gebruikt de inhoud van het stackpointerregister, die 'S' is in de microprocessor, als een pointer (9 bits) naar het laatst geretourneerde adres dat is opgeslagen op pagina 1 ($0100 tot $01FF) van het geheugen. De stapel groeit vanaf $01FF en maakt het mogelijk om de subroutines tot 128 niveaus diep te nesten.

Een ander gebruik van de stackpointer is het afhandelen van interrupts. De 6502 µP heeft de pinnen met het label IRQ en NMI. Het is mogelijk dat er kleine elektrische signalen op deze pinnen worden toegepast, waardoor de 6502 µP stopt met het uitvoeren van het ene programma en het andere programma begint uit te voeren. In dit geval wordt het eerste programma onderbroken. Net als subroutines kunnen de interruptcodesegmenten worden genest. Het onderbreken van de verwerking wordt besproken in het volgende hoofdstuk.

Opmerking : De stackpointer heeft 8 bits voor het lagere byte-adres bij het adresseren van de locaties van $0100 tot $01FF. De hogere byte van 00000001 2 wordt verondersteld.

De volgende tabel geeft de instructies die de stapelwijzer “S” met de A-, X-, Y- en P-registers relateren aan het stapelgebied in het geheugen:

4.13 Subroutineoproep en terugkeer

Een subroutine is een reeks instructies die een bepaald doel bereiken. Het vorige optel- of aftrekprogramma is een zeer korte subroutine. Subroutines worden soms gewoon routines genoemd. De instructie om een ​​subroutine aan te roepen is:

JSR: Ga naar SubRoutine

De instructie om terug te keren vanuit een subroutine is:

RTS: Terugkeren vanuit subroutine

De microprocessor heeft de neiging om de instructies in het geheugen continu, de een na de ander, uit te voeren. Neem aan dat de microprocessor momenteel een codesegment aan het uitvoeren is en dat hij een spronginstructie (JMP) tegenkomt om een ​​codesegment uit te voeren dat gecodeerd is achter het codesegment dat mogelijk al is uitgevoerd. Het voert dat codesegment erachter uit en gaat door met het uitvoeren van alle codesegmenten (instructies) die het codesegment volgen, totdat het het huidige codesegment opnieuw uitvoert en hieronder verder gaat. JMP duwt de volgende instructie niet naar de stapel.

In tegenstelling tot JMP duwt JSR het adres van de volgende instructie na zichzelf van de pc (programmateller) naar de stapel. De stapelpositie van dit adres wordt in de stapelwijzer “S” geplaatst. Wanneer een RTS-instructie wordt aangetroffen (uitgevoerd) in de subroutine, wordt het adres dat op de stapel wordt gepusht van de stapel gehaald en wordt het programma hervat op dat verwijderde adres, dat het volgende instructieadres is vlak voor de oproep van de subroutine. Het laatste adres dat uit de stapel wordt verwijderd, wordt naar de programmateller gestuurd. De volgende tabel geeft de technische details van de JSR- en RTS-instructies:

Zie de volgende illustratie voor het gebruik van JSR en RTS:

4.14 Een voorbeeld van een aftellus

De volgende subroutine telt af van $FF naar $00 (totaal 256 10 telt):

start LDX #$FF ; laad X met $FF = 255
lus DEX; X = X – 1
BNE-lus; als X niet nul is, ga dan naar de lus
RTS; opbrengst

Elke regel heeft een commentaar. Opmerkingen worden nooit in het geheugen opgeslagen voor uitvoering. De assembler (vertaler) die een programma converteert naar wat het in het geheugen bevat voor uitvoering (uitvoeren), verwijdert altijd de opmerkingen. Een opmerking begint met “;” . De “start” en “loop” in dit programma worden labels genoemd. Een label identificeert (de naam) voor het adres van de instructie. Als de instructie een instructie van één byte is (impliciete adressering), is het label het adres van die instructie. Als de instructie een multibyte-instructie is, identificeert het label de eerste byte voor de multibyte-instructie. De eerste instructie voor dit programma bestaat uit twee bytes. Ervan uitgaande dat het begint op het $0300-adres, kan het $0300-adres verderop in het programma worden vervangen door 'start'. De tweede instructie (DEX) is een instructie van één byte en zou op het adres $0302 moeten staan. Dit betekent dat het adres $0302 vervangen kan worden door “loop”, verderop in het programma, wat feitelijk zo is in “BNE loop”.

“BNE-lus” betekent de aftakking naar het opgegeven adres wanneer de Z-vlag van het statusregister 0 is. Wanneer de waarde in het A-, X- of Y-register 00000000 is 2 , vanwege de laatste bewerking is de Z-vlag 1 (set). Dus hoewel het 0 is (niet 1), worden de tweede en derde instructies in het programma in die volgorde herhaald. In elke herhaalde reeks wordt de waarde (geheel getal) in het X-register met 1 verlaagd. DEX betekent X = X – 1. Wanneer de waarde in het X-register $00 = 00000000 is 2 , Z wordt 1. Op dat moment is er geen herhaling meer van de twee instructies. De laatste RTS-instructie in het programma, die een instructie van één byte is (impliciete adressering), keert terug van de subroutine. Het effect van deze instructie is dat het programmatelleradres in de stapel wordt gemaakt voor de code die moet worden uitgevoerd vóór de subroutineaanroep, en dat het teruggaat naar de programmateller (PC). Dit adres is het adres van de instructie die moet worden uitgevoerd voordat de subroutine wordt aangeroepen.

Opmerking: Bij het schrijven van een assembleertaalprogramma voor de 6502 µP mag alleen een label aan het begin van een regel beginnen; elke andere lijncode moet minstens één spatie naar rechts worden verschoven.

Een subroutine oproepen
Het programma negeert de geheugenruimte die wordt ingenomen door de vorige labels en neemt 6 bytes aan opeenvolgende locaties in het geheugen (RAM) van $0300 tot $0305. In dit geval is het programma:

LDX #$FF ; laad X met $FF = 255
DEX; X = X – 1
BNE $ 0302; als X niet nul is, ga dan naar de lus
RTS; opbrengst

Vanaf het adres $0200 in het geheugen kan de oproep voor de subroutine beginnen. De oproepinstructie is:

JSR-start; start is adres $0300, d.w.z. JSR $0300

De subroutine en zijn oproep die correct in het teksteditorbestand zijn geschreven, zijn:

start LDX #$FF; laad X met $FF = 255
lus DEX; X = X – 1

BNE-lus; als X niet nul is, ga dan naar de lus
RTS; opbrengst

JSR-start: ga naar routine vanaf $ 0300

Nu kunnen er veel subroutines in één lang programma zijn. Ze kunnen niet allemaal de naam “start” hebben. Ze zouden verschillende namen moeten hebben. In feite zou geen van hen de naam “start” kunnen hebben. Om leerredenen wordt hier “Start” gebruikt.

4.15 Een programma vertalen

Een programma vertalen of assembleren betekent hetzelfde. Denk eens aan het volgende programma:

start LDX #$FF: laad X met $FF = 255
lus DEX: X = X – 1
BNE-lus: als X niet nul is, ga dan naar de lus
RTS: terug
JSR-start: ga naar routine vanaf $ 0300

Dit is het programma dat eerder is geschreven. Het bestaat uit de subroutine, start en de oproep naar de subroutine. Het programma telt af vanaf 255 10 naar 0 10 . Het programma begint op het beginadres van de gebruiker $0200 (RAM). Het programma wordt in een teksteditor getypt en op de schijf opgeslagen. Het heeft een naam zoals “sample.asm”, waarbij “sample” de naam is die de programmeur zelf kiest, maar de extensie “.asm” voor de assembleertaal moet aan de bestandsnaam worden gekoppeld.

Het samengestelde programma wordt geproduceerd door een ander programma dat een assembler wordt genoemd. De assembler wordt geleverd door de fabrikant van de 6502 µP of door een derde partij. De assembler reproduceert het programma zodanig dat het zich in het geheugen (RAM) bevindt terwijl het wordt uitgevoerd (run).

Neem aan dat de JSR-instructie begint op het $0200-adres en dat de subroutine begint op het $0300-adres. De assembler verwijdert alle opmerkingen en witte ruimtes. De commentaren en witruimtes verspillen het geheugen dat altijd schaars is. Een mogelijke lege regel tussen het vorige subroutinecodesegment en de subroutineoproep is een voorbeeld van witruimte. Het samengestelde bestand wordt nog steeds op de schijf opgeslagen en heeft de naam 'sample.exe'. Het “voorbeeld” is de naam van de keuze van de programmeur, maar de extensie “.exe” moet aanwezig zijn om aan te geven dat het een uitvoerbaar bestand is.

Het samengestelde programma kan als volgt worden gedocumenteerd:

Het produceren van een dergelijk document heet het met de hand in elkaar zetten. Houd er rekening mee dat de opmerkingen in dit document niet in het geheugen verschijnen (voor uitvoering). De adreskolom in de tabel geeft de startadressen van de instructies in het geheugen aan. Merk op dat “JSR start”, dat wil zeggen “JSR $0300”, dat naar verwachting gecodeerd zal worden als “20 03 00”, feitelijk gecodeerd is als “20 00 03”, waarbij het lagere geheugenbyte-adres de lagere byte in het geheugen in beslag neemt en de byte-adres met hoger geheugen neemt de hogere byte in het geheugen - weinig endianness. De opcode voor JSR is 20 16 .

Merk op dat de offset naar een aftakkingsinstructie zoals BNE een twee-complementgetal is in het bereik van 128 10 tot + 127 10 . “BNE-lus” betekent dus “BNE -1 10 ” wat eigenlijk “D0 FF” is in de codevorm van FF 16 is -1 in twee-complement dat is geschreven als = 11111111 in basis twee. Het assemblerprogramma vervangt de labels en velden door daadwerkelijke hexadecimale getallen (hexadecimale getallen zijn binaire getallen die in vier bits zijn gegroepeerd). De daadwerkelijke adressen waar elke instructie begint, zijn feitelijk inbegrepen.

Opmerking: De “JSR start”-instructie wordt vervangen door kortere instructies die de huidige inhoud (hoge en lage bytes) van de programmateller naar de stapel sturen met de stapelwijzer die twee keer wordt verlaagd (eenmaal voor hoge byte en eenmaal voor lage byte) en laadt vervolgens de pc opnieuw met het $0300-adres. De stackpointer wijst nu naar $00FD, ervan uitgaande dat deze is geïnitialiseerd op $01FF.

Ook wordt de RTS-instructie vervangen door een aantal kortere instructies die de stapelwijzer “S” twee keer verhogen (eenmaal voor lage byte en eenmaal voor hoge byte) en de corresponderende twee adresbytes van de stapelwijzer naar de pc halen voor de volgende instructie.

Opmerking: Een labeltekst mag niet meer dan 8 tekens bevatten.

“BNE-lus” gebruikt de relatieve adressering. Het betekent dat je -3 moet optellen 10 naar de volgende programmatellerinhoud van $0305. De bytes voor “BNE-lus” zijn “D0 FD” waarbij FD het twee-complement van -3 is 10 .

Let op: Dit hoofdstuk bevat niet alle instructies voor de 6502 µP. Alle instructies en hun details zijn te vinden in het document getiteld “SY6500 8-Bit Microprocessor Family”. Er bestaat een PDF-bestand met de naam “6502.pdf” voor dit document, dat gratis beschikbaar is op internet. De 6502 µP die in dit document wordt beschreven, is 65C02.

4.16 Onderbrekingen

De signalen van elk apparaat dat is aangesloten op de externe (verticaal oppervlak) poorten van de Commodore 64 moeten door de CIA 1- of CIA 2-circuits (IC's) gaan voordat ze de 6502-microprocessor bereiken. De signalen van de databus van de 6502 µP moeten via de CIA 1- of CIA 2-chip gaan voordat ze een extern apparaat bereiken. CIA staat voor Complexe Interface Adapter. In Fig 4.1 “Blokdiagram van het Commodore_64 moederbord” vertegenwoordigen de blokinvoer/uitvoerapparaten de CIA 1 en de CIA 2. Wanneer een programma actief is, kan het worden onderbroken om een ​​ander stukje code uit te voeren voordat het verdergaat. Er is hardwareonderbreking en softwareonderbreking. Voor hardwareonderbrekingen zijn er twee ingangssignaalpinnen op de 6502 µP. De namen van deze pinnen zijn IRQ En NMI . Dit zijn geen µP-datalijnen. De datalijnen voor de µP zijn D7, D6, D5, D4, D3, D2, D1 en D0; met D0 voor het minst significante bit en D7 voor het meest significante bit.

IRQ staat voor Interrupt ReQuest “actief” laag. Deze ingangslijn naar de µP is normaal gesproken hoog, ongeveer 5 volt. Wanneer deze naar ongeveer 0 volt daalt, is dat een interruptverzoek dat de µP signaleert. Zodra het verzoek wordt ingewilligd, gaat de lijn weer hoog. Het toestaan ​​van het interruptverzoek betekent dat de µP vertakt naar de code (subroutine) die de interrupt afhandelt.

NMI staat voor Non-Maskable Interrupt “actief” laag. Terwijl de code voor IRQ wordt geëxecuteerd NMI laag kan gaan. In dit geval, NMI wordt afgehandeld (de eigen code wordt uitgevoerd). Daarna wordt de code voor IRQ gaat door. Na de code voor IRQ eindigt, gaat de hoofdprogrammacode verder. Dat is, NMI onderbreekt de IRQ begeleider. Het signaal voor NMI kan nog steeds aan de µP worden gegeven, zelfs als de µP inactief is en niets verwerkt of geen hoofdprogramma draait.

Opmerking: Het is eigenlijk de overgang van hoog naar laag NMI , dat is de NMI signaal – daarover later meer. IRQ komt normaal gesproken van CIA 1 en NMI komt normaal gesproken van CIA 2. NMI , wat staat voor Non-Maskable Interrupt, kan worden beschouwd als een niet-stopbare interrupt.

Onderbrekingen afhandelen
Of het verzoek afkomstig is van IRQ of NMI , moet de huidige instructie worden voltooid. De 6502 heeft alleen de A-, X- en Y-registers. Terwijl een subroutine actief is, kan deze deze drie registers samen gebruiken. Een interrupthandler is nog steeds een subroutine, maar wordt niet als zodanig gezien. Nadat de huidige instructie is voltooid, wordt de inhoud van de A-, X- en Y-registers voor de 65C02 µP in de stapel opgeslagen. Het adres van de volgende instructie van de programmateller wordt ook naar de stapel gestuurd. De µP vertakt zich vervolgens naar de code voor de interrupt. Daarna wordt de inhoud van de A-, X- en Y-registers vervolgens hersteld van de stapel in de omgekeerde volgorde waarin ze zijn verzonden.

Voorbeeldcodering voor een interrupt
Voor de eenvoud wordt aangenomen dat de routine voor de µP IRQ interrupt is alleen maar om de getallen $01 en $02 op te tellen en het resultaat van $03 op te slaan op het geheugenadres $0400. De code is:

ISR PHA
PHX
PHY
;
LDA #$01
ADC #$02
ZE KOSTEN $ 0400
;
PLY
PLX
PLA
RTI

ISR is een label en identificeert het geheugenadres waar de PHA-instructie zich bevindt. ISR betekent Interrupt Service Routine. PHA, PHX en PHY sturen de inhoud van de A-, X- en Y-registers naar de stapel in de hoop dat ze nodig zullen zijn voor welke code (programma) dan ook die vlak voor de onderbreking wordt uitgevoerd. De volgende drie instructies vormen de kern van de interrupthandler. De PLY-, PLX- en PLA-instructies moeten in die volgorde staan ​​en ze brengen de inhoud van de Y-, X- en A-registers terug. De laatste instructie, RTI, (zonder een operand) retourneert de voortzetting van de uitvoering naar welke code (programma) dan ook die wordt uitgevoerd vóór de onderbreking. RTI trekt het adres van de volgende instructie van de code die wordt uitgevoerd van de stapel terug naar de programmateller. RTI betekent ReTurn van Interrupt. Daarmee is de interruptafhandeling (subroutine) voorbij.

Software-onderbreking
De belangrijkste manier om een ​​software-interrupt voor de 6502 µP te verkrijgen is door gebruik te maken van de impliciete adresinstructie van BRK. Stel dat het hoofdprogramma actief is en de BRK-instructie tegenkomt. Vanaf dat moment moet het adres van de volgende instructie op de pc naar de stapel worden gestuurd zodra de huidige instructie is voltooid. Een subroutine die de software-instructie afhandelt, zou “next” moeten heten. Deze interrupt-subroutine moet de inhoud van het A-, X- en Y-register naar de stapel duwen. Nadat de kern van de subroutine is uitgevoerd, moet de inhoud van de A-, X- en Y-registers door de voltooiing van de subroutine van de stapel naar hun registers worden teruggetrokken. De laatste instructie in de routine is RTI. De pc-inhoud wordt dankzij RTI ook automatisch teruggetrokken van de stapel naar de pc.

Vergelijking en contrast van subroutine en interrupt-serviceroutine
In de volgende tabel worden de subroutine en de interruptserviceroutine vergeleken en vergeleken:

4.17 Samenvatting van de belangrijkste adresseringsmodi van de 6502

Elke instructie voor de 6502 is één byte, gevolgd door nul of meer operanden.

Onmiddellijke adresseringsmodus
Bij de directe adresseringsmodus staat na de operand de waarde en geen geheugenadres. De waarde moet worden voorafgegaan door #. Als de waarde hexadecimaal is, moet de “#” worden gevolgd door “$”. De directe adresseringsinstructies voor de 65C02 zijn: ADC, AND, BIT, CMP, CPX, CPY, EOR, LDA, LDX, LDY, ORA, SBC. De lezer dient de documentatie voor 65C02 µP te raadplegen om te weten hoe hij de instructies moet gebruiken die hier worden vermeld en die niet in dit hoofdstuk worden uitgelegd. Een voorbeeldinstructie is:

LDA#$77

Absolute adresseringsmodus
In de absolute adresseringsmodus is er één operand. Deze operand is het adres van de waarde in het geheugen (meestal in hexadecimaal of een label). Er zijn 64K 10 = 65.536 10 geheugenadressen voor de 6502 µP. Normaal gesproken bevindt de waarde van één byte zich op een van deze adressen. De absolute adresseringsinstructies voor de 65C02 zijn: ADC, AND, ASL, BIT, CMP, CPX, CPY, DEC, EOR, INC, JMP, JSR, LDA, LDX, LDY, LSR, ORA, ROL, ROR, SBC, STA , STX, STY, STZ, TRB, TSB. De lezer dient de documentatie voor 65C02 µP te raadplegen om te weten hoe hij de hier vermelde instructies moet gebruiken, evenals voor de rest van de adresseringsmodi die niet in dit hoofdstuk worden uitgelegd. Een voorbeeldinstructie is:

ZE ZIJN $ 1234

Impliciete adresseringsmodus
In de impliciete adresseringsmodus is er geen operand. Elk betrokken µP-register wordt door de instructie geïmpliceerd. De impliciete adresseringsinstructies voor de 65C02 zijn: BRK, CLC, CLD, CLI, CLV, DEX, DEY, INX, INY, NOP, PHA, PHP, PHX, PHY, PLA, PLP, PLX, PLY, RTI, RTS, SEC , SED, SEI, BELASTING, TAY, TSX, TXA, TXS, TYA. Een voorbeeldinstructie is:

DEX: Verlaag het X-register met één eenheid.

Relatieve adresseringsmodus
De relatieve adresseringsmodus heeft alleen betrekking op vertakkingsinstructies. In de relatieve adresseringsmodus is er slechts één operand. Het is een waarde vanaf -128 10 tot +127 10 . Deze waarde wordt een offset genoemd. Op basis van het teken wordt deze waarde opgeteld bij of afgetrokken van de volgende instructie van de programmateller om te resulteren in het adres van de beoogde volgende instructie. De relatieve adresmodusinstructies zijn: BCC, BCS, BEQ, BMI, BNE, BPL, BRA, BVC, BVS. De instructievoorbeelden zijn:

BNE $7F : (tak als Z = 0 in statusregister, P)

Die voegt 127 toe aan de huidige programmateller (uit te voeren adres) en begint de instructie op dat adres uit te voeren. Op dezelfde manier:

BEQ $F9 : (tak als Z = : in statusregister, P)

Dit voegt een -7 toe aan de huidige programmateller en start de uitvoering op het nieuwe programmatelleradres. De operand is een twee-complementgetal.

Absoluut geïndexeerde adressering
Bij absolute indexadressering wordt de inhoud van het X- of Y-register opgeteld bij het gegeven absolute adres (ergens tussen $0000 en $FFFF, d.w.z. vanaf 0 10 naar 65536 10 ) om het echte adres te hebben. Dit gegeven absolute adres wordt het basisadres genoemd. Als het X-register wordt gebruikt, is de montage-instructie ongeveer als volgt:

LDA $C453,X

Als het Y-register wordt gebruikt, is het zoiets als:

LDA $C453,J

De waarde voor het X- of Y-register wordt de tel- of indexwaarde genoemd en kan ergens tussen $00 (0 10 ) naar $FF (250 10 ). Het wordt niet de offset genoemd.

De absolute indexadresseringsinstructies zijn: ADC, AND, ASL (alleen X), BIT (met accumulator en geheugen, alleen met X), CMP, DEC (alleen geheugen en X), EOR, INC (alleen geheugen en X), LDA , LDX, LDY, LSR (alleen X), ORA, ROL (alleen X), ROR (alleen X), SBC, STA, STZ (alleen X).

Absoluut indirecte adressering
Dit wordt alleen gebruikt bij de spronginstructie. Hiermee heeft het gegeven absolute adres een pointeradres. Het pointeradres bestaat uit twee bytes. De aanwijzer van twee bytes verwijst naar (is het adres van) de bestemmingsbytewaarde in het geheugen. De assembleertaalinstructie is dus:

JMP ($3456)

Tussen haakjes staat en $13 op de adreslocatie $3456, terwijl $EB op de adreslocatie $3457 staat (= $3456 + 1). Het bestemmingsadres is dan $13EB en $13EB is de aanwijzer. De absolute $3456 staat tussen haakjes in de instructie, waarbij 34 de lagere byte is en 56 de hogere byte.

4.18 Een string maken met de 6502 µP-assembleertaal

Zoals in het volgende hoofdstuk wordt gedemonstreerd, kan het bestand, nadat het in het geheugen is aangemaakt, op de schijf worden opgeslagen. Het bestand moet een naam krijgen. De naam is een voorbeeld van een string. Er zijn nog veel meer voorbeelden van strings bij het programmeren.

Er zijn twee manieren om een ​​reeks ASCII-codes te maken. Op beide manieren nemen alle ASCII-codes (tekens) opeenvolgende bytelocaties in het geheugen in. Op één van de manieren wordt deze reeks bytes voorafgegaan door een integer-byte die de lengte (aantal tekens) in de reeks (string) is. Op de andere manier wordt de reeks karakters opgevolgd (onmiddellijk gevolgd) door de Null-byte die 00 is 16 , dat wil zeggen $ 00. De lengte van de string (aantal tekens) wordt op deze andere manier niet aangegeven. Het Null-teken wordt op de eerste manier niet gebruikt.

Denk bijvoorbeeld eens aan de tekst 'Ik hou van jou!' tekenreeks zonder de aanhalingstekens. De lengte is hier 11; een spatie telt als één ASCII-byte (teken). Stel dat de string in het geheugen moet worden geplaatst, waarbij het eerste teken op adres $0300 staat.

De volgende tabel toont de stringgeheugeninstelling wanneer de eerste byte 11 is 10 = 0B 16 :

De volgende tabel toont de stringgeheugeninstelling wanneer de eerste byte “I” is en de laatste byte Null ($00):

De volgende instructie kan worden gebruikt om te beginnen met het maken van de string:

ZE KOSTEN $ 0300

Stel dat de eerste byte zich in de accumulator bevindt die naar de adreslocatie $0300 moet worden verzonden. Deze instructie geldt voor beide gevallen (beide soorten strings).

Nadat alle tekens één voor één in de geheugencellen zijn geplaatst, kan de string via een lus worden gelezen. In het eerste geval wordt het aantal tekens na de lengte uitgelezen. In het tweede geval worden de tekens gelezen vanaf “I” totdat aan het Null-teken, dat “Null” is, wordt voldaan.

4.19 Een array maken met de 6502 µP-assembleertaal

Een array van gehele getallen van één byte bestaat uit opeenvolgende geheugenbytelocaties met de gehele getallen. Vervolgens is er een aanwijzer die naar de locatie van het eerste gehele getal verwijst. Een array van gehele getallen bestaat dus uit twee delen: de aanwijzer en de reeks locaties.

Bij een array met strings kan elke string zich op een andere plaats in het geheugen bevinden. Vervolgens zijn er opeenvolgende geheugenlocaties met pointers waarbij elke pointer naar de eerste locatie van elke string verwijst. Een pointer bestaat in dit geval uit twee bytes. Als een string begint met zijn lengte, wijst de corresponderende aanwijzer naar de locatie van die lengte. Als een string niet begint met zijn lengte maar eindigt met een nulteken, wijst de corresponderende aanwijzer naar de locatie van het eerste teken van de string. En er is een pointer die verwijst naar het lagere byte-adres van de eerste pointer van opeenvolgende pointers. Een array van strings bestaat dus uit drie delen: de strings op verschillende plaatsen in het geheugen, de corresponderende opeenvolgende pointers, en de pointer naar de eerste pointer van de opeenvolgende pointers.

4.20 Problemen

De lezer wordt geadviseerd alle problemen in een hoofdstuk op te lossen voordat hij naar het volgende hoofdstuk gaat.

  1. Schrijf een assembleertaalprogramma dat begint bij $0200 voor de 6502 µP en voeg de niet-ondertekende getallen van 2A94 toe H (toevoegen) aan 2ABF H (augend). Laat de invoer en uitvoer in het geheugen staan. Maak het samengestelde programmadocument ook met de hand.
  2. Schrijf een assembleertaalprogramma dat begint bij $0200 voor de 6502 µP en trek de niet-ondertekende getallen van 1569 ervan af H (aftrekker) van 2ABF H (aftrektal). Laat de in- en uitgangen in het geheugen staan. Maak het samengestelde programmadocument ook met de hand.
  3. Schrijf een assembleertaalprogramma voor de 6502 µP dat met behulp van een lus optelt van $00 naar $09. Het programma zou moeten beginnen bij $ 0200. Maak het samengestelde programmadocument ook met de hand.
  4. Schrijf een assembleertaalprogramma dat begint bij $0200 voor de 6502 µP. Het programma heeft twee subroutines. De eerste subroutine voegt de niet-ondertekende nummers van 0203 toe H (augend) en 0102H (toevoegen). De tweede subroutine telt de som van de eerste subroutine, namelijk 0305H, op tot 0006 H (augend). Het eindresultaat wordt in het geheugen opgeslagen. Roep de eerste subroutine aan die FSTSUB is en de tweede subroutine die SECSUB is. Laat de in- en uitgangen in het geheugen staan. Maak ook het samengestelde programmadocument voor het hele programma met de hand.
  5. Gezien het feit dat een IRQ handler voegt $02 tot $01 toe aan de accumulator als kernbehandeling terwijl NMI wordt uitgegeven en de kernbehandeling daarvoor NMI voegt $05 tot $04 toe aan de accumulator, schrijf een assembleertaal voor beide handlers inclusief hun oproepen. De oproep aan de IRQ De handler moet zich op het adres $0200 bevinden. De IRQ handler moet beginnen op het adres $0300. De NMI handler moet beginnen op het adres $0400. Het resultaat van de IRQ handler moet op het adres $0500 worden geplaatst, en het resultaat van de NMI handler moet op het adres $0501 worden geplaatst.
  6. Leg kort uit hoe de BRK-instructie wordt gebruikt om de software-interrupt in een 65C02-computer te produceren.
  7. Maak een tabel die een normale subroutine vergelijkt en contrasteert met een interrupt-serviceroutine.
  8. Leg kort de belangrijkste adresseringsmodi van de 65C02 µP uit, gegeven de instructievoorbeelden in de assembleertaal.
  9. a) Schrijf een 6502-machinetaalprogramma met de tekst 'Ik hou van jou!' reeks ASCII-codes in het geheugen, beginnend bij het adres $0300 met de lengte van de reeks. Het programma zou moeten starten op het adres $0200. Haal elk personage één voor één uit de accumulator, ervan uitgaande dat ze daarheen worden gestuurd, door een of andere subroutine. Monteer het programma ook met de hand. (Als je de ASCII-codes wilt weten voor “Ik hou van jou!”. Hier zijn ze: ‘I’:49 16 , ruimte : 20 16 , ‘l’: 6C 16 , ‘o’:6F 16 , 'in':76 16 , 'e':65, 'y':79 16 , 'in':75 16 , en ‘!’:21 16 (Opmerking: elke code beslaat 1 byte).
    b) Schrijf een 6502-machinetaalprogramma met de tekst 'Ik hou van jou!' reeks ASCII-codes in het geheugen, beginnend bij het adres $0300 zonder de lengte van de reeks, maar eindigend op 00 16 . Het programma zou moeten starten op het adres $0200. Haal elk personage uit de accumulator, ervan uitgaande dat ze daar één voor één door een of andere subroutine naartoe worden gestuurd. Monteer het programma ook met de hand.