Kapitel 4: 6502 Microprocessor Assembly Language Tutorial

Kapitel 4 6502 Microprocessor Assembly Language Tutorial



Kapitel 4: 6502 Microprocessor Assembly Language Tutorial

4.1 Indledning

6502-mikroprocessoren blev udgivet i 1975. Den blev brugt som mikroprocessor til nogle personlige computere dengang, såsom Apple II, Commodore 64 og BBC Micro.







6502 mikroprocessoren bliver stadig produceret i stort antal i dag. Det er ikke længere en central behandlingsenhed, der i dag bruges i personlige computere (laptops), men den produceres stadig i stort antal og bruges i elektroniske og elektriske apparater i dag. For at forstå de mere moderne computerarkitekturer er det meget nyttigt at undersøge en ældre, men ret vellykket mikroprocessor som 6502.



Da det er nemt at forstå og programmere, er det en af ​​de bedste (hvis ikke den bedste) mikroprocessorer at bruge til undervisning i assemblersprog. Assembly sprog er et lavt niveau sprog, der kan bruges til at programmere en computer. Bemærk, at assemblersproget for en mikroprocessor er forskelligt fra assemblersproget for en anden mikroprocessor. 6502 mikroprocessor assemblersproget er undervist i dette kapitel. Mere præcist er det 65C02, der undervises i, men omtales blot som 6502.



En berømt computer i fortiden hedder commodore_64. 6502 er en mikroprocessor i 6500-familien. Commodore_64-computeren bruger 6510-mikroprocessoren. 6510 mikroprocessoren er af 6500 µP. Instruktionssættet til 6502 µP er næsten alle instruktionerne til 6510 µP. Kendskabet til dette kapitel og det næste er baseret på computeren commodore_64. Denne viden bruges som grundlag for at forklare de moderne computerarkitekturer og moderne operativsystemer i denne del af online karrierekurset.





Computerarkitektur refererer til komponenterne på computerens bundkort og en forklaring på, hvordan dataene flyder inden for hver komponent, især mikroprocessoren, hvordan dataene flyder mellem komponenterne, og også hvordan dataene interagerer. Ental for data er datum. En effektiv måde at studere computerarkitekturen på er at studere bundkortets assemblersprog.

Commodore_64-computeren siges at være en computer med 8-bit computerord. Det betyder, at informationen lagres, overføres og manipuleres i form af otte-bit binære koder.



Blokdiagram af Commodore 64 bundkort
Blokdiagrammet for commodore 64 bundkortet er:


Fig. 4.1 Blokdiagram af Commodore_64 System Unit

Forestil dig 6510-mikroprocessoren som 6502-mikroprocessoren. Den samlede hukommelse er en serie af bytes (8-bits pr. byte). Der er hukommelsen med tilfældig adgang (læse/skrive), hvortil bytes kan skrives eller slettes. Når strømmen til computeren slukkes, slettes al information i RAM (Random-Access Memory). Der er også skrivebeskyttet hukommelse (ROM). Når strømmen til computeren er slukket, forbliver informationen i ROM'en (slettes ikke).

Der er input/output-porten (kredsløb), som omtales som input/output-enhederne i diagrammet. Denne port må ikke forveksles med de porte, der er synlige på venstre og højre eller forreste og bagerste lodrette overflader af computerens systemenhed. Det er to forskellige ting. Forbindelserne fra denne indre port til de eksterne enheder såsom harddisken (eller floppy-disken), tastaturet og skærmen er ikke vist i diagrammet.

Der er tre busser (grupper af elektriske meget små ledere) i diagrammet. Hver ledning kan overføre en bit 1 eller bit 0. Databussen til overførsel af otte-bit byte ad gangen (én clock-impuls) til RAM og input/output-porten (input/output-enheder) er tovejs. Databussen er otte bit bred.

Alle komponenter er forbundet til adressebussen. Adressebussen er ensrettet fra mikroprocessoren. Der er seksten ledere til adressebussen, og hver bærer en bit (1 eller 0). Seksten bit sendes i én clock-impuls.

Der er kontrolbussen. Nogle af lederne i styrebussen ville overføre en bit hver fra mikroprocessoren til de andre komponenter. Nogle få kontrollinjer fører bits fra input/output (IO) porten til mikroprocessoren.

Computerhukommelse
RAM og ROM betragtes som én hukommelsesenhed. Denne samling er repræsenteret diagrammatisk som følger, hvor hexadecimale tal har '$'-præfikset:


Fig 4.11 Hukommelseslayout for Commodore 64-computeren

RAM er fra 0000 16 til DFFF 16 som er skrevet fra $0000 til $DFFF. Med 6502 µP assemblersproget får et hexadecimalt tal foran med '$' og ikke suffikset (underskrevet) med 16 eller H eller hex. Enhver information i RAM forsvinder, når computeren slukkes. ROM'en begynder fra $E000 til $FFFF. Den har underrutiner, som ikke slukkes, når computeren slukkes. Disse underrutiner er de almindeligt anvendte rutiner, som hjælper med programmering. Brugerprogrammet kalder dem (se næste kapitel).

Pladsen (bytes) fra $0200 til $D000 er til brugerprogrammerne. Pladsen fra $D000 til $DFFF er til information, der er direkte relateret til de eksterne enheder (input/output-enheder). Dette er en del af operativsystemet. Så operativsystemet på commodore-64 computeren er i to hoveddele: den del i ROM, der aldrig slukker, og den del fra $D000 til $DFFF, der slukkes, når strømmen slukkes. Disse IO (input/output) data skal indlæses fra en disk, hver gang computeren tændes. I dag kaldes sådanne data perifere drivere. De ydre enheder begynder fra Input/Output Device-porten gennem forbindelserne på bundkortet til de identificerbare porte på de lodrette overflader af computeren, som skærmen, tastaturet osv. er tilsluttet til, og til selve de eksterne enheder (skærm, tastatur osv. .).

Hukommelsen består af 2 16 = 65.536 byte-placeringer. I hexadecimal form er disse 10000 16 = 10.000 H = 10.000 hex = $10.000 steder. Ved beregning begynder tælling i basis to, basis ti, basis seksten osv. fra 0 og ikke fra 1. Så den første placering er faktisk lokationsnummeret 0000000000000000 2 = 0 10 = 0000 16 = $0000. I 6502 µP assemblersproget er identifikationen af ​​en adresseplacering præfikset med $, og der er intet suffiks eller sænket skrift. Det sidste sted er lokationsnummeret 1111111111111111 2 = 65.535 10 = FFFF 16 = $FFFF og ikke 10000000000000000 2 eller 65.536 10 eller 10000 16 , eller $10.000. De 1000000000000000 2 65.536 10 , 10000 16 , eller $10000 giver det samlede antal byteplaceringer.

Her, 2 16 = 65.536 = 64 x 1024 = 64 x 2 10 = 64 Kbytes (Kilobytes). Suffikset 64 i navnet Commodore-64 betyder 64KB samlet hukommelse (RAM og ROM). En byte er 8 bit, og de 8 bits vil gå til en byte placering i hukommelsen.

De 64 Kbytes hukommelse er opdelt i sider. Hver side har 0100 16 = 256 10 byte placeringer. De første 256 10 = første 0100 16 placeringer er side 0. Den anden er side 1, den tredje er side 2, og så videre.

For at adressere de 65.536 lokationer er 16 bit nødvendige for hver lokation (adresse). Så adressebussen fra mikroprocessoren til hukommelsen består af 16 linjer; en linje for en bit. En bit er enten 1 eller 0.

6502 µP registrene
Et register er ligesom bytecellerne for en bytehukommelsesplacering. 6502 µP har seks registre: fem 8-bit registre og et 16-bit register. 16-bit registeret kaldes Program Counter, som forkortes til PC. Den indeholder hukommelsesadressen til den næste instruktion. Et assemblersprogsprogram består af instruktioner, der er placeret i hukommelsen. Seksten (16) forskellige bit er nødvendige for at adressere en bestemt byteplacering i hukommelsen. Ved en bestemt clock-impuls sendes disse bit til adressebussens 16-bit adresselinjer til læsning af en instruktion. Alle registre for 6502 µP er afbildet som følger:


Fig. 4.12 6502 µP registre

Programtælleren eller pc'en kan ses som et 16-bit register i diagrammet. De lavere signifikante otte bit er mærket som PCL for Program Counter Low. De højere signifikante otte bit er mærket som PCH for Program Counter High. En instruktion i hukommelsen til Commodore-64 kan bestå af en, to eller tre bytes. De 16 bits i pc'en peger på den næste instruktion, der skal udføres, i hukommelsen. Blandt kredsløbene i mikroprocessoren kaldes to af dem Arithmetic Logic Unit og Instruction Decoder. Hvis den aktuelle instruktion, der behandles i µP (mikroprocessor) er en byte lang, øger disse to kredsløb pc'en for den næste instruktion med 1 enhed. Hvis den aktuelle instruktion, der behandles i µP, er to bytes lang, hvilket betyder, at den optager to på hinanden følgende bytes i hukommelsen, øger disse to kredsløb pc'en for den næste instruktion med 2 enheder. Hvis den aktuelle instruktion, der behandles i µP, er tre byte lang, hvilket betyder, at den optager tre på hinanden følgende bytes i hukommelsen, øger disse to kredsløb pc'en for den næste instruktion med 3 enheder.

Akkumulatoren 'A' er et otte-bits generel register, der gemmer resultatet af de fleste aritmetiske og logiske operationer.

'X' og 'Y' registrene bruges hver til at tælle programtrinene. Optællingen i programmering begynder fra 0. Så de kaldes som indeksregistre. De har et par andre formål.

Selvom Stack Pointer-registret har 'S' 9 bit, der betragtes som et otte-bit register. Dens indhold peger på en byte-placering på side 1 i Random Access Memory (RAM). Side 1 begynder fra byte $0100 (256 10 ) til byte $01FF (511 10 ). Når et program kører, flyttes det fra en instruktion til den næste på hinanden følgende instruktion i hukommelsen. Dette er dog ikke altid tilfældet. Der er tidspunkter, hvor den hopper fra et hukommelsesområde til et andet hukommelsesområde for at fortsætte med at køre instruktionerne der, fortløbende. Side 1 i RAM bruges som stakken. Stakken er et stort RAM-hukommelsesområde, der har de næste adresser til fortsættelse af koden, hvorfra der er et spring. Koderne med springinstruktioner er ikke i stakken; de er andre steder i hukommelsen. Men efter at spring-til-instruktionerne er udført, er fortsættelsesadresserne (ikke kodesegmenter) i stakken. De blev skubbet dertil som følge af spring- eller greninstruktionerne.

8-bit processorstatusregisteret for P er en speciel type register. De enkelte bits er ikke relateret til eller forbundet med hinanden. Hver bit der kaldes et flag og værdsættes uafhængigt af de andre. Betydningen af ​​flagene er givet i det følgende, efterhånden som behovet opstår.

Det første og sidste bitindeks for hvert register er angivet over hvert register i det foregående diagram. Bitindeks (position)-tællingen i et register begynder fra 0 til højre.

Hukommelsessider i binær, hexadecimal og decimal
Følgende tabel viser begyndelsen af ​​hukommelsessiderne i binær, hexadecimal og decimal:

Hver side har 1.000.0000 2 antal bytes, som er det samme som 100 H antal bytes, som er det samme som 256 10 antal bytes. I det foregående hukommelsesdiagram er siderne angivet, der går op fra side 0 og ikke går ned som angivet i tabellen.

De binære, hexadecimale og decimale kolonner i denne tabel giver hukommelsesbyteplaceringsadresserne i deres forskellige baser. Bemærk, at for side nul er det kun bits for den nederste byte, der er nødvendige for at skrive ved kodning. Bittene for den højere byte kan udelades, da de altid er nuller (for side nul). For resten af ​​siderne skal bits for den højere byte bruges.

Resten af ​​dette kapitel forklarer 6502 µP Assembly Language ved hjælp af alle de tidligere oplysninger. For hurtigt at forstå sproget skal læseren addere og trække fra i grundtallet seksten i stedet for titallet. Det er egentlig meningen, at det skal være base to, men at regne i base to er besværligt. Husk, at når du tilføjer to tal i base to, er en carry stadig 1 som i base ti. Men når man trækker to tal fra i basis to, er et lån to og ikke ti som i basis ti. Når du tilføjer to tal i base seksten, er en carry stadig 1 som i base ti. Men når man trækker to tal fra i grundtallet seksten, er et lån seksten og ikke ti som i grundtallet ti.

4.2 Instruktioner til dataoverførsel

Overvej følgende tabel med instruktionerne til overførsel af assemblersprog for 6502 µP:

Når en byte (8-bit) kopieres fra en hukommelsesbyteplacering til akkumulatorregistret, X-registret eller Y-registret, indlæses det. Når en byte kopieres fra et af disse registre til en hukommelsesbyteplacering, er det overførsel. Når en byte kopieres fra et register til et andet, overføres det stadig. I den anden kolonne i tabellen viser pilen retningen af ​​kopien for en byte. Resten af ​​de fire kolonner viser forskellige adresseringstilstande.

En indtastning i adresseringstilstandskolonnen er den faktiske bytekode for den tilsvarende mnemoniske del af instruktionen i hexadecimal. AE, for eksempel, er den faktiske byte-kode for LDX, som skal indlæse en byte fra hukommelsen til X-registret i absolut adresseringstilstand som AE 16 = 10101110 2 . Så bits for LDX i en hukommelsesbyteplacering er 10101110.

Bemærk, at for den LDX-mnemoniske del af instruktionen er der tre mulige bytes, som er A2, AE og A6, og hver er til en bestemt adresseringstilstand. Når den byte, der indlæses i X-registret, ikke skal kopieres fra en hukommelsesbyte-placering, skal værdien indtastes med (lige efter) LDX-mnemonikken i instruktionen i hexadecimal eller decimal. I dette kapitel er sådanne værdier skrevet med hexadecimal. Dette er øjeblikkelig adressering, så den faktiske byte i hukommelsen til at repræsentere LDX er A2 16 = 10100010 2 og ikke AE 16 hvilket er lig med 10101110 2 .

I tabellen kaldes alle bytes under adresseringstilstandens overskrifter Operation Codes, som er forkortet som opcodes. Der kan være mere end én opcode for én mnemonic, afhængigt af adresseringstilstanden.

Bemærk: Ordet 'indlæs' i computerens systemenhed kan have to betydninger: det kan henvise til indlæsningen af ​​en fil fra en disk til computerens hukommelse, eller det kan henvise til overførslen af ​​en byte fra en hukommelsesbyteplacering til et mikroprocessorregister .

Der er flere adresseringstilstande end de fire i tabellen for 6502 µP.

Medmindre andet er angivet, begynder al brugerprogrammeringskode i dette kapitel fra adresse 0200 16 som er begyndelsen af ​​brugerområdet i hukommelsen.

Hukommelse M og akkumulator A

Hukommelse til akkumulator

Øjeblikkelig adressering
Den følgende instruktion gemmer nummeret FF 16 = 255 10 ind i akkumulatoren:

LDA #$FF

'$' bruges ikke kun til at identificere en hukommelsesadresse. Generelt bruges det til at angive, at det næste tal, der følger, er hexadecimalt. I dette tilfælde er $FF ikke adressen på nogen hukommelsesbyteplacering. Det er nummer 255 10 i hexadecimal. Base 16 eller nogen af ​​dens andre tilsvarende abonnenter må ikke skrives i assemblersprogsinstruktionen. '#' angiver, at det næste, der følger, er den værdi, der skal indsættes i akkumulatorregistret. Værdien kan også skrives i basis ti, men det er ikke gjort i dette kapitel. '#' betyder øjeblikkelig adressering.

En mnemonic har en vis lighed med dens tilsvarende engelske sætning. 'LDA #$FF' betyder at indlæse tallet 255 10 ind i akkumulatoren A. Da dette er umiddelbar adressering fra den foregående tabel, er LDA A9 og ikke AD eller A5. A9 i binær er 101010001. Så hvis A9 for LDA er i $0200-adresse i hukommelsen, er $FF i $0301 = 0300 + 1 adresse. #$FF er netop operanden for LDA-mnemonikken.

Absolut adressering
Hvis værdien af ​​$FF er på $0333 placering i hukommelsen, er den forrige instruktion:

LDA $0333

Bemærk fraværet af #. I dette tilfælde betyder fraværet af #, at det følgende er en hukommelsesadresse og ikke værdien af ​​interesse (ikke værdien, der skal indsættes i akkumulatoren). Så opkoden for LDA, denne gang, er AD og ikke A9 eller A5. Operanden for LDA her er $0333-adressen og ikke $FF-værdien. $FF er i $0333 placering, som er ret langt væk. 'LDA $0333'-instruktionen optager tre på hinanden følgende placeringer i hukommelsen, og ikke to, som den forrige illustration gjorde. 'AD' for LDA er på $0200 placeringen. Den nederste byte på 0333, som er 33, er på $0301-placeringen. Den højere byte på $0333, som er 03, er på $0302 placeringen. Dette er lidt endianness, som bruges af 6502 assemblersproget. Samlingssprogene for forskellige mikroprocessorer er forskellige.

Dette er et eksempel på absolut adressering. $0333 er adressen på det sted, der har $FF. Instruktionen består af tre på hinanden følgende bytes og inkluderer ikke $FF eller dens faktiske byteplacering.

Zero-Page Addressing

Antag, at $FF-værdien er i $0050-hukommelsesplaceringen på side nul. Byteplaceringerne for nulsiden begynder fra $0000 og slutter ved $00FF. Disse er 256 10 steder i alt. Hver side i Commodore-64-hukommelsen er 256 10 lang. Bemærk, at den højere byte er nul for alle mulige placeringer i nul-side pladsen i hukommelsen. Adresseringstilstanden med nul sider er den samme som den absolutte adresseringstilstand, men den højere byte på 00 indtastes ikke i instruktionen. Så for at indlæse $FF fra $0050 placeringen i akkumulatoren, er instruktionen i nul-side adresseringstilstand:

LDA $50

Med LDA er A5 og ikke A9 eller AD, A5 16 = 10100101 2 . Husk, at hver byte i hukommelsen består af 8 celler, og hver celle rummer en bit. Instruktionen her består af to på hinanden følgende bytes. A5 for LDA er i $0200-hukommelsesplaceringen, og $50-adressen, uden den højere byte på 00, er på $0301-placeringen. Fraværet af 00, som ville have forbrugt en byte i den samlede 64K hukommelse, sparer hukommelsespladsen.

Akkumulator til hukommelse

Absolut adressering
Den følgende instruktion kopierer en byteværdi, uanset hvad den er, fra akkumulatoren til hukommelsesplaceringen på $1444:

DE ER 1444 $

Dette siges at være overførsel fra akkumulatoren til hukommelsen. Den indlæses ikke. Indlæsning er det modsatte. Opcode-byten for STA er 8D 16 = 10001101 2 . Denne instruktion består af tre på hinanden følgende bytes i hukommelsen. 8D 16 er på $0200 lokationen. Den 44 16 af $1444-adressen er på $0201-lokationen. Og 14 16 er i $0202 lokationen - lidt endianness. Den faktiske byte, der kopieres, er ikke en del af instruktionen. 8D og ikke 85 til nulsideadressering (i tabellen) bruges her for STA.

Nul sideadressering
Den følgende instruktion kopierer en byteværdi, uanset hvad den er, fra akkumulatoren til hukommelsesplaceringen på $0050 på side nul:

STA $0050

Opcode-byten for STA her er 85 16 = 10000101 2 . Denne instruktion består af to på hinanden følgende bytes i hukommelsen. Den 85 16 er på lokation $0200. De 50 16 af $0050-adressen er på lokation $0201. Spørgsmålet om endianness opstår ikke her, fordi adressen kun har én byte, som er den nederste byte. Den faktiske byte, der kopieres, er ikke en del af instruktionen. 85 og ikke 8D til nulsideadressering bruges her til STA.

Det giver ikke mening at bruge den umiddelbare adressering til at overføre en byte fra akkumulatoren til en placering i hukommelsen. Dette skyldes, at den faktiske værdi som $FF skal angives i instruktionen i øjeblikkelig adressering. Så øjeblikkelig adressering er ikke mulig for overførsel af en byteværdi fra et register i µP til enhver hukommelsesplacering.

LDX, STX, LDY og STY Mnemonics
LDX og STX ligner henholdsvis LDA og STA. Men her bruges X-registret og ikke A-registret (akkumulator). LDY og STY ligner henholdsvis LDA og STA. Men her bruges Y-registret og ikke A-registret. Se tabel 4.21 for hver opkode i hexadecimal, der svarer til en bestemt mnemonisk og en bestemt adresseringstilstand.

Registrer-til-registrer-overførsler
De to foregående sæt instruktioner i tabel 4.21 omhandler kopiering af hukommelse/mikroprocessor-register (overførsel) og register-/registerkopiering (overførsel). TAX-, TXA-, TAY-, TYA-, TSX- og TXS-instruktionerne kopierer (overfører) fra registeret i mikroprocessoren til et andet register i den samme mikroprocessor.

For at kopiere byten fra A til X er instruktionen:

SKAT

For at kopiere byten fra X til A er instruktionen:

TX

For at kopiere byten fra A til Y er instruktionen:

HÅND

For at kopiere byten fra Y til A er instruktionen:

TYA

For commodore 64 computeren er stakken side 1 lige efter side 0 i hukommelsen. Som alle andre sider består den af ​​25610 10 byte-placeringer, fra $0100 til $01FF. Normalt udfører et program fra en instruktion til den næste på hinanden følgende instruktion i hukommelsen. Fra tid til anden er der et spring til et andet hukommelseskode (sæt instruktioner) segment. Stakområdet i hukommelsen (RAM) har de næste instruktionsadresser, hvorfra springene (eller grenene) slap for programfortsættelse.

Stakmarkøren 'S' er et 9-bit register i 6502 µP. Den første bit (længst til venstre) er altid 1. Alle byteplaceringsadresserne på side et begynder med 1 efterfulgt af 8 forskellige bits for de 256 10 placeringer. Stakmarkøren har adressen på lokationen på side 1, som har adressen på den næste instruktion, som programmet skal vende tilbage og fortsætte med efter at have udført det aktuelle (hoppede til) kodesegment. Da den første bit af alle adresserne på stakken (side et) begynder med 1, behøver stakpointerregisteret kun at indeholde de resterende otte bit. Når alt kommer til alt, er dens første bit, som er bit længst til venstre (den niende bit tæller fra højre), altid 1.

For at kopiere byten fra S til X er instruktionen:

TSX

For at kopiere byten fra X til S er instruktionen:

TXT

Register-til-registrerings-instruktionerne tager ikke nogen operand. De består kun af mnemonikken. Hver mnemonic har sin opkode i hexadecimal. Dette er i underforstået adresseringstilstand, fordi der ikke er nogen operand (ingen hukommelsesadresse, ingen værdi).

Bemærk: Der er ingen X til Y eller Y til X overførsel (kopiering).

4.3 Aritmetiske operationer

Kredsløbet, Arithmetic Logic Unit i 6502 µP, kan kun tilføje to otte-bit tal ad gangen. Den trækker ikke fra, den formerer sig ikke, og den deler sig ikke. Følgende tabel viser opkoderne og adresseringstilstandene for aritmetiske operationer:

Bemærk: Alle mnemonics til aritmetiske operationer og andre typer operationer (dvs. alle 6502 mnemonics) tager en byte af operationskode (op). Hvis der er mere end én adresseringstilstand for mnemonicen, ville der være forskellige opkoder for den samme mnemonic: en pr. adresseringstilstand. C, D og V i tabellen er statusregistrets flag. Deres betydning vil blive givet senere, når behovet opstår.

Tilføjelse af usignerede numre
Med 6502 µP er de signerede numre tos komplementtal. De usignerede tal er almindelige positive tal, der begynder fra nul. Så for en byte på otte-bit er det mindste tal uden fortegn 00000000 2 = 0 10 = 00 16 og det største usignerede nummer er 11111111 2 = 255 10 = FF 16 . For to usignerede numre er tilføjelsen:

A+M+C→A

Det betyder, at akkumulatorens 8-bit indhold tilføjes af den aritmetiske logiske enhed til en byte (8-bit) fra hukommelsen. Efter tilføjelsen af ​​A og M går overføringen til den niende bit til bæreflagcellen i statusregisteret. Enhver tidligere bærebit fra en tidligere tilføjelse, som stadig er i bæreflagcellen i statusregistret, tilføjes også til summen af ​​A og M, hvilket gør A+M+C→A. Resultatet lægges tilbage i akkumulatoren.

Hvis tillægget af interesse er:

A + M

Og der er ingen grund til at tilføje nogen tidligere carry, bæreflaget skal ryddes, hvilket er gjort til 0, så tilføjelsen er:

A+M+0→A samme som A+M→A

Bemærk: Hvis M føjes til A, og en carry på 1 forekommer, fordi resultatet er større end 255 10 = 11111111 2 = FF 16 , dette er en ny bære. Denne nye carry på 1 sendes automatisk til transportflagcellen i tilfælde af, at det er nødvendigt for det næste par af otte-bit, der skal summeres (en anden A + M).

Kode for at tilføje to usignerede otte-bits
00111111 2 +00010101 2 er det samme som 3F 16 + 15 16 hvilket er det samme som 63 10 +21 10 . Resultatet er 010101002 2 hvilket er det samme som 54 16 og 84 10 . Resultatet er ikke over det maksimale antal for otte bit, som er 255 10 = 11111111 2 = FF 16 . Så der er ingen resulterende carry af 1. For at sige det på en anden måde, den resulterende carry er 0. Før tilføjelsen er der ingen tidligere carry på 1. Med andre ord, den forrige carry er 0. Koden til at foretage denne tilføjelse måske:

CLC
LDA #$3F
ADC #$15

Bemærk: Mens du skriver assemblersproget, trykkes der på 'Enter'-tasten på tastaturet i slutningen af ​​hver instruktion. Der er tre instruktioner i denne kode. Den første instruktion (CLC) sletter bæreflaget, hvis en tidligere tilføjelse har 1. CLC kan kun udføres i underforstået adresseringstilstand. Mnemonikken for underforstået adresseringstilstand tager ingen operand. Dette sletter bærecellen i statusregistret for P. Rydning betyder at give bitten 0 til bæreflagcellen. De næste to instruktioner i koden bruger den øjeblikkelige adresseringstilstand. Med umiddelbar adressering er der kun én operand for mnemonikken, som er et tal (og hverken en hukommelse eller registeradresse). Derfor skal tallet være '#' foran. '$' betyder, at tallet, der følger, er hexadecimalt.

Den anden instruktion indlæser tallet 3F 16 ind i akkumulatoren. For den tredje instruktion tager det aritmetiske logiske enhedskredsløb for µP den forrige (ryddede) overføring af 0 (tvunget til 0) af bæreflagcellen, af statusregisteret og tilføjer den til 15 16 samt til den værdi, der allerede er i 3F 16 akkumulator og sætter det komplette resultat tilbage i akkumulatoren. I dette tilfælde er der en resulterende carry på 0. ALU (Aritmetic Logic Unit) sender (sætter) 0 ind i bæreflagcellen i statusregistret. Processorstatusregistret og statusregistret betyder det samme. Hvis en carry på 1 resulterede, sender ALU'en 1 til bæreflaget for statusregistret.

De tre linjer med tidligere kode skal være i hukommelsen, før de udføres. Opkoden 1816 for CLC (implied addressing) er på $0200 byte-placering. Opkoden A9 16 for LDA (umiddelbar adressering) er på $0201 byte placering. Tallet 3F 10 er på $0202 byte placering. Opkoden 69 16 for LDA (umiddelbar adressering) er på $0203 byte placering. Tallet 15 10 er på $0204 byte placering.

Bemærk: LDA er en overførselsinstruktion (belastning) og ikke en aritmetisk instruktion (mnemonisk).

Kode til at tilføje to usignerede seksten-bits
Alle registre i 6502 µP er i det væsentlige otte-bit registre, undtagen pc'en (programtæller), der er 16-bit. Selv statusregisteret er 8-bit bredt, selvom dets otte bits ikke fungerer sammen. I dette afsnit overvejes tilføjelsen af ​​to 16 bit uden fortegn, med en overføring fra det første par på otte bit til det andet par på otte bit. Bæren af ​​interesse her er overføringen fra den ottende bitposition til den niende bitposition.

Lad tallene være 0010101010111111 2 = 2ABF16 16 = 10.943 10 og 0010101010010101 2 = 2A95 16 = 10.901 10 . Summen er 0101010101010100 2 = 5554 16 = 21.844 10 .

Tilføjelse af disse to tal uden fortegn i basis to er som følger:

Følgende tabel viser den samme tilføjelse med overføring af 1 fra den ottende bit til den niende bit position, begyndende fra højre:

Ved kodning af dette tilføjes de to nederste bytes først. Derefter sender ALU (Aritmetic Logic Unit) overføringen af ​​1 fra den ottende bitposition til den niende bitposition til bæreflagcellen i statusregisteret. Resultatet af 0 1 0 1 0 1 0 0 uden carry går til akkumulatoren. Derefter tilføjes det andet par bytes med carry. ADC-mnemonikken betyder automatisk tilføjelse med den forrige carry. I dette tilfælde må den tidligere carry, som er 1, ikke ændres før den anden tilføjelse. For den første tilføjelse, da enhver tidligere overføring ikke er en del af denne komplette tilføjelse, skal den ryddes (gjort 0).

For den komplette tilføjelse af de to par bytes er den første tilføjelse:

A + M + 0 -> A

Den anden tilføjelse er:

A + M + 1 -> A

Så bæreflaget skal slettes (givet værdi på 0) lige før den første tilføjelse. Følgende program, som læseren skal læse den følgende forklaring af, bruger den absolutte adresseringstilstand til denne summering:

CLC
LDA $0213
ADC $0215
; ingen clearing, fordi bæreflagværdien er nødvendig
STA $0217
LDA $0214
ADC $0216
STA $0218

Bemærk, at med 6502 assemblersproget begynder et semikolon en kommentar. Dette betyder, at i udførelsen af ​​programmet ignoreres semikolon og alt til højre. Det program, der tidligere er skrevet, er i en tekstfil, der gemmes med navnet på programmørens valg og med filtypen '.asm'. Det forrige program er ikke det nøjagtige program, der går til hukommelsen for udførelse. Det tilsvarende program i hukommelsen kaldes det oversatte program, hvor mnemonics er erstattet med opkoderne (bytes). Enhver kommentar forbliver i assemblersprogets tekstfil og fjernes, før det oversatte program når hukommelsen. Faktisk er der to filer, der er gemt på disken i dag: '.asm'-filen og '.exe'-filen. '.asm'-filen er den i den forrige illustration. '.exe'-filen er '.asm'-filen med alle kommentarer fjernet, og alle mnemonics erstattet af deres opkoder. Når den åbnes i en teksteditor, er '.exe'-filen uigenkendelig. Medmindre andet er angivet, kopieres '.exe'-filen til dette kapitels formål til hukommelsen begyndende fra $0200-placeringen. Dette er den anden betydning af indlæsning.

De to 16-bit tal, der skal tilføjes, optager fire bytes i hukommelsen til absolut adressering: to bytes pr. tal (hukommelse er en sekvens af bytes). Med absolut adressering er operanden til opkoden i hukommelsen. Det summerende resultat er to bytes bredt og skal også placeres i hukommelsen. Det giver i alt 6 10 = 6 16 bytes til input og output. Indgangene er ikke fra tastaturet, og outputtet er ikke fra skærmen eller printeren. Indgangene er i hukommelsen (RAM), og outputtet (summeringsresultat) går tilbage til hukommelsen (RAM) i denne situation.

Før et program køres, skal den oversatte version være i hukommelsen først. Ser man på den tidligere programkode, kan det ses, at instruktionerne uden kommentaren udgør 19 10 = 13 16 bytes. Så programmet tager fra $0200 byte placering i hukommelsen til $0200 + $13 - $1 = $0212 byte placeringer (startende fra $0200 og ikke $0201, hvilket indebærer - $1). Tilføjelse af de 6 bytes for input- og outputnumrene får hele programmet til at slutte på $0212 + $6 = $0218. Programmets samlede længde er 19 16 = 25 10 .

Den nederste byte af augend skal være i $0213-adressen, og den højere byte af samme augend skal være i $0214-adressen – lidt endianness. Tilsvarende skal den nederste byte af tilføjelsen være i $0215-adressen, og den højere byte af den samme tilføjelse skal være i $0216-adressen - little endianness. Den nederste byte af resultatet (sum) skal være i $0217-adressen, og den højere byte af det samme resultat skal være i $0218-adressen – little endianness.

Opkoden 18 16 for CLC (implied addressing) er i byteplaceringen på $0200. Opkoden for 'LDA $0213', dvs. AD 16 for LDA (absolut adressering), er i byteplaceringen på $0201. Den nederste byte af augend, som er 10111111, er i hukommelsesbyte-placeringen på $0213. Husk, at hver opkode optager én byte. '$0213'-adressen på 'LDA $0213' er i byteplaceringerne $0202 og $0203. 'LDA $0213'-instruktionen indlæser den nederste byte af augend til akkumulatoren.

Opkoden for 'ADC $0215', dvs. 6D 16 for ADC (absolut adressering), er i byteplaceringen på $0204. Den nederste byte af tilføjelsen, som er 10010101, er i byteplaceringen på $0215. '$0215'-adressen på 'ADC $0215' er i byteplaceringerne $0205 og $0206. 'ADC $0215'-instruktionen tilføjer den nederste byte af tilføjelsen til den nederste byte af den augend, som allerede er i akkumulatoren. Resultatet placeres tilbage i akkumulatoren. Enhver overførsel efter den ottende bit sendes til statusregistrets bæreflag. Bæreflagcellen må ikke ryddes før den anden tilføjelse af de højere bytes. Denne carry tilføjes automatisk til summen af ​​de højere bytes. Faktisk tilføjes en carry på 0 til summen af ​​de lavere bytes automatisk i begyndelsen (svarende til, at der ikke tilføjes nogen carry) på grund af CLC.

Kommentaren tager de næste 48 10 = 30 16 bytes. Dette forbliver dog kun i '.asm'-tekstfilen. Det når ikke hukommelsen. Det fjernes af oversættelsen, som udføres af assembleren (et program).

For den næste instruktion, som er 'STA $0217', opkoden for STA, som er 8D 16 (absolut adressering) er i byte-placeringen på $0207. '$0217'-adressen på 'STA $0217' er i hukommelsesplaceringerne $0208 og $0209. 'STA $0217'-instruktionen kopierer 8-bit indholdet af akkumulatoren til hukommelsesplaceringen på $0217.

Den højere byte af augend, som er 00101010, er i hukommelsesplaceringen på $0214, og den højere byte af tilføjelsen, som er 00101010, er i byteplaceringen på $02 16 . Opkoden for 'LDA $0214', som er AD16 for LDA (absolut adressering) er i byte-placeringen på $020A. '$0214'-adressen på 'LDA $0214' er på placeringerne $020B og $020C. 'LDA $0214'-instruktionen indlæser den højere byte af augend til akkumulatoren og sletter alt, hvad der er i akkumulatoren.

Opkoden for 'ADC $0216', som er 6D 16 for ADC (absolut adressering) er i byteplaceringen på $020D. '$0216'-adressen på 'ADC 0216' er i byteplaceringerne $020E og $020F. 'ADC $0216'-instruktionen tilføjer den højere byte af addend til den højere byte af augend, som allerede er i akkumulatoren. Resultatet placeres tilbage i akkumulatoren. Hvis der er en carry på 1, for denne anden tilføjelse, placeres den automatisk i bærecellen i statusregistret. Selvom bæringen ud over den sekstende bit (venstre) ikke er påkrævet for dette problem, er det rart at kontrollere, om en bæring på 1 fandt sted ved at kontrollere, om bæreflaget blev 1.

For den næste og sidste instruktion, som er 'STA $0218', er opkoden for STA, som er 8D16 (absolut adressering), i byteplaceringen på $0210. '$0218'-adressen på 'STA $0218' er i hukommelsesplaceringerne $0211 og $0212. 'STA $0218'-instruktionen kopierer otte-bit indholdet af akkumulatoren til hukommelsesplaceringen på $0218. Resultatet af tilføjelsen af ​​de to seksten-bit tal er 0101010101010100, med den nederste byte på 01010100 i hukommelsesplaceringen på $0217 og den højere byte på 01010101 i hukommelsesplaceringen på $0218 – lille endianness.

Subtraktion
Med 6502 µP er de signerede numre tos komplementtal. Et tos komplementtal kan være otte-bit, seksten bit eller et hvilket som helst multiplum af otte bit. Med to’s komplement er den første bit fra venstre fortegnsbitten. For et positivt tal er denne første bit 0 for at angive tegnet. Resten af ​​bitsene danner tallet på normal vis. For at opnå de tos komplement af et negativt tal, skal du invertere alle bits for det tilsvarende positive tal og derefter tilføje 1 til resultatet fra højre ende.

For at trække et positivt tal fra et andet positivt tal, konverteres subtrahenden til et negativt to-komplement tal. Derefter tilføjes minuenden og det nye negative tal på normal vis. Så otte-bit subtraktionen bliver:

Hvor carry antages som 1. Resultatet i akkumulatoren er forskellen i to’s komplement. Så for at trække to tal fra, skal bæreflaget indstilles (gjort til 1).

Når du trækker to seksten-bit-tal fra, foretages subtraktionen to gange ligesom med tilføjelse af to seksten-bit-tal. Da subtraktion er en form for addition med 6502 µP, sættes bæreflaget kun én gang for den første subtraktion, når to seksten-bit tal trækkes fra. For den anden subtraktion udføres enhver indstilling af bæreflaget automatisk.

Programmering af subtraktionen for otte-bit-tal eller seksten-bit-tal udføres på samme måde som at programmere additionen. Bæreflaget skal dog sættes helt i begyndelsen. Mnemonikken til at gøre dette er:

Subtraktion med seksten-bit positive tal
Overvej subtraktionen med følgende tal:

Denne subtraktion involverer ikke tos komplement. Da subtraktionen i 6502 µP udføres i to's komplement, udføres subtraktionen i base to som følger:

De tos komplementresultat er det samme som resultatet, der opnås ved den almindelige subtraktion. Bemærk dog, at 1'eren, der går til den syttende bitposition fra højre, ignoreres. Minuenden og subtrahenden er opdelt i to otte bits hver. De tos komplement af 10010110 af subtrahendens lavere byte bestemmes uafhængigt af dens højere byte og enhver carry. De tos komplement af 11101011 af subtrahendens højere byte bestemmes uafhængigt af dens lavere byte og enhver carry.

Minuendens 16-bit er allerede i to’s komplement, begyndende med 0 fra venstre. Så det behøver ikke nogen justering i bits. Med 6502 µP føjes den nederste byte af minuenden uden nogen ændring til den nederste byte af de tos komplement af subtrahenden. Minuendens nederste byte konverteres ikke til to's komplement, fordi de seksten bits af hele minuenden allerede skal være i to's komplement (med et 0 som den første bit til venstre). I denne første tilføjelse tilføjes en obligatorisk carry på 1 på grund af 1=0 SEC instruktionen.

I den aktuelle effektive subtraktion er der en carry på 1 (addition) fra den ottende bit til den niende bit (fra højre). Da dette reelt er subtraktion, komplementeres (inverteres) den bit, der formodes at være i bæreflaget i statusregistret. Så bæringen af ​​1 bliver 0 i C-flaget. I den anden operation føjes den højere byte af minuenden til de højere tos komplementbyte af subtrahenden. Den automatisk komplementerede bæreflagbit i statusregistret (i dette tilfælde er 0) tilføjes også (til de højere bytes). Enhver 1, der går ud over den sekstende bit fra højre, ignoreres.

Den næste ting er bare at kode alt det skema som følger:

SEC
LDA $0213
SBC $0215
; ingen clearing, fordi den omvendte bæreflagværdi er nødvendig
STA $0217
LDA $0214
SBC $0216
STA $0218

Husk, at med 6502 assemblersproget begynder et semikolon en kommentar, som ikke er inkluderet i den oversatte programversion i hukommelsen. De to 16-bit tal til subtraktion optager fire bytes hukommelse med absolut adressering; to pr. tal (hukommelse er en række bytes). Disse input er ikke fra tastaturet. Det summerende resultat er to bytes og skal også placeres i hukommelsen et andet sted. Dette output går ikke til skærmen eller printeren; det går til hukommelsen. Det giver i alt 6 10 = 6 16 bytes til input og output, der skal placeres i hukommelsen (RAM).

Før et program køres, skal det være i hukommelsen først. Ser man på programkoden, kan det ses, at instruktionerne uden kommentaren udgør 19 10 = 13 16 bytes. Da alle programmer i dette kapitel begynder fra hukommelsesplaceringen på $0200, tager programmet fra $0200 byte placeringen i hukommelsen til $0200 + $13 – $1 = $0212 byte placering (begyndende fra $0200 og ikke $0201). Dette interval inkluderer ikke regionen for input- og outputbytes. De to inputtal tager 4 bytes, og det ene outputtal tager 2 bytes. Tilføjelse af de 6 bytes for input- og outputtallene gør intervallet for programmet, som ender på $0212 + $6 = $0218. Programmets samlede længde er 19 16 = 25 10 .

Den nederste byte af minuend skal være i $0213-adressen, og den højere byte af samme minuend skal være i $0214-adressen - lidt endianness. På samme måde skal den nederste byte af subtrahenden være i $0215-adressen, og den højere byte af den samme subtrahend skal være i $0216-adressen - little endianness. Den nederste byte af resultatet (forskel) skal være i $0217-adressen, og den højere byte af det samme resultat skal være i $0218-adressen - little endianness.

Opkoden for 38 16 for SEC (implied addressing) er i $0200-adressen. Alle programmer i dette kapitel antages at starte ved hukommelsesplaceringen på $0200, hvilket annullerer ethvert program, der ville have været der; medmindre andet er angivet. Opkoden for 'LDA $0213', dvs. AD 16 , for LDA (absolut adressering) er i $0201 byte placeringen. Den nederste byte af minuenden, som er 10111111, er i hukommelsesbyteplaceringen på $0213. Husk, at hver opkode optager én byte. '$0213'-adressen på 'LDA $0213' er i byteplaceringerne $0202 og $0203. 'LDA $0213'-instruktionen indlæser den nederste byte af minuenden til akkumulatoren.

Opkoden for 'SBC $0215', dvs. ED 16 , for SBC (absolut adressering) er i $0204 byte placeringen. Den nederste byte af subtrahenden, som er 01101010, er på $0215 byte-placeringen. '$0215'-adressen på 'ADC $0215' er i byteplaceringerne $0205 og $0206. 'SBC $0215'-instruktionen trækker den nederste byte af subtrahenden fra den nederste byte af minuenden, som allerede er i akkumulatoren. Dette er tos komplement subtraktion. Resultatet placeres tilbage i akkumulatoren. Komplementet (inversion) af enhver carry efter den ottende bit sendes til statusregistrets bæreflag. Dette bæreflag må ikke slettes før den anden subtraktion med de højere bytes. Denne carry tilføjes automatisk til subtraktionen af ​​de højere bytes.

Kommentaren tager de næste 57 10 = 3916 16 bytes. Dette forbliver dog kun i '.asm'-tekstfilen. Det når ikke hukommelsen. Det fjernes af oversættelsen, som udføres af assembleren (et program).

For den næste instruktion, som er 'STA $0217', opkoden for STA, dvs. 8D 16 (absolut adressering), er på $0207 byte placeringen. '$0217'-adressen på 'STA $0217' er i hukommelsesplaceringerne $0208 og $0209. 'STA $0217'-instruktionen kopierer 8-bit indholdet af akkumulatoren til hukommelsesplaceringen på $0217.

Den højere byte af minuenden, som er 00101010, er i hukommelsesplaceringen på $0214, og den højere byte af subtrahenden, som er 00010101, er i byteplaceringen på $0216. Opkoden for 'LDA $0214', dvs. AD 16 for LDA (absolut adressering), er på $020A byte-placeringen. '$0214'-adressen på 'LDA $0214' er på placeringerne $020B og $020C. 'LDA $0214'-instruktionen indlæser den højere byte af minuenden til akkumulatoren og sletter det, der er i akkumulatoren.

Opkoden for 'SBC $0216', dvs. ED 16 for SBC (absolut adressering), er i $020D byte placering. '$0216'-adressen på 'SBC $0216' er i byteplaceringerne $020E og $020F. 'SBC $0216'-instruktionen trækker den højere byte af subtrahenden fra den højere byte af minuenden (to-komplement), som allerede er i akkumulatoren. Resultatet placeres tilbage i akkumulatoren. Hvis der er en carry på 1 for denne anden subtraktion, placeres dens komplement automatisk i statusregisterets bærecelle. Selvom carry ud over den sekstende bit (venstre) ikke er påkrævet til dette problem, er det rart at kontrollere, om komplement-transporten forekommer ved at kontrollere carry-flaget.

For den næste og sidste instruktion, som er 'STA $0218', opkoden for STA, dvs. 8D 16 (absolut adressering), er på $0210 byte-placeringen. '$0218'-adressen på 'STA $0218' er i hukommelsesplaceringerne $0211 og $0212. 'STA $0218'-instruktionen kopierer otte-bit indholdet af akkumulatoren til hukommelsesplaceringen på $0218. Resultatet af subtraktionen med de to seksten-bit tal er 0001010101010101 med den nederste byte på 01010101 i hukommelsesplaceringen på $0217 og den højere byte på 00010101 i hukommelsesplaceringen på $0218 - lille endianness.

6502 µP har kun kredsløb til addition og indirekte til de tos komplement subtraktion. Den har ikke kredsløb til multiplikation og division. For at udføre multiplikationen og divisionen bør der skrives et assemblersprogsprogram med detaljer, herunder flytning af delprodukter og deludbytter.

4.4 Logiske operationer

I 6502 µP er mnemonikken for OR ORA og mnemonikken for eksklusiv OR er EOR. Bemærk, at de logiske operationer ikke har den underforståede adressering. Den underforståede adressering tager ingen operand. Hver af de logiske operatorer skal tage to operander. Den første er i akkumulatoren, og den anden er i hukommelsen eller i instruktionen. Resultatet (8-bit) er tilbage i akkumulatoren. Den første i akkumulatoren sættes enten der ved en øjeblikkelig instruktion eller kopieres fra hukommelsen med absolut adressering. I dette afsnit bruges kun nulsideadresseringen til illustration. Disse logiske operatorer er alle Bitwise-operatorer.

OG
Følgende tabel illustrerer Bitwise AND i binær, hexadecimal og decimal:

Alle programmerne i dette kapitel bør starte ved hukommelsesbyteplaceringen på $0200. Imidlertid er programmerne i dette afsnit på side nul, med det formål at illustrere brugen af ​​side nul uden den højere byte på 00000000 2 . Den tidligere ANDing kan kodes som følger:

LDA #$9A ; ikke fra hukommelsen - umiddelbar adressering
OG #$CD ; ikke fra hukommelsen - umiddelbar adressering
STA $30 ; gemmer $88 til nul-baserede $0030

ELLER
Følgende tabel illustrerer Bitwise OR i binær, hexadecimal og decimal:

LDA #$9A ; ikke fra hukommelsen - umiddelbar adressering
ORA #$CD ; ikke fra hukommelsen - umiddelbar adressering
STA $30 ; gemmer $CF til nul-baserede $0030

GRATIS
Følgende tabel illustrerer Bitwise XOR i binær, hexadecimal og decimal:

LDA #$9A ; ikke fra hukommelsen - umiddelbar adressering
EOR #$CD ; ikke fra hukommelsen - umiddelbar adressering
STA $30 ; gemmer $57 til nul-baserede $0030

4.5 Skift- og rotationsoperationer

Mnemonikken og opkoderne for skift- og rotationsoperatørerne er:

ASL: Skift til venstre en bit af akkumulator eller hukommelsesplacering, og indsæt 0 i den ledige celle længst til højre.

LSR: Skift til højre en bit af akkumulator eller hukommelsesplacering, og indsæt 0 i den ledige celle længst til venstre.
ROL: Drej en bit til venstre for akkumulator- eller hukommelsesplacering, og indsæt den bit, der er faldet ud til venstre, i den ledige celle længst til højre.
ROR: Drej en bit til højre for akkumulator- eller hukommelsesplacering, og indsæt den bit, der er faldet ud til højre, i den ledige celle længst til venstre.

For at lave et skift eller en rotation med akkumulatoren er instruktionen sådan her:

LSR A

Dette bruger en anden adresseringstilstand kaldet akkumulatoradresseringstilstanden.

For at lave et skift eller rotation med en byte-hukommelsesplacering er instruktionen noget som denne:

ROR $2BCD

Hvor 2BCD er hukommelsesplaceringen.

Bemærk, at der ikke er nogen umiddelbar eller underforstået adresseringstilstand til at skifte eller rotere. Der er ingen umiddelbar adresseringstilstand, fordi det ikke nytter noget at skifte eller rotere et tal, der kun forbliver i instruktionen. Der er ingen underforstået adresseringstilstand, fordi designerne af 6502 µP kun ønsker, at indholdet af akkumulatoren (A-registeret) eller en hukommelsesbyteplacering skal flyttes eller roteres.

4.6 Relativ adresseringstilstand

Mikroprocessoren inkrementerer altid (med 1, 2 eller 3 enheder) programtælleren (PC) for at pege på den næste instruktion, der skal udføres. 6502 µP har en instruktion, hvis mnemonic er BVS, hvilket betyder Branch on Overflow Set. Pc'en består af to bytes. Denne instruktion får pc'en til at have en anden hukommelsesadresse for den næste instruktion, der skal udføres, som ikke er resultatet af en normal stigning. Det gør det ved at tilføje eller trække en værdi, kaldet en offset, til indholdet af pc'en. Og så peger pc'en derefter på en anden (forgrenet) hukommelsesplacering, hvor computeren kan fortsætte med at udføre derfra. Forskydningen er et heltal fra -128 10 til +127 10 (to’er komplement). Så forskydningen kan få springet til at gå videre i hukommelsen. Hvis det er positivt eller bagud i hukommelsen, eller hvis det er negativt.

BVS-instruktionen tager kun én operand, som er offset. BVS bruger den relative adressering. Overvej følgende instruktion:

BVS $7F

I base to, 7F H er 01111111 2 = 127 10 . Antag, at indholdet i pc'en til den næste instruktion er $0300. BVS-instruktionen får $7F (et positivt tal allerede i to's komplement) til at blive tilføjet til $0300 for at give $037F. Så i stedet for den næste instruktion, der skal udføres ved hukommelsesplaceringen på $0300, er den på hukommelsesplaceringen $037F (ca. en halv sideforskel).

Der er andre greninstruktioner, men BVS er en meget god en at bruge til at illustrere den relative adressering. Relativ adressering omhandler greninstruktioner.

4.7 Indekseret adressering og indirekte adressering separat

Disse adresseringstilstande gør det muligt for 6502 µP at håndtere de enorme mængder data i korte perioder med reduceret antal instruktioner. Der er 64KB placeringer for hele Comodore-64 hukommelsen. Så for at få adgang til en hvilken som helst byteplacering på 16 bit, er det nødvendigt med to bytes. Den eneste undtagelse fra behovet for to bytes er for side nul, hvor den højere byte på $00 er udeladt for at spare på pladsen, der optages af instruktionen i hukommelsen. Med en ikke-side-nul adresseringstilstand er både de højere og lavere bytes af 16-bit hukommelsesadressen for det meste angivet på en eller anden måde.

Grundlæggende indekseret adressering

Absolut indeksadressering
Husk at X- eller Y-registret kaldes indeksregistret. Overvej følgende instruktion:

LDA $C453,X

Antag, at værdien af ​​6 H er i X-registret. Bemærk, at 6 ikke er skrevet nogen steder i instruktionen. Denne instruktion tilføjer værdien af ​​6H til C453 H som er en del af den maskinskrevne instruktion i tekstfilen, der stadig skal samles – C453 H + 6 H = C459 H . LDA betyder at indlæse en byte til akkumulatoren. Byten, der skal indlæses i akkumulatoren, kommer fra $C459-adressen. $C459, som er summen af ​​$C453, der er skrevet med instruktionen og 6 H som findes i X-registret bliver den effektive adresse, hvorfra den byte, der skal indlæses i akkumulatoren, kommer fra. Hvis 6 H var i Y-registret, indtastes Y i stedet for X i instruktionen.

I den indtastede instruktionssætning er $C453 kendt som basisadressen og 6 H i X- eller Y-registret er kendt som tælle- eller indeksdelen for den effektive adresse. Basisadressen kan referere til enhver byteadresse i hukommelsen og de næste 256 10 adresser kan tilgås, forudsat at det påbegyndte indeks (eller antal) i X- eller Y-registret er 0. Husk at en byte kan give et kontinuerligt område på op til 256 10 tal (dvs. 00000000 2 til 11111111 2 ).

Så den absolutte adressering tilføjer det, der allerede er sat (er blevet sat af en anden instruktion) i X- eller Y-registret til de 16 adresser, der er indtastet med instruktionen for at opnå den effektive adresse. I den indskrevne instruktion er de to indeksregistre kendetegnet ved X eller Y, som er skrevet efter et komma. Enten X eller Y er skrevet; ikke begge dele.

Når alt kommer til alt, er programmet skrevet i en teksteditor og gemt med filnavnet '.asm' filnavnet, så skal assembleren, som er et andet program, oversætte det indtastede program til det, der er (indlæst) i hukommelsen. Den tidligere instruktion, som er 'LDA $C453,X', optager tre byte-placeringer i hukommelsen og ikke fem.

Husk, at en mnemonic såsom LDA kan have mere end én opcode (forskellige bytes). Opkoden for instruktionen, der bruger X-registret, er forskellig fra den op-kode, der bruger Y-registret. Samleren ved, hvilken opcode der skal bruges baseret på den indtastede instruktion. En-byte-opkoden for 'LDA $C453,X' er forskellig fra en-byte-opkoden for 'LDA $C453,Y'. Faktisk er opkoden for LDA i 'LDA $C453,X' BD, og ​​opkoden for LDA i 'LDA $C453,9' er BD.

Hvis opkoden for LDA er i $0200 byte-placeringen. Derefter tager 16-bit-adressen på $C453 den næste til byte-placeringerne i hukommelsen, som er $0201 og $0202. Den særlige opcode-byte angiver, om det er X-registret eller Y-registret, der er involveret. Så den samlede sproginstruktion, som er 'LDA $C453,X' eller 'LDA $C453,Y' optager tre på hinanden følgende bytes i hukommelsen, og ikke fire eller fem.

Nul-side indekseret adressering
Den nulsides indeksadressering er som den absolutte indeksadressering, som tidligere er beskrevet, men målbyten må kun være på side nul (fra $0000 til $00FF). Når du nu har at gøre med nulsiden, er den højere byte, som altid er 00 H for hukommelsesplaceringerne undgås normalt. Så det nævnes normalt, at side nul begynder fra $00 til FF. Og så er den tidligere instruktion af 'LDA $C453,X':

LDA $53.X

$C4, en højere byte, der refererer til en side over sidenul, kan ikke anvendes i denne instruktion, da den sætter den forventede målbyte, der skal indlæses i den akkumulerede byte uden for og over sidens nul.

Når værdien som er indtastet i instruktionen lægges til værdien i indeksregisteret, skal summen ikke give et resultat over siden nul (FF H ). Så det er udelukket at have en instruktion som 'LDA $FF, X' og en værdi som FF H i indeksregistret fordi FF H + FF H = 200 H som er den første byte ($0200) placering af side 2 (tredje side) i hukommelsen, er en stor afstand fra side 0. Så med nul-side indekseret adressering, skal den effektive adresse ligge i side nul.

Indirekte adressering

Hop absolut adressering
Før vi diskuterer den absolutte indirekte adressering, er det godt først at se på JMP’s absolutte adressering. Antag, at adressen, der har værdien af ​​interesse (målbyte) er $8765. Dette er 16-bits bestående af to bytes: den højere byte, som er 87 H og den nederste byte, som er 65 H . Så de to bytes til $8765 sættes i pc'en (programtælleren) til den næste instruktion. Det, der skrives i assemblersprogprogrammet (filen), er:

JMP $8765

Det eksekverende program i hukommelsen hopper fra den adresse, det har adgang til, til $8765. JMP mnemonic har tre opkoder, som er 4C, 6C og 7C. Opkoden for denne absolutte adressering er 4C. Opkoden for JMP absolut indirekte adressering er 6C (se de følgende illustrationer).

Absolut indirekte adressering
Dette bruges kun sammen med jump-instruktionen (JMP). Antag, at adressen, der har interessebyten (målbyte), er $8765. Dette er 16-bits bestående af to bytes: den højere byte, som er 87 H og den nederste byte, som er 65 H . Med absolut indirekte adressering er disse to bytes faktisk placeret i to på hinanden følgende byteplaceringer andre steder i hukommelsen.

Antag, at de er placeret i hukommelsesplaceringerne $0210 og $0211. Derefter den nederste byte af interesseadressen, som er 65 H er i $0210-adressen, og den højere byte, som er 87 H er på $0211-adressen. Det betyder, at den lavere hukommelsesbyte af interesse går til lavere konsekutiv adresse, og den højere hukommelsesbyte af interesse går til den højere konsekutive adresse – little endianness.

16-bit adressen kan referere til to på hinanden følgende adresser i hukommelsen. I det lys henviser $0210-adressen til adresserne på $0210 og $0211. Adresseparret på $0210 og $0211 har den ultimative adresse (16-bits af to bytes) på målbyten, med den nederste byte på 65 H i $0210 og den højere byte på 87 H i $0211. Så springinstruktionen, der indtastes, er:

JMP (0210 USD)

JMP mnemonic har tre opkoder, som er 4C, 6C og 7C. Opkoden for absolut indirekte adressering er 6C. Det, der er skrevet i tekstfilen, er 'JMP ($0210)'. På grund af parenteserne bruger assembleren (oversætteren) opkoden 6C til JMP og ikke 4C eller 7C.

Med absolut indirekte adressering er der faktisk tre hukommelsesområder. Den første region kan bestå af byteplaceringerne $0200, $0201 og $0202. Dette har de tre bytes til 'JMP ($0210)' instruktionen. Den anden region, som ikke nødvendigvis er ved siden af ​​den første, består af de to på hinanden følgende byteplaceringer på $0210 og $0211. Det er den nederste byte her ($0210), der er skrevet i assemblersprogsprograminstruktionen. Hvis interesseadressen er $8765, er den nederste byte 65 H er på $0210 byte-placeringen og den højere byte på 87 H er på $0211 byte placering. Den tredje region består kun af en byte-placering. Det er på $8765-adressen for den målrettede byte (den ultimative byte af interesse). Parret af på hinanden følgende adresser, $0210 og $0211, har $8765 pointeren, som er interesseadressen. Efter computerfortolkningen er det $8765, der går ind i pc'en (Program Counter) for at få adgang til målbyten.

Nul side indirekte adressering
Denne adressering er den samme som den absolutte indirekte adressering, men markøren skal være på side nul. Den nedre byte-adresse for markørområdet er, hvad der er i den indtastede instruktion som følger:

JMP ($50)

Den højere byte af markøren er på $51 byte placeringen. Den effektive adresse (spids) behøver ikke at være på side nul.

Så med indeksadressering lægges værdien i et indeksregister til den basisadresse, der er givet i instruktionen om at have den effektive adresse. Indirekte adressering bruger en pointer.

4.8 Indekseret indirekte adressering

Absolut indekseret indirekte adressering
Denne adresseringstilstand bruges kun med JMP-instruktionen.
Ved absolut indirekte adressering er der den spidse værdi (byte) med sine egne to på hinanden følgende byte-adresser. Disse to på hinanden følgende adresser danner markøren til at være i pointerområdet af to på hinanden følgende bytes i hukommelsen. Den nederste byte af pointerområdet er det, der er skrevet i instruktionen i parentes. Markøren er adressen på den spidse værdi. I den tidligere situation er $8765 adressen på den spidse værdi. $0210 (efterfulgt af $0211) er adressen, hvis indhold er $8765, som er markøren. Med den absolutte indirekte adresseringstilstand er det ($0210), der skrives i programmet (tekstfil), inklusive parenteser.

På den anden side, med den absolut indekserede indirekte adresseringstilstand, dannes den nedre adressebyte for pointerregionen ved at tilføje værdien i X-registret til den indtastede adresse. For eksempel, hvis markøren er i adresseplaceringen på $0210, kan den indtastede instruktion være noget som denne:

JMP ($020A,X)

Hvor X-registret har værdien 6 H . 020A H + 6 H = 0210 H . Y-registret bruges ikke med denne adresseringstilstand.

Nul sideindekseret indirekte adressering
Denne adresseringstilstand bruger X-registret og ikke Y-registret. Med denne adresseringstilstand er der stadig den spidse værdi og markøren i dens to-byte adressemarkørregion. Der skal være to på hinanden følgende bytes på side nul for markøren. Adressen, der er indtastet i instruktionen, er en adresse på én byte. Denne værdi lægges til værdien i X-registret, og enhver carry kasseres. Resultatet peger på markørområdet på side 0. Hvis f.eks. interesseadressen (spids) er $8765, og den er i byteplaceringerne $50 og $51 på side 0, og værdien i X-registret er $30, den indtastede instruktion er sådan her:

LDA ($20,X)

Fordi $20 + $30 = $50.

Indirekte indekseret adressering
Denne adresseringstilstand bruger Y-registret og ikke X-registret. Med denne adresseringstilstand er der stadig den spidse værdi og pointerområdet, men indholdet af pointerområdet fungerer anderledes. Der skal være to på hinanden følgende bytes på side nul for markørområdet. Den nederste adresse på markørområdet er indtastet i instruktionen. Dette tal (bytepar), der er indeholdt i markørområdet, lægges til værdien i Y-registeret for at have den rigtige pointer. Lad f.eks. interesseadressen (peget) være $8765, værdien af ​​6H være i Y-registret, og tallet (to bytes) være på adressen 50 H og 51 H . De to bytes tilsammen er $875F siden $875F + $6 = $8765. Den maskinskrevne instruktion er sådan her:

LDA ($50), Y

4.9 Inkrement, formindsk og test-BIT-instruktioner

Følgende tabel viser betjeningen af ​​inkrement- og reduktionsinstruktionerne:

INA og DEA øger og formindsker henholdsvis akkumulatoren. Det kaldes akkumulatoradressering. INX, DEX, INY og DEY er for henholdsvis X- og Y-registrene. De tager ikke nogen operand. Så de bruger den underforståede adresseringstilstand. Increment betyder at tilføje 1 til registeret eller hukommelsesbyten. Reduktion betyder at trække 1 fra registeret eller hukommelsesbyten.

INC og DEC øger og formindsker henholdsvis en hukommelsesbyte (og ikke et register). Brug af nulsideadresseringen i stedet for den absolutte adressering er at spare på hukommelsen til instruktionen. Nulsideadressering er en byte mindre end den absolutte adressering for instruktionen i hukommelsen. Imidlertid påvirker nulsideadresseringstilstanden kun sidenul.

BIT-instruktionen tester bits af en byte i hukommelsen med de 8 bits i akkumulatoren, men ændrer ingen af ​​dem. Kun nogle flag i Processor Status Register 'P' er indstillet. Bittene i den specificerede hukommelsesplacering er logisk OG-forsynet med akkumulatorens. Derefter indstilles følgende statusbits:

  • N, som er bit 7 og den sidste bit (til venstre) af statusregistret, modtager bit 7 af hukommelsesplaceringen før AND-indstillingen.
  • V, som er bit 6 i statusregistret, modtager bit 6 af hukommelsesplaceringen før AND-indstillingen.
  • Z-flaget for statusregistret indstilles (gjort 1), hvis resultatet af AND er nul (00000000 2 ). Ellers ryddes den (gjort 0).

4.10 Sammenlign instruktioner

Sammenligningsinstruktionsmnemonikken for 6502 µP er CMP, CPX og CPY. Efter hver sammenligning påvirkes N-, Z- og C-flag i processorstatusregisteret 'P'. N-flaget er sat (gjort til 1), når resultatet er et negativt tal. Z-flaget er sat (gjort til 1), når resultatet er et nul (000000002). C-flaget er sat (gjort til 1), når der er en carry fra otte til niende bit. Følgende tabel giver en detaljeret illustration

Betyder 'større end'. Med det burde sammenligningstabellen være selvforklarende.

4.11 Hop- og greninstruktioner

Følgende tabel opsummerer hop- og greninstruktionerne:

JMP-instruktionen bruger den absolutte og indirekte adressering. Resten af ​​instruktionerne i tabellen er greninstruktioner. De bruger kun den relative adressering med 6502 µP. Dermed bliver tabellen selvforklarende, hvis den læses fra venstre mod højre og top til bund.

Bemærk, at grenene kun kan anvendes på adresser inden for -128 til +127 bytes fra den givne adresse. Dette er relativ adressering. For både JMP- og filialinstruktionerne er programtælleren (PC) direkte påvirket. 6502 µP tillader ikke grenene til en absolut adresse, selvom springet kan udføre den absolutte adressering. JMP-instruktionen er ikke en filialinstruktion.

Bemærk: Relativ adressering bruges kun med greninstruktioner.

4.12 Stableområdet

En subrutine er ligesom et af de tidligere korte programmer at tilføje to tal eller trække to tal fra. Stakområdet i hukommelsen starter fra $0100 til $01FF inklusive. Dette område kaldes simpelthen stakken. Når mikroprocessoren udfører et spring til subrutineinstruktionen (JSR – se den følgende diskussion), skal den vide, hvor den skal vende tilbage, når den er færdig. 6502 µP opbevarer denne information (returadresse) i lav hukommelse fra $0100 til $01FF (stakområdet) og bruger stakpointerregisterets indhold, som er 'S' i mikroprocessoren som en pointer (9 bit) til den sidst returnerede adresse der er gemt på side 1 ($0100 til $01FF) i hukommelsen. Stakken vokser ned fra $01FF og gør det muligt at indlejre underrutinerne op til 128 niveauer dybe.

En anden brug af stak-markøren er at håndtere interrupts. 6502 µP har stifterne mærket som IRQ og NMI. Det er muligt for nogle små elektriske signaler at blive påført disse ben og få 6502 µP til at holde op med at udføre et program og få det til at begynde at udføre et andet. I dette tilfælde afbrydes det første program. Ligesom underrutiner kan interrupt-kodesegmenterne indlejres. Afbrydelsesbehandling diskuteres i næste kapitel.

Bemærk : Stakmarkøren har 8 bits til den nederste byteadresse i adressering af lokationerne fra $0100 til $01FF. Den højere byte på 00000001 2 er antaget.

Følgende tabel giver instruktionerne, der relaterer stakmarkøren 'S' med A-, X-, Y- og P-registrene til stakområdet i hukommelsen:

4.13 Subrutine opkald og retur

En subrutine er et sæt instruktioner, der opnår et bestemt mål. Det forrige additions- eller subtraktionsprogram er en meget kort subrutine. Underrutiner kaldes nogle gange bare rutiner. Instruktionen til at kalde en underrutine er:

JSR : Hop til SubRoutine

Instruktionen for at vende tilbage fra en subrutine er:

RTS: Vend tilbage fra underrutine

Mikroprocessoren har en tendens til kontinuerligt at udføre instruktionerne i hukommelsen, den ene efter den anden. Antag, at mikroprocessoren i øjeblikket udfører et kodesegment, og den støder på en hop-instruktion (JMP) om at gå og udføre et kodesegment, som er kodet bagved, at det måske allerede er udført. Den udfører kodesegmentet bagved og fortsætter med at udføre alle kodesegmenterne (instruktionerne) efter kodesegmentet bagved, indtil det genudfører det aktuelle kodesegment igen og fortsætter nedenfor. JMP skubber ikke den næste instruktion til stakken.

I modsætning til JMP skubber JSR adressen på den næste instruktion efter sig selv fra pc'en (programtælleren) over på stakken. Stabelpositionen for denne adresse placeres i stakmarkøren 'S'. Når en RTS-instruktion stødes på (udføres) i underrutinen, trækker adressen, der skubbes på stakken, af stakken, og programmet genoptages på den aftrukne adresse, som er den næste instruktionsadresse lige før underrutinekaldet. Den sidste adresse, der fjernes fra stakken, sendes til programtælleren. Følgende tabel giver de tekniske detaljer for JSR- og RTS-instruktionerne:

Se følgende illustration for brugen af ​​JSR og RTS:

4.14 Eksempel på en nedtællingsløkke

Følgende underrutine tæller ned fra $FF til $00 (i alt 256 10 tæller):

start LDX #$FF ; indlæs X med $FF = 255
loop DEX ; X = X – 1
BNE loop ; hvis X ikke er nul, så gå til loop
RTS ; Vend tilbage

Hver linje har en kommentar. Kommentarer går aldrig ind i hukommelsen til udførelse. Samleren (oversætteren), der konverterer et program til det, det er i hukommelsen til udførelse (køring), fjerner altid kommentarerne. En kommentar begynder med ';' . 'Start' og 'loop' i dette program kaldes etiketter. En etiket identificerer (navnet) for instruktionens adresse. Hvis instruktionen er en enkelt byte-instruktion (underforstået adressering), er etiketten adressen på den instruktion. Hvis instruktionen er en multibyte-instruktion, identificerer etiketten den første byte for multibyte-instruktionen. Den første instruktion for dette program består af to bytes. Forudsat at den starter ved $0300-adressen, kan $0300-adressen erstattes med 'start' nede i programmet. Den anden instruktion (DEX) er en enkelt byte-instruktion og skal være på $0302-adressen. Det betyder, at $0302-adressen kan erstattes med 'loop', nede i programmet, hvilket faktisk er det i 'BNE loop'.

'BNE loop' betyder grenen til den givne adresse, når Z-flaget i statusregistret er 0. Når værdien i A- eller X- eller Y-registret er 00000000 2 , på grund af den sidste operation er Z-flaget 1 (sæt). Så mens det er 0 (ikke 1), gentages den anden og tredje instruktion i programmet i den rækkefølge. I hver gentaget sekvens reduceres værdien (hele tallet) i X-registret med 1. DEX betyder X = X – 1. Når værdien i X-registret er $00 = 00000000 2 , Z bliver 1. På det tidspunkt er der ikke flere gentagelser af de to instruktioner. Den sidste RTS-instruktion i programmet, som er en enkelt byte-instruktion (implicit adressering), vender tilbage fra subrutinen. Effekten af ​​denne instruktion er at lave programtælleradressen i stakken for den kode, der skal udføres før subrutinekaldet og gå tilbage til programtælleren (PC). Denne adresse er adressen på den instruktion, der skal udføres, før subrutinen kaldes.

Bemærk: Når du skriver et assemblersprogsprogram til 6502 µP, må kun en etiket starte i begyndelsen af ​​en linje; enhver anden linjekode skal flyttes mindst et mellemrum til højre.

Opkald til en underrutine
Ignorerer den hukommelsesplads, der optages af de tidligere etiketter, tager programmet 6 bytes på hinanden følgende placeringer i hukommelsen (RAM) fra $0300 til $0305. I dette tilfælde er programmet:

LDX #$FF ; indlæs X med $FF = 255
DEX ; X = X – 1
BNE $0302 ; hvis X ikke er nul, så gå til loop
RTS ; Vend tilbage

Startende fra $0200-adressen i hukommelsen kan opkaldet til subrutinen. Opkaldsinstruktionen er:

JSR start ; start er adresse $0300, dvs. JSR $0300

Underrutinen og dens opkald, der er korrekt skrevet i tekstredigeringsfilen, er:

start LDX #$FF; indlæs X med $FF = 255
loop DEX ; X = X – 1

BNE loop ; hvis X ikke er nul, så gå til loop
RTS ; Vend tilbage

JSR-start: hop til rutine, der starter ved $0300

Nu kan der være mange underrutiner i et langt program. Alle kan ikke have navnet 'start'. De skal have forskellige navne. Faktisk har ingen af ​​dem måske navnet 'start'. 'Start' bruges her af undervisningsmæssige årsager.

4.15 Oversættelse af et program

At oversætte et program eller samle det betyder det samme. Overvej følgende program:

start LDX #$FF : indlæs X med $FF = 255
loop DEX : X = X – 1
BNE loop: hvis X ikke er nul, så gå til loop
RTS: retur
JSR-start: hop til rutine, der starter ved $0300

Dette er det program, der tidligere er skrevet. Den består af subrutinen, start og opkaldet til subrutinen. Programmet tæller ned fra 255 10 til 0 10 . Programmet starter ved brugerens begyndelsesadresse på $0200 (RAM). Programmet skrives i en teksteditor og gemmes på disken. Den har et navn som 'sample.asm', hvor 'sample' er navnet på programmørens valg, men '.asm'-udvidelsen for assemblersproget skal være forbundet med filnavnet.

Det samlede program er produceret af et andet program, som kaldes en assembler. Monteringsenheden er leveret af producenten af ​​6502 µP eller af en tredjepart. Assembleren gengiver programmet på en sådan måde, at det er i hukommelsen (RAM), mens det udføres (køres).

Antag, at JSR-instruktionen begynder ved $0200-adressen, og subrutinen begynder ved $0300-adressen. Samleren fjerner alle kommentarer og hvide mellemrum. Kommentarerne og hvide mellemrum spilder hukommelsen, som altid er knap. En mulig tom linje mellem det forrige subrutinekodesegment og subrutineopkaldet er et eksempel på blanktegn. Den samlede fil er stadig gemt på disken, og den hedder noget i stil med 'sample.exe'. 'Samplen' er navnet på programmørens valg, men udvidelsen '.exe' skal være der for at angive, at det er en eksekverbar fil.

Det samlede program kan dokumenteres som følger:

Fremstilling af et dokument som dette siges at være at samle i hånden. Bemærk, at kommentarerne i dette dokument ikke vises i hukommelsen (til udførelse). Adressekolonnen i tabellen angiver startadresserne for instruktionerne i hukommelsen. Bemærk, at 'JSR start', dvs. 'JSR $0300', som forventes at blive kodet som '20 03 00', faktisk er kodet som '20 00 03', hvor den nederste hukommelsesbyteadresse tager den nederste byte i hukommelsen og højere hukommelsesbyteadresse tager den højere byte i hukommelsen – lille endianness. Opkoden for JSR er 20 16 .

Bemærk, at forskydningen til en greninstruktion, såsom BNE, er et to-komplementnummer i intervallet 128 10 til +127 10 . Så 'BNE loop' betyder 'BNE -1 10 ” som faktisk er “D0 FF” i kodeformen FF 16 er -1 i to’s komplement, som skrives som = 11111111 i grundtal to. Assembler-programmet erstatter etiketterne og felterne til faktiske hexadecimale tal (hexadecimale tal er binære tal, der er grupperet i fire bit). De faktiske adresser, hvor hver instruktion starter, er faktisk inkluderet.

Bemærk: 'JSR start'-instruktionen erstattes af kortere instruktioner, der sender det aktuelle indhold (høje og lave bytes) af programtælleren til stakken med stak-markøren, der dekrementeres to gange (én gang for høj byte og én gang for lav byte) og genindlæser derefter pc'en med $0300-adressen. Stakmarkøren peger nu på $00FD, forudsat at den er initialiseret til $01FF.

RTS-instruktionen erstattes også af et antal kortere instruktioner, som inkrementerer stakmarkøren 'S' to gange (én gang for lav byte og én gang for høj byte) og trækker de tilsvarende to bytes adresse fra stakmarkøren til pc'en for næste instruktion.

Bemærk: En etikettekst bør ikke have mere end 8 tegn.

'BNE loop' bruger den relative adressering. Det betyder at tilføje -3 10 til det næste programtællerindhold på $0305. Bytene for 'BNE loop' er 'D0 FD', hvor FD er de tos komplement af -3 10 .

Bemærk: Dette kapitel indeholder ikke alle instruktionerne for 6502 µP. Alle instruktionerne og deres detaljer kan findes i dokumentet med titlen 'SY6500 8-Bit Microprocessor Family'. Der er en PDF-fil med navnet '6502.pdf' til dette dokument, som er frit tilgængelig på internettet. De 6502 µP, der er beskrevet i dette dokument, er 65C02.

4.16 Afbryder

Signalerne fra enhver enhed, der er forbundet til de eksterne (lodrette overflade) porte på Commodore 64, skal passere gennem enten CIA 1- eller CIA 2-kredsløbene (IC'er), før de når 6502-mikroprocessoren. Signalerne fra databussen på 6502 µP skal passere enten gennem CIA 1- eller CIA 2-chippen, før de når nogen ekstern enhed. CIA står for Complex Interface Adapter. I Fig. 4.1 “Blokdiagram af Commodore_64-bundkortet”, repræsenterer blokinput/output-enhederne CIA 1 og CIA 2. Når et program kører, kan det afbrydes for at køre et andet stykke kode, før det fortsættes. Der er hardwareafbrydelse og softwareafbrydelse. Til hardwareafbrydelse er der to indgangssignalben til 6502 µP. Navnene på disse stifter er IRQ og NMI . Disse er ikke µP-datalinjer. Datalinjerne for µP er D7, D6, D5, D4, D3, D2, D1 og D0; med D0 for den mindst signifikante bit og D7 for den mest signifikante bit.

IRQ står for Interrupt ReQuest 'active' low. Denne indgangslinje til µP er normalt høj ved ca. 5 volt. Når det går ned til cirka 0 volt, er det en afbrydelsesanmodning, der signalerer µP. Så snart anmodningen er imødekommet, går linjen højt tilbage. At give afbrydelsesanmodningen betyder, at µP forgrener sig til koden (subrutinen), der håndterer afbrydelsen.

NMI står for Non-Maskable Interrupt 'active' low. Mens koden til IRQ bliver henrettet NMI kan gå lavt. I dette tilfælde, NMI håndteres (dets egen kode udføres). Derefter er koden til IRQ fortsætter. Efter koden til IRQ slutter, fortsætter hovedprogramkoden. Det er, NMI afbryder IRQ handler. Signalet for NMI kan stadig gives til µP, selv når µP er inaktiv og ikke håndterer noget eller ikke kører et hovedprogram.

Bemærk: Det er faktisk overgangen fra høj til lav, af NMI , det er NMI signal – mere om det senere. IRQ kommer normalt fra CIA 1 og NMI kommer normalt fra CIA 2. NMI , som står for Non-Maskable Interrupt, kan betragtes som non-stopable interrupt.

Håndtering af afbrydelser
Om anmodningen er fra IRQ eller NMI , skal den aktuelle instruktion fuldføres. 6502 har kun A-, X- og Y-registrene. Mens en underrutine kører, kan den bruge disse tre registre sammen. En interrupt-handler er stadig en subrutine, selvom den ikke ses som sådan. Efter den aktuelle instruktion er fuldført, gemmes indholdet af A-, X- og Y-registrene for 65C02 µP i stakken. Adressen på den næste instruktion af programtælleren sendes også til stakken. µP forgrener sig derefter til koden for afbrydelsen. Derefter gendannes indholdet af A-, X- og Y-registrene fra stakken i omvendt rækkefølge, som de sendes til.

Eksempel på kodning for en afbrydelse
For nemheds skyld antages, at rutinen for µP IRQ interrupt er bare at tilføje tallene $01 og $02 og gemme resultatet af $03 på hukommelsesadressen på $0400. Koden er:

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

ISR er en etiket og identificerer hukommelsesadressen, hvor PHA-instruktionen er. ISR betyder Interrupt Service Rutine. PHA, PHX og PHY sender indholdet af A-, X- og Y-registrene til stakken med håb om, at de bliver nødvendige af den kode (program), der kører lige før afbrydelsen. De næste tre instruktioner udgør kernen i interrupt-handleren. PLY-, PLX- og PLA-instruktionerne skal være i den rækkefølge, og de bringer indholdet af Y-, X- og A-registrene tilbage. Den sidste instruktion, som er RTI, (uden en operand) returnerer fortsættelsen af ​​eksekveringen til den kode (program), der udføres før afbrydelse. RTI trækker adressen på den næste instruktion af koden, der udføres, fra stakken tilbage til programtælleren. RTI betyder ReTurn from Interrupt. Dermed er afbrydelseshåndteringen (subrutinen) slut.

Softwareafbrydelse
Den vigtigste måde at få en softwareafbrydelse til 6502 µP på er ved brug af den underforståede BRK-adresseinstruktion. Antag, at hovedprogrammet kører, og det støder på BRK-instruktionen. Fra det tidspunkt skal adressen på den næste instruktion i pc'en sendes til stakken, efterhånden som den aktuelle instruktion er fuldført. En underrutine til at håndtere softwareinstruktionen skal kaldes 'næste'. Denne afbrydelsesunderrutine skal skubbe A-, X- og Y-registerindholdet til stakken. Efter at kernen af ​​subrutinen er udført, bør indholdet af A-, X- og Y-registrene trækkes tilbage fra stakken til deres registre af den fuldende subrutine. Det sidste udsagn i rutinen er RTI. Pc-indholdet trækkes også automatisk tilbage fra stakken til pc'en på grund af RTI.

Sammenligning og kontrast af underrutine og afbrydelsestjenesterutine
Følgende tabel sammenligner og kontrasterer underrutinen og afbrydelsestjenesterutinen:

4.17 Oversigt over 6502 hovedadresseringstilstande

Hver instruktion for 6502 er én byte efterfulgt af nul eller flere operander.

Øjeblikkelig adresseringstilstand
Med øjeblikkelig adresseringstilstand, efter operanden, er værdien og ikke en hukommelsesadresse. Værdien skal have # foran. Hvis værdien er i hexadecimal, skal '#' efterfølges af '$'. De umiddelbare adresseringsinstruktioner for 65C02 er: ADC, AND, BIT, CMP, CPX, CPY, EOR, LDA, LDX, LDY, ORA, SBC. Læseren bør konsultere dokumentationen for 65C02 µP for at vide, hvordan man bruger instruktionerne, der er angivet her, og som ikke er forklaret i dette kapitel. En eksempelinstruktion er:

LDA #$77

Absolut adresseringstilstand
I absolut adresseringstilstand er der én operand. Denne operand er adressen på værdien i hukommelsen (normalt i hexadecimal eller en etiket). Der er 64K 10 = 65.536 10 hukommelsesadresser for 6502 µP. Typisk er én-byte værdien på en af ​​disse adresser. De absolutte adresseringsinstruktioner for 65C02 er: 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. Læseren bør konsultere dokumentationen for 65C02 µP for at vide, hvordan man bruger instruktionerne, der er angivet her, såvel som for resten af ​​adresseringstilstandene, der ikke er forklaret i dette kapitel. En eksempelinstruktion er:

DE ER 1234 $

Underforstået adresseringstilstand
I implicit adresseringstilstand er der ingen operand. Ethvert involveret µP-register er underforstået af instruktionen. De underforståede adresseringsinstruktioner for 65C02 er: BRK, CLC, CLD, CLI, CLV, DEX, DEY, INX, INY, NOP, PHA, PHP, PHX, PHY, PLA, PLP, PLX, PLY, RTI, RTS, SEC , SED, SEI, TAX, TAY, TSX, TXA, TXS, TYA. En eksempelinstruktion er:

DEX : Formindsk X-registret med én enhed.

Relativ adresseringstilstand
Relativ adresseringstilstand omhandler kun greninstruktioner. I relativ adresseringstilstand er der kun én operand. Det er en værdi fra -128 10 til +127 10 . Denne værdi kaldes en offset. Baseret på tegnet tilføjes eller trækkes denne værdi fra den næste instruktion i programtælleren for at resultere i adressen på den tilsigtede næste instruktion. De relative adressetilstandsinstruktioner er: BCC, BCS, BEQ, BMI, BNE, BPL, BRA, BVC, BVS. Instruktionseksemplerne er:

BNE $7F : (gren hvis Z = 0 i statusregister, P)

Som tilføjer 127 til den aktuelle programtæller (adresse, der skal udføres) og begynder at udføre instruktionen på den adresse. Tilsvarende:

BEQ $F9 : (gren hvis Z = : i statusregister, P)

Som tilføjer en -7 til den aktuelle programtæller og starter udførelse på den nye programtælleradresse. Operanden er et to-komplementnummer.

Absolut indekseret adressering
Ved absolut indeksadressering føjes indholdet af X- eller Y-registret til den givne absolutte adresse (alt fra $0000 til $FFFF, dvs. fra 0 10 til 65536 10 ) for at have den rigtige adresse. Denne givne absolutte adresse kaldes basisadressen. Hvis X-registret bruges, er monteringsinstruktionen sådan her:

LDA $C453,X

Hvis Y-registret bruges, er det noget i retning af:

LDA $C453,Y

Værdien for X- eller Y-registret kaldes tælle- eller indeksværdien, og den kan være alt fra $00 (0 10 ) til $FF (250 10 ). Det kaldes ikke offset.

De absolutte indeksadresseringsinstruktioner er: ADC, AND, ASL (kun X), BIT (med akkumulator og hukommelse, kun med X), CMP, DEC (kun hukommelse og X), EOR, INC (kun hukommelse og X), LDA , LDX, LDY, LSR (kun X), ORA, ROL (kun X), ROR (kun X), SBC, STA, STZ (kun X).

Absolut indirekte adressering
Dette bruges kun sammen med springinstruktionen. Hermed har den givne absolutte adresse en pointeradresse. Pointeradressen består af to bytes. To-byte-markøren peger på (er adressen på) destinationsbyteværdien i hukommelsen. Så assemblersprogsinstruktionen er:

JMP ($3456)

Med parentes, og $13 er i adresseplaceringen $3456, mens $EB er i adresseplaceringen $3457 (= $3456 + 1). Derefter er destinationsadressen $13EB og $13EB er markøren. Den absolutte $3456 er i parentes i instruktionen, hvor 34 er den lavere byte og 56 er den højere byte.

4.18 Oprettelse af en streng med 6502 µP Assembly Language

Som vist i næste kapitel, efter at have oprettet en fil i hukommelsen, kan filen gemmes på disken. Filen skal have et navn. Navnet er et eksempel på en streng. Der er mange andre eksempler på strenge i programmering.

Der er to hovedmåder at oprette en streng af ASCII-koder på. På begge måder tager alle ASCII-koder (tegn) fortløbende byteplaceringer i hukommelsen. På en af ​​måderne er denne sekvens af bytes forudgået af en heltalsbyte, som er længden (antal tegn) i sekvensen (streng). På den anden måde bliver tegnsekvensen efterfulgt (umiddelbart efterfulgt) af Null-byten, som er 00 16 , dvs. $00. Længden af ​​strengen (antal tegn) er ikke angivet på denne anden måde. Null-tegnet bruges ikke på den første måde.

Overvej for eksempel 'Jeg elsker dig!' streng uden anførselstegn. Længden her er 11; et mellemrum tæller som én ASCII-byte (tegn). Antag, at strengen skal placeres i hukommelsen med det første tegn på adressen $0300.

Følgende tabel viser strenghukommelsesindstillingen, når den første byte er 11 10 = 0B 16 :

Følgende tabel viser strenghukommelsesindstillingen, når den første byte er 'I', og den sidste byte er Null ($00):

Følgende instruktion kan bruges til at begynde at oprette strengen:

De koster 0300 kr

Antag, at den første byte er i akkumulatoren, der skal sendes til adresseplaceringen $0300. Denne instruktion gælder for begge tilfælde (begge typer strenge).

Efter tilpasning af alle tegn i hukommelsescellerne, en efter en, kan strengen læses ved hjælp af en loop. For det første tilfælde aflæses antallet af tegn efter længden. For det andet tilfælde læses tegnene fra 'I', indtil null-tegnet, som er 'Null', er opfyldt.

4.19 Oprettelse af et array med 6502 µP Assembly Language

En matrix af enkeltbyte-heltal består af på hinanden følgende hukommelsesbyteplaceringer med heltal. Så er der en markør, der peger på placeringen af ​​det første heltal. Så en matrix af heltal består af to dele: markøren og rækken af ​​placeringer.

For en række strenge kan hver streng være et andet sted i hukommelsen. Derefter er der på hinanden følgende hukommelsesplaceringer med pointere, hvor hver pointer peger på den første placering af hver streng. En pointer består i dette tilfælde af to bytes. Hvis en streng begynder med sin længde, peger den tilsvarende markør på placeringen af ​​denne længde. Hvis en streng ikke begynder med sin længde, men ender med et nul-tegn, peger den tilsvarende markør på placeringen af ​​det første tegn i strengen. Og der er en pointer, der peger på den nederste byteadresse på den første pointer af på hinanden følgende pointere. Så et array af strenge består af tre dele: strengene på forskellige steder i hukommelsen, de tilsvarende på hinanden følgende pointere og pointeren til den første pointer af de på hinanden følgende pointere.

4.20 Problemer

Læseren rådes til at løse alle problemerne i et kapitel, før de går videre til næste kapitel.

  1. Skriv et assemblersprogsprogram, der starter ved $0200 for 6502 µP og tilføjer de usignerede numre af 2A94 H (tilføj) til 2ABF H (augend). Lad input og output være i hukommelsen. Fremstil også det samlede programdokument i hånden.
  2. Skriv et assemblersprogsprogram, der starter ved $0200 for 6502 µP og trækker de usignerede tal fra 1569 fra H (subtrahend) fra 2ABF H (minend). Lad input og output være i hukommelsen. Fremstil også det samlede programdokument i hånden.
  3. Skriv et assemblersprogsprogram til 6502 µP, der tæller op fra $00 til $09 ved hjælp af en loop. Programmet skulle starte ved $0200. Fremstil også det samlede programdokument i hånden.
  4. Skriv et assemblersprogsprogram, som starter ved $0200 for 6502 µP. Programmet har to underrutiner. Den første underrutine tilføjer de usignerede numre af 0203 H (augend) og 0102H (tilføjet). Den anden underrutine tilføjer summen fra den første underrutine, som er 0305H til 0006 H (augend). Det endelige resultat gemmes i hukommelsen. Kald den første underrutine, som er FSTSUB, og den anden underrutine, som er SECSUB. Lad input og output være i hukommelsen. Fremstil også det samlede programdokument for hele programmet i hånden.
  5. I betragtning af at en IRQ handler tilføjer $02 til $01 ved akkumulatoren som kernehåndtering mens NMI er udstedt og kernehåndteringen for NMI tilføjer $05 til $04 ved akkumulatoren, skriv et assemblersprog for begge handlere inklusive deres opkald. Opkaldet til IRQ handler skal være på adressen $0200. Det IRQ handler skal starte på adressen $0300. Det NMI handler skal starte på adressen $0400. Resultatet af IRQ handler skal placeres på adressen $0500, og resultatet af NMI handler skal placeres på adressen $0501.
  6. Forklar kort, hvordan BRK-instruktionen bruges til at producere softwareafbrydelsen i en 65C02-computer.
  7. Lav en tabel, der sammenligner og kontrasterer en normal underrutine med en afbrydelsesservicerutine.
  8. Forklar kort de vigtigste adresseringstilstande for 65C02 µP givet eksemplerne på assemblersproget.
  9. a) Skriv et 6502 maskinsprogsprogram for at sætte 'Jeg elsker dig!' streng af ASCII-koder i hukommelsen, begyndende fra $0300-adressen med længden af ​​strengen. Programmet skal starte på $0200-adressen. Få hver karakter fra akkumulatoren én efter én, forudsat at de er sendt dertil af en eller anden underrutine. Saml også programmet i hånden. (Hvis du har brug for at kende ASCII-koderne for 'Jeg elsker dig!'. Her er de: 'I':49 16 , plads: 20 16 , 'l': 6C 16 , 'o':6F 16 , 'i':76 16 , 'e':65, 'y':79 16 , 'i':75 16 , og ‘!’:21 16 (Bemærk: hver kode optager 1 byte).
    b) Skriv et 6502 maskinsprogsprogram for at sætte 'Jeg elsker dig!' streng af ASCII-koder i hukommelsen, begyndende fra $0300-adressen uden længden af ​​strengen, men slutter med 00 16 . Programmet skal starte på $0200-adressen. Få hver karakter fra akkumulatoren, forudsat at de sendes dertil, én efter én, af en eller anden underrutine. Saml også programmet i hånden.