Kapitel 4: Handledning för 6502 Microprocessor Assembly Language

Kapitel 4 Handledning For 6502 Microprocessor Assembly Language



Kapitel 4: Handledning för 6502 Microprocessor Assembly Language

4.1 Inledning

Mikroprocessorn 6502 släpptes 1975. Den användes som mikroprocessor för vissa persondatorer då som Apple II, Commodore 64 och BBC Micro.







Mikroprocessorn 6502 tillverkas fortfarande i stort antal idag. Det är inte längre en central enhet som används i persondatorer (bärbara datorer) idag, men den tillverkas fortfarande i stort antal och används i elektroniska och elektriska apparater idag. För att förstå de mer moderna datorarkitekturerna är det till stor hjälp att undersöka en äldre men ganska framgångsrik mikroprocessor som 6502.



Eftersom den är enkel att förstå och programmera är den en av de bästa (om inte den bästa) mikroprocessorn att använda för att lära ut assemblerspråk. Assembly language är ett lågnivåspråk som kan användas för att programmera en dator. Observera att assembleringsspråket för en mikroprocessor skiljer sig från assemblerspråket för en annan mikroprocessor. Sammanställningsspråket för 6502 mikroprocessorer lärs ut i det här kapitlet. Mer exakt är det 65C02 som lärs ut, men som helt enkelt kallas 6502.



En känd dator i det förflutna kallas commodore_64. 6502 är en mikroprocessor i 6500-familjen. Datorn commodore_64 använder mikroprocessorn 6510. Mikroprocessorn 6510 är av 6500 µP. Instruktionsuppsättningen för 6502 µP är nästan alla instruktioner för 6510 µP. Kunskapen om detta kapitel och nästa är baserad på datorn commodore_64. Denna kunskap används som grund för att förklara modern datorarkitektur och moderna operativsystem i denna del av onlinekarriärkursen.





Datorarkitektur hänvisar till komponenterna i datorns moderkort och en förklaring av hur data flödar inom varje komponent, särskilt mikroprocessorn, hur data flödar mellan komponenterna och även hur data interagerar. Singular för data är datum. Ett effektivt sätt att studera en dators datorarkitektur är att studera moderkortets assemblerspråk.

Datorn commodore_64 sägs vara en dator med 8-bitars datorord. Detta innebär att informationen lagras, överförs och manipuleras i form av åttabitars binära koder.



Blockdiagram av Commodore 64-moderkortet
Blockschemat för commodore 64 moderkortet är:


Fig 4.1 Blockdiagram för Commodore_64-systemenheten

Föreställ dig 6510-mikroprocessorn som 6502-mikroprocessorn. Det totala minnet är en serie byte (8-bitar per byte). Det finns ett slumpmässigt (läs/skriv)minne till vilket byte kan skrivas eller raderas. När strömmen till datorn stängs av raderas all information i RAM-minnet. Det finns också läsminnet (ROM). När strömmen till datorn stängs av finns informationen i ROM kvar (raderas inte).

Det finns ingångs-/utgångsporten (kretsen) som kallas ingångs-/utgångsenheterna i diagrammet. Denna port ska inte förväxlas med portarna som är synliga på vänster och höger eller fram och bak vertikala ytor på datorsystemenheten. Det är två olika saker. Anslutningarna från denna inre port till kringutrustning som hårddisken (eller disketten), tangentbordet och bildskärmen visas inte i diagrammet.

Det finns tre bussar (grupper av elektriska mycket små trådledare) i diagrammet. Varje tråd kan överföra en bit 1 eller bit 0. Databussen, för överföring av åtta-bitars byte åt gången (en klockpuls) till RAM-minnet och in-/utgångsporten (ingångs-/utgångsenheter) är dubbelriktad. Databussen är åtta bitar bred.

Alla komponenter är anslutna till adressbussen. Adressbussen är enkelriktad från mikroprocessorn. Det finns sexton ledare för adressbussen, och var och en bär en bit (1 eller 0). Sexton bitar skickas i en klockpuls.

Där finns kontrollbussen. Några av ledarna i styrbussen skulle överföra en bit vardera från mikroprocessorn till de andra komponenterna. Ett fåtal kontrolllinjer för bitarna från input/output (IO)-porten till mikroprocessorn.

Datorminne
RAM och ROM betraktas som en minnesenhet. Denna sammansättning representeras schematiskt enligt följande där hexadecimala tal har prefixet '$':


Fig 4.11 Minneslayout för Commodore 64-datorn

RAM-minnet är från 0000 16 till DFFF 16 som skrivs från $0000 till $DFFF. Med assemblerspråket 6502 µP har ett hexadecimalt tal prefixet '$' och inte suffixet (skrivet) med 16 eller H eller hex. All information i RAM-minnet försvinner när datorn stängs av. ROM börjar från $E000 till $FFFF. Den har subrutiner som inte slocknar när datorn stängs av. Dessa subrutiner är de vanligaste rutinerna som hjälper till vid programmering. Användarprogrammet anropar dem (se nästa kapitel).

Utrymmet (bytes) från $0200 till $D000 är för användarprogrammen. Utrymmet från $D000 till $DFFF är för information som är direkt relaterad till kringutrustningen (ingångs-/utgångsenheter). Detta är en del av operativsystemet. Så, operativsystemet för commodore-64-datorn består av två huvuddelar: delen i ROM som aldrig slocknar och delen från $D000 till $DFFF som stängs av när strömmen stängs av. Denna IO-data (ingång/utgång) måste laddas från en disk varje gång datorn slås på. Idag kallas sådana data perifera drivrutiner. Kringutrustningen börjar från Input/Output Device-porten genom anslutningarna på moderkortet till de identifierbara portarna på de vertikala ytorna på datorn som bildskärmen, tangentbordet etc. är ansluten till och till kringutrustningen (bildskärm, tangentbord, etc.) .).

Minnet består av 2 16 = 65 536 byteplatser. I hexadecimal form är dessa 10 000 16 = 10 000 H = 10 000 hex = $10 000 platser. Vid beräkning börjar räkna i bas två, bas tio, bas sexton, etc. från 0 och inte från 1. Så, den första platsen är faktiskt platsnumret 0000000000000000 2 = 0 10 = 0000 16 = 0 000 USD. I assemblerspråket 6502 µP har identifieringen av en adressplats prefixet $ och det finns inget suffix eller sänkning. Den sista platsen är platsnumret 1111111111111111 2 = 65,535 10 = FFFF 16 = $FFFF och inte 10000000000000000 2 eller 65,536 10 , eller 10 000 16 , eller 10 000 USD. 1000000000000000 2 65,536 10 , 10 000 16 , eller $10000 ger det totala antalet byteplatser.

Här, 2 16 = 65 536 = 64 x 1024 = 64 x 2 10 = 64 Kbyte (Kilobyte). Suffixet 64 i namnet Commodore-64 betyder 64KB totalt minne (RAM och ROM). En byte är 8 bitar, och de 8 bitarna kommer att hamna på en byteplats i minnet.

Minnet på 64 kbyte är uppdelat i sidor. Varje sida har 0100 16 = 256 10 byteplatser. De första 256 10 = första 0100 16 platser är sida 0. Den andra är sida 1, den tredje är sida 2, och så vidare.

För att adressera de 65 536 platserna krävs 16 bitar för varje plats (adress). Så, adressbussen från mikroprocessorn till minnet består av 16 linjer; en rad för en bit. En bit är antingen 1 eller 0.

6502 µP-registren
Ett register är som bytecellerna för en byte-minnesplats. 6502 µP har sex register: fem 8-bitars register och ett 16-bitars register. 16-bitarsregistret kallas Program Counter som förkortas PC. Den innehåller minnesadressen för nästa instruktion. Ett assemblerprogram består av instruktioner som placeras i minnet. Sexton (16) olika bitar behövs för att adressera en speciell byteplats i minnet. Vid en speciell klockpuls sänds dessa bitar till adressbussens 16-bitars adresslinjer för läsning av en instruktion. Alla register för 6502 µP är avbildade enligt följande:


Fig. 4.12 6502 µP register

Programräknaren eller PC:n kan ses som ett 16-bitars register i diagrammet. De lägre signifikanta åtta bitarna är märkta som PCL för Program Counter Low. De högre signifikanta åtta bitarna är märkta som PCH för Program Counter High. En instruktion i minnet för Commodore-64 kan bestå av en, två eller tre byte. De 16 bitarna i PC:n pekar på nästa instruktion som ska exekveras, i minnet. Bland kretsarna i mikroprocessorn kallas två av dem Arithmetic Logic Unit and Instruction Decoder. Om den aktuella instruktionen som bearbetas i µP (mikroprocessor) är en byte lång, ökar dessa två kretsar PC:n för nästa instruktion med 1 enhet. Om den aktuella instruktionen som bearbetas i µP är två byte lång, vilket betyder att den upptar två på varandra följande byte i minnet, ökar dessa två kretsar PC:n för nästa instruktion med 2 enheter. Om den aktuella instruktionen som bearbetas i µP är tre byte lång, vilket betyder att den upptar tre på varandra följande byte i minnet, ökar dessa två kretsar PC:n för nästa instruktion med 3 enheter.

Ackumulatorn 'A' är ett åtta-bitars generellt register som lagrar resultatet av de flesta aritmetiska och logiska operationer.

'X'- och 'Y'-registren används för att räkna programstegen. Räkningen i programmering börjar från 0. Så de kallas indexregister. De har några andra syften.

Även om Stack Pointer-registret har 'S' 9 bitar, vilket betraktas som ett åttabitarsregister. Dess innehåll pekar på en byteplats på sidan 1 i Random Access Memory (RAM). Sida 1 börjar från byte $0100 (256 10 ) till byte $01FF (511 10 ). När ett program körs flyttas det från en instruktion till nästa på varandra följande instruktion i minnet. Detta är dock inte alltid fallet. Det finns tillfällen då den hoppar från ett minnesområde till ett annat minnesområde för att fortsätta köra instruktionerna där i följd. Sida 1 i RAM används som stack. Stacken är ett stort RAM-minnesområde som har nästa adresser för fortsättningen av koden varifrån det finns ett hopp. Koderna med hoppinstruktioner finns inte i stacken; de finns någon annanstans i minnet. Men efter att hopp till-instruktionerna har utförts finns fortsättningsadresserna (inte kodsegment) i stacken. De knuffades dit som ett resultat av hopp- eller greninstruktionerna.

Åttabitars processorstatusregistret för P är en speciell typ av register. De enskilda bitarna är inte relaterade till eller kopplade till varandra. Varje bit där kallas en flagga och uppskattas oberoende av de andra. Flaggornas betydelser ges i det följande när behov uppstår.

Det första och sista bitindexet för varje register indikeras ovanför varje register i föregående diagram. Bitindex (positions)räkningen i ett register börjar från 0 till höger.

Minnessidor i binärt, hexadecimalt och decimalt
Följande tabell visar början av minnessidorna i binärt, hexadecimalt och decimalt:

Varje sida har 1 000 000 2 antal byte som är samma som 100 H antal byte som är samma som 256 10 antal byte. I det föregående minnesdiagrammet anges att sidorna går upp från sidan 0 och inte går ner som anges i tabellen.

De binära, hexadecimala och decimala kolumnerna i denna tabell ger minnesbytens platsadresser i sina olika baser. Observera att för sida noll är endast bitarna för den lägre byten nödvändiga för att skriva vid kodning. Bitarna för den högre byten kan utelämnas eftersom de alltid är nollor (för sida noll). För resten av sidorna ska bitarna för den högre byten användas.

Resten av detta kapitel förklarar 6502 µP Assembly Language med all tidigare information. För att snabbt förstå språket måste läsaren addera och subtrahera i bas sexton istället för bas tio. Det är egentligen tänkt att vara bas två, men att räkna i bas två är krångligt. Kom ihåg att när du lägger till två siffror i bas två, är ett bär fortfarande 1 som i bas tio. Men när man subtraherar två tal i bas två är ett lån två och inte tio som i bas tio. När man lägger till två siffror i bas sexton, är en bärare fortfarande 1 som i bas tio. Men när man subtraherar två tal i bas sexton, är ett lån sexton och inte tio som i bas tio.

4.2 Instruktioner för dataöverföring

Beakta följande tabell med instruktioner för överföring av assemblerspråk för 6502 µP:

När en byte (8-bitar) kopieras från en minnesbyteplats till ackumulatorregistret, X-registret eller Y-registret, laddas det. När en byte kopieras från något av dessa register till en minnesbyteplats, är det överföring. När en byte kopieras från ett register till ett annat överförs det fortfarande. I den andra kolumnen i tabellen visar pilen riktningen för kopian för en byte. Resten av de fyra kolumnerna visar olika adresseringslägen.

En post i kolumnen för adresseringsläge är den faktiska bytekoden för motsvarande mnemoniska del av instruktionen i hexadecimal form. AE, till exempel, är den faktiska bytekoden för LDX som ska ladda en byte från minnet till X-registret i absolut adresseringsläge som AE 16 = 10101110 2 . Så, bitarna för LDX i en minnesbyteplats är 10101110.

Lägg märke till att för LDX-mnemoniska delen av instruktionen finns det tre möjliga byte som är A2, AE och A6, och var och en är för ett speciellt adresseringsläge. När byten som laddas in i X-registret inte ska kopieras från en minnesbyteplats, måste värdet skrivas in med (strax efter) LDX-mnemoniken i instruktionen i hexadecimal eller decimal. I det här kapitlet är sådana värden skrivna med hexadecimal. Detta är omedelbar adressering, så den faktiska byten i minnet som representerar LDX är A2 16 = 10100010 2 och inte AE 16 vilket är lika med 10101110 2 .

I tabellen kallas alla byte under adresseringslägesrubrikerna Operation Codes som förkortas som opcodes. Det kan finnas mer än en op-kod för en mnemonic, beroende på adresseringsläget.

Notera: Ordet 'ladda' i datorsystemenheten kan ha två betydelser: det kan hänvisa till laddningen av en fil från en disk till datorns minne eller det kan hänvisa till överföringen av en byte från en minnesbyteplats till ett mikroprocessorregister .

Det finns fler adresseringslägen än de fyra i tabellen för 6502 µP.

Om inget annat anges börjar all användarprogrammeringskod i detta kapitel från adress 0200 16 vilket är början på användarområdet i minnet.

Minne M och ackumulator A

Minne till ackumulator

Omedelbar adressering
Följande instruktion lagrar numret FF 16 = 255 10 in i ackumulatorn:

LDA #$FF

'$' används inte bara för att identifiera en minnesadress. I allmänhet används det för att indikera att nästa nummer som följer är hexadecimalt. I det här fallet är $FF inte adressen till någon minnesbyteplats. Det är nummer 255 10 i hexadecimal. Basen 16 eller någon av dess andra likvärdiga prenumerationer får inte skrivas i assemblerspråksinstruktionen. '#' indikerar att det som följer härnäst är det värde som ska läggas in i ackumulatorregistret. Värdet kan också skrivas i bas tio, men det görs inte i det här kapitlet. '#' betyder omedelbar adressering.

En mnemonic har viss likhet med dess motsvarande engelska fras. 'LDA #$FF' betyder att ladda numret 255 10 in i ackumulatorn A. Eftersom detta är omedelbar adressering från föregående tabell är LDA A9 och inte AD eller A5. A9 i binär är 101010001. Så, om A9 för LDA är i $0200-adress i minnet, är $FF i $0301 = 0300 + 1 adress. #$FF är just operanden för LDA-mnemoniken.

Absolut adressering
Om värdet på $FF finns på $0333 plats i minnet, är den föregående instruktionen:

LDA $0333

Observera att # inte finns. I det här fallet betyder frånvaron av # att det som följer är en minnesadress och inte värdet av intresse (inte värdet som ska läggas in i ackumulatorn). Så op-koden för LDA, den här gången, är AD och inte A9 eller A5. Operaanden för LDA här är $0333-adressen och inte $FF-värdet. $FF är på $0333 plats som är ganska långt borta. 'LDA $0333'-instruktionen upptar tre på varandra följande platser i minnet, och inte två, som föregående illustration gjorde. 'AD' för LDA är på $0200-platsen. Den lägre byten av 0333 som är 33 är på $0301-platsen. Den högre byten på $0333 som är 03 är på $0302-platsen. Detta är lite endianness som används av assemblerspråket 6502. Sammansättningsspråken för olika mikroprocessorer är olika.

Detta är ett exempel på absolut adressering. $0333 är adressen till den plats som har $FF. Instruktionen består av tre på varandra följande byte och inkluderar inte $FF eller dess faktiska byteplats.

Zero-Page Addressing

Antag att $FF-värdet finns på $0050-minnesplatsen på sidan noll. Byteplatserna för nollsidan börjar från $0000 och slutar på $00FF. Dessa är 256 10 platser totalt. Varje sida i Commodore-64-minnet är 256 10 lång. Lägg märke till att den högre byten är noll för alla möjliga platser i nollsidorsutrymmet i minnet. Adresseringsläget med noll sidor är detsamma som det absoluta adresseringsläget, men den högre byten på 00 skrivs inte in i instruktionen. Så, för att ladda $FF från $0050-platsen till ackumulatorn, är instruktionen för nollsidors adresseringsläge:

LDA $50

Med LDA som A5 och inte A9 eller AD, A5 16 = 10100101 2 . Kom ihåg att varje byte i minnet består av 8 celler, och varje cell rymmer en bit. Instruktionen här består av två på varandra följande byte. A5 för LDA finns på $0200-minnesplatsen och $50-adressen, utan den högre byten 00, finns på $0301-platsen. Frånvaron av 00, som skulle ha förbrukat en byte i det totala 64K-minnet, sparar minnesutrymmet.

Ackumulator till minne

Absolut adressering
Följande instruktion kopierar ett bytevärde, vad det än är, från ackumulatorn till minnesplatsen på $1444:

DE ÄR $1444

Detta sägs överföras från ackumulatorn till minnet. Den laddas inte. Laddning är motsatsen. Opcode-byten för STA är 8D 16 = 10001101 2 . Denna instruktion består av tre på varandra följande byte i minnet. 8D 16 är på $0200 plats. Den 44 16 av $1444-adressen finns på $0201-platsen. Och 14 16 är på $0202 plats – lite endianness. Den faktiska byten som kopieras är inte en del av instruktionen. 8D och inte 85 för nollsidig adressering (i tabellen) används här för STA.

Noll sidadressering
Följande instruktion kopierar ett bytevärde, vad det än är, från ackumulatorn till minnesplatsen på $0050 på sidan noll:

STA $0050

Opcode-byten för STA här är 85 16 = 10000101 2 . Denna instruktion består av två på varandra följande byte i minnet. 85:an 16 är på plats $0200. De 50 16 av $0050-adressen finns på plats $0201. Frågan om endianness uppstår inte här eftersom adressen bara har en byte som är den lägre byten. Den faktiska byten som kopieras är inte en del av instruktionen. 85 och inte 8D för nollsidig adressering används här för STA.

Det är inte meningsfullt att använda den omedelbara adresseringen för att överföra en byte från ackumulatorn till en plats i minnet. Detta beror på att det faktiska värdet som $FF måste anges i instruktionen för omedelbar adressering. Så omedelbar adressering är inte möjlig för överföring av ett bytevärde från ett register i µP till någon minnesplats.

LDX, STX, LDY och STY Mnemonics
LDX och STX liknar LDA respektive STA. Men här används X-registret och inte A-registret (ackumulator). LDY och STY liknar LDA respektive STA. Men här används Y-registret och inte A-registret. Se Tabell 4.21 för varje op-kod i hexadecimal form som motsvarar ett visst minnesminne och ett särskilt adresseringsläge.

Registrera för att registrera överföringar
De två föregående uppsättningarna av instruktioner i Tabell 4.21 behandlar minne/mikroprocessor-registerkopiering (överföring) och register/registerkopiering (överföring). Instruktionerna TAX, TXA, TAY, TYA, TSX och TXS gör kopieringen (överföringen) från registret i mikroprocessorn till ett annat register i samma mikroprocessor.

För att kopiera byten från A till X är instruktionen:

BESKATTA

För att kopiera byten från X till A är instruktionen:

TX

För att kopiera byten från A till Y är instruktionen:

HAND

För att kopiera byten från Y till A är instruktionen:

TYA

För commodore 64-datorn är stacken sida 1 strax efter sida 0 i minnet. Liksom alla andra sidor består den av 25610 10 byteplatser, från $0100 till $01FF. Normalt exekverar ett program från en instruktion till nästa på varandra följande instruktion i minnet. Från tid till annan görs det ett hopp till ett annat minneskodsegment (uppsättning instruktioner). Stackområdet i minnet (RAM) har nästa instruktionsadresser från där hoppen (eller grenarna) slutade för programfortsättning.

Stackpekaren 'S' är ett 9-bitars register i 6502 µP. Den första biten (längst till vänster) är alltid 1. Alla byteplatsadresser på sida ett börjar med 1 följt av 8 olika bitar för de 256 10 platser. Stackpekaren har adressen till platsen på sidan 1 som har adressen till nästa instruktion som programmet måste återvända och fortsätta med efter exekvering av det aktuella (hoppade) kodsegmentet. Eftersom den första biten av alla adresser i stacken (sida ett) börjar med 1, behöver stackpekarregistret bara hålla de återstående åtta bitarna. När allt kommer omkring är dess första bit, som är biten längst till vänster (den nionde biten räknat från dess högra), alltid 1.

För att kopiera byten från S till X är instruktionen:

TSX

För att kopiera byten från X till S är instruktionen:

Text

Register-to-register-instruktionerna tar inte någon operand. De består bara av mnemonika. Varje minnesminne har sin opkod i hexadecimal form. Detta är i implicit adresseringsläge eftersom det inte finns någon operand (ingen minnesadress, inget värde).

Notera: Det finns ingen X till Y eller Y till X överföring (kopiering).

4.3 Aritmetiska operationer

Kretsen, Arithmetic Logic Unit i 6502 µP, kan bara lägga till två åttabitars nummer åt gången. Den subtraherar inte, den multiplicerar inte och den delar inte. Följande tabell visar opkoder och adresseringslägen för aritmetiska operationer:

Notera: Alla mnemonics för aritmetiska operationer och andra typer av operationer (dvs alla 6502 mnemonics) tar en byte av operationskod (op). Om det finns mer än en adresseringsmod för mnemoniken, skulle det finnas olika opkoder för samma mnemonik: en per adresseringsmod. C, D och V i tabellen är flaggorna för statusregistret. Deras betydelser kommer att ges senare när behovet uppstår.

Tillägg av osignerade nummer
Med 6502 µP är de signerade talen tvås komplementnummer. De osignerade talen är vanliga positiva tal som börjar från noll. Så för en byte på åtta bitar är det minsta talet utan tecken 00000000 2 = 0 10 = 00 16 och det största osignerade numret är 11111111 2 = 255 10 = FF 16 . För två osignerade nummer är tillägget:

A+M+C→A

Det betyder att ackumulatorns 8-bitars innehåll adderas av den aritmetiska logiska enheten till en byte (8-bitar) från minnet. Efter tillägget av A och M, går överföringen till den nionde biten till bärflaggcellen i statusregistret. Varje tidigare överföringsbit från en tidigare addition som fortfarande finns i bärflaggcellen i statusregistret läggs också till summan av A och M, vilket gör A+M+C→A. Resultatet sätts tillbaka i ackumulatorn.

Om tillägget av intresse är:

A + M

Och det finns inget behov av att lägga till någon tidigare bär, bärflaggan måste rensas som görs till 0, så att tillägget blir:

A+M+0→A samma som A+M→A

Notera: Om M läggs till A och en överföring av 1 inträffar eftersom resultatet är större än 255 10 = 11111111 2 = FF 16 , det här är en ny bärare. Denna nya överföring av 1 sänds automatiskt till överföringsflaggcellen i fall den behövs av nästa par med åtta bitar som ska summeras (en annan A + M).

Kod för att lägga till två osignerade åttabitar
00111111 2 +00010101 2 är samma som 3F 16 + 15 16 vilket är samma som 63 10 +21 10 . Resultatet är 010101002 2 vilket är samma som 54 16 och 84 10 . Resultatet är inte över det maximala antalet för åtta bitar som är 255 10 = 11111111 2 = FF 16 . Så, det finns ingen resulterande överföring av 1. För att uttrycka det på ett annat sätt, den resulterande överföringen är 0. Före tillägget finns det ingen tidigare överföring av 1. Med andra ord, den föregående överföringen är 0. Koden för att göra denna addition kan vara:

CLC
LDA #$3F
ADC #15 $

Notera: Medan du skriver assemblerspråket, trycks 'Enter'-tangenten på tangentbordet ned i slutet av varje instruktion. Det finns tre instruktioner i den här koden. Den första instruktionen (CLC) rensar bärflaggan om ett tidigare tillägg har 1. CLC kan endast göras i implicit adresseringsmod. Mnemoniken för implicit adresseringsläge tar ingen operand. Detta tömmer överföringscellen i statusregistret för P. Rensning betyder att biten 0 ges till överföringsflaggacellen. De följande två instruktionerna i koden använder det omedelbara adresseringsläget. Med omedelbar adressering finns det bara en operand för mnemoniken som är ett nummer (och varken ett minne eller registeradress). Därför måste numret föregås av '#'. '$' betyder att talet som följer är hexadecimalt.

Den andra instruktionen laddar numret 3F 16 in i ackumulatorn. För den tredje instruktionen tar den aritmetiska logiska enhetskretsen för µP den föregående (rensade) överföringen av 0 (tvingad till 0) av bärflaggacellen, av statusregistret och adderar den till 15 16 samt till värdet som redan finns i 3F 16 ackumulator och sätter tillbaka hela resultatet i ackumulatorn. I detta fall finns det en resulterande överföring av 0. ALU (Aritmetic Logic Unit) sänder (sätter) 0 in i bärflaggcellen i statusregistret. Processorstatusregistret och statusregistret betyder samma sak. Om en överföring av 1 resulterade, skickar ALU 1 till överföringsflaggan i statusregistret.

De tre raderna i föregående kod måste finnas i minnet innan de exekveras. Op-koden 1816 för CLC (implied addressing) är på $0200 byte-plats. Op-koden A9 16 för LDA (omedelbar adressering) är på $0201 byte plats. Siffran 3F 10 är på $0202 byte plats. Op-koden 69 16 för LDA (omedelbar adressering) är på $0203 byte plats. Siffran 15 10 är på $0204 byte plats.

Notera: LDA är en överföringsinstruktion (belastning) och inte en aritmetisk instruktion (mnemonik).

Kod för att lägga till två osignerade sexton-bitar
Alla register i 6502 µP är i huvudsak åtta-bitars register, förutom PC:n (Program Counter) som är 16-bitars. Till och med statusregistret är 8-bitars brett, även om dess åtta bitar inte fungerar tillsammans. I detta avsnitt beaktas tillägget av två 16 osignerade bitar, med en överföring från det första paret på åtta bitar till det andra paret på åtta bitar. Bären av intresse här är överföringen från den åttonde bitpositionen till den nionde bitpositionen.

Låt siffrorna vara 0010101010111111 2 = 2ABF16 16 = 10,943 10 och 0010101010010101 2 = 2A95 16 = 10 901 10 . Summan är 0101010101010100 2 = 5554 16 = 21,844 10 .

Att lägga till dessa två osignerade tal i bas två är som följer:

Följande tabell visar samma tillägg med överföring av 1 från den åttonde biten till den nionde bitpositionen, med början från höger:

Vid kodning av detta läggs de två lägre byten till först. Sedan sänder ALU (Aritmetic Logic Unit) överföringen av 1 från den åttonde bitpositionen till den nionde bitpositionen, till bärflaggcellen i statusregistret. Resultatet av 0 1 0 1 0 1 0 0 utan överföring går till ackumulatorn. Sedan läggs det andra paret byte till med bäraren. ADC-mnemoniken innebär att lägga till med föregående bär automatiskt. I det här fallet får den tidigare överföringen, som är 1, inte ändras före den andra tillägget. För det första tillägget, eftersom alla tidigare överföringar inte är en del av detta kompletta tillägg, måste det rensas (görs till 0).

För den fullständiga tillägget av de två paren av byte är det första tillägget:

A + M + 0 -> A

Det andra tillägget är:

A + M + 1 -> A

Så bärflaggan måste rensas (givet värde på 0) precis före det första tillägget. Följande program som läsaren måste läsa förklaringen som följer använder det absoluta adresseringsläget för denna summering:

CLC
LDA $0213
ADC $0215
; ingen clearing eftersom bärflaggavärdet behövs
STA $0217
LDA $0214
ADC $0216
STA $0218

Observera att med 6502 assemblerspråk börjar ett semikolon en kommentar. Detta innebär att i körningen av programmet ignoreras semikolon och allt till höger om det. Programmet som tidigare skrivits finns i en textfil som sparas med namnet på programmerarens val och med tillägget '.asm'. Det föregående programmet är inte det exakta programmet som går till minnet för exekvering. Motsvarande program i minnet kallas det översatta programmet där mnemonics ersätts med opkoderna (bytes). Alla kommentarer finns kvar i assemblerspråkets textfil och tas bort innan det översatta programmet når minnet. Faktum är att det finns två filer som sparas på disken idag: '.asm'-filen och '.exe'-filen. '.asm'-filen är den i föregående illustration. '.exe'-filen är '.asm'-filen med alla kommentarer borttagna och alla minnesminnen ersatta av deras opkoder. När den öppnas i en textredigerare är '.exe'-filen oigenkännlig. Om inget annat anges, för detta kapitel, kopieras '.exe'-filen till minnet med början från $0200-platsen. Detta är den andra betydelsen av lastning.

De två 16-bitarstalen som ska läggas till upptar fyra byte i minnet för absolut adressering: två byte per nummer (minnet är en sekvens av byte). Med absolut adressering finns operanden till opkoden i minnet. Det summerande resultatet är två byte brett och måste också placeras i minnet. Detta ger totalt 6 10 = 6 16 byte för ingångar och utdata. Ingångarna kommer inte från tangentbordet och utdata kommer inte från monitorn eller skrivaren. Ingångarna finns i minnet (RAM) och utgången (summeringsresultat) går tillbaka till minnet (RAM) i denna situation.

Innan ett program körs måste den översatta versionen finnas i minnet först. Om man tittar på föregående programkod kan man se att instruktionerna utan kommentaren utgör 19 10 = 13 16 bytes. Så, programmet tar från $0200 byte plats i minnet till $0200 + $13 – $1 = $0212 byte platser (med början från $0200 och inte $0201 vilket innebär – $1). Att lägga till de 6 byten för ingångs- och utmatningsnumren gör att hela programmet slutar på $0212 + $6 = $0218. Den totala längden på programmet är 19 16 = 25 10 .

Den lägre byten av augend bör vara i $0213-adressen, och den högre byten av samma augend bör vara i $0214-adressen – little endianness. På samma sätt bör den lägre byten för tillägget vara i $0215-adressen, och den högre byten för samma tillägg bör vara i $0216-adressen – little endianness. Den lägre byten av resultatet (summan) bör vara i $0217-adressen, och den högre byten av samma resultat bör vara i $0218-adressen – little endianness.

Op-koden 18 16 för CLC (implied addressing) är på byteplatsen $0200. Op-koden för 'LDA $0213', dvs AD 16 för LDA (absolut adressering), är på byteplatsen $0201. Den nedre byten av augend, som är 10111111, finns i minnesbyteplatsen för $0213. Kom ihåg att varje opkod upptar en byte. '$0213'-adressen för 'LDA $0213' är på byteplatserna $0202 och $0203. 'LDA $0213'-instruktionen laddar den nedre byten av augend till ackumulatorn.

Op-koden för 'ADC $0215', dvs 6D 16 för ADC (absolut adressering), är på byteplatsen $0204. Den nedre byten för tillägget som är 10010101 är på byteplatsen $0215. '$0215'-adressen för 'ADC $0215' är på byteplatserna $0205 och $0206. 'ADC $0215'-instruktionen lägger till den nedre byten av tillägget till den nedre byten för den augend som redan finns i ackumulatorn. Resultatet placeras tillbaka i ackumulatorn. Varje överföring efter den åttonde biten sänds till överföringsflaggan i statusregistret. Bärflaggacellen får inte rensas före den andra tillägget av de högre byten. Denna överföring läggs automatiskt till summan av de högre byten. Faktum är att en överföring på 0 läggs till summan av de lägre byten automatiskt i början (motsvarande att ingen överföring läggs till) på grund av CLC.

Kommentaren tar nästa 48 10 = 30 16 bytes. Detta finns dock bara kvar i textfilen '.asm'. Den når inte minnet. Det tas bort av översättningen som görs av assemblern (ett program).

För nästa instruktion som är 'STA $0217', op-koden för STA som är 8D 16 (absolut adressering) är på byteplatsen $0207. '$0217'-adressen för 'STA $0217' finns i minnesplatserna $0208 och $0209. 'STA $0217'-instruktionen kopierar ackumulatorns åttabitars innehåll till minnesplatsen $0217.

Den högre byten av augend som är 00101010 är i minnesplatsen $0214, och den högre byten för tillägget som är 00101010 är i byteplatsen $02 16 . Op-koden för 'LDA $0214' som är AD16 för LDA (absolut adressering) är på byteplatsen $020A. '$0214'-adressen för 'LDA $0214' är på platserna $020B och $020C. 'LDA $0214'-instruktionen laddar den högre byten av augend till ackumulatorn och raderar allt som finns i ackumulatorn.

Op-koden för 'ADC $0216' som är 6D 16 för ADC (absolut adressering) är på byteplatsen $020D. '$0216'-adressen för 'ADC 0216' är på byteplatserna $020E och $020F. 'ADC $0216'-instruktionen lägger till den högre byten av addend till den högre byten av augend som redan finns i ackumulatorn. Resultatet placeras tillbaka i ackumulatorn. Om det finns en överföring av 1, för detta andra tillägg, placeras den automatiskt i överföringscellen i statusregistret. Även om överföringen bortom den sextonde biten (vänster) inte krävs för detta problem, är det trevligt att kontrollera om en överföring av 1 inträffade genom att kontrollera om bärflaggan blev 1.

För nästa och sista instruktion som är 'STA $0218', är opkoden för STA som är 8D16 (absolut adressering) på byteplatsen $0210. '$0218'-adressen för 'STA $0218' finns i minnesplatserna $0211 och $0212. 'STA $0218'-instruktionen kopierar ackumulatorns åttabitars innehåll till minnesplatsen $0218. Resultatet av tillägget av de två sextonbitarstalen är 0101010101010100, med den lägre byten på 01010100 i minnesplatsen $0217 och den högre byten på 01010101 i minnesplatsen $0218 - liten endianness.

Subtraktion
Med 6502 µP är de signerade talen tvås komplementnummer. En tvås komplementnummer kan vara åtta-bitar, sexton bitar eller valfri multipel av åtta bitar. Med tvåkomplement är den första biten från vänster teckenbiten. För ett positivt tal är denna första bit 0 för att indikera tecknet. Resten av bitarna bildar numret på normalt sätt. För att erhålla de tvås komplement av ett negativt tal, invertera alla bitar för motsvarande positiva tal och lägg sedan till 1 till resultatet från den högra änden.

För att subtrahera ett positivt tal från ett annat positivt tal omvandlas subtrahenden till ett negativt två-komplement. Sedan läggs minuend och det nya negativa talet till på vanligt sätt. Så, åtta-bitars subtraktion blir:

Där överföringen antas som 1. Resultatet i ackumulatorn är skillnaden i tvås komplement. Så för att subtrahera två tal måste bärflaggan ställas in (gjort till 1).

När man subtraherar två sextonbitars tal, görs subtraktionen två gånger som med tillägg av två sextonbitarsnummer. Eftersom subtraktion är en form av addition med 6502 µP, ställs bärflaggan endast in en gång för den första subtraktionen när man subtraherar två sextonbitars tal. För den andra subtraktionen görs varje inställning av bärflaggan automatiskt.

Programmering av subtraktionen för åttabitars tal eller sextonbitarsnummer görs på samma sätt som att programmera additionen. Bärflaggan måste dock ställas in redan i början. Mnemoniken för att göra detta är:

Subtraktion med sexton-bitars positiva tal
Tänk på subtraktionen med följande tal:

Denna subtraktion involverar inte tvås komplement. Eftersom subtraktionen i 6502 µP görs i tvås komplement, görs subtraktionen i bas två enligt följande:

De tvås komplementresultat är detsamma som resultatet som erhålls från den vanliga subtraktionen. Observera dock att 1:an som går till den sjuttonde bitpositionen från höger ignoreras. Minuend och subtrahend delas upp i två åttondelsbitar vardera. De tvås komplement av 10010110 av subtrahendens lägre byte bestäms oberoende av dess högre byte och eventuell bärighet. De tvås komplement av 11101011 av subtrahendens högre byte bestäms oberoende av dess lägre byte och eventuell bärighet.

Minuendens 16 bitar är redan i tvås komplement, med början med 0 från vänster. Så den behöver ingen justering i bitar. Med 6502 µP läggs den nedre byten av minuend utan någon modifiering till den nedre byten av de tvås komplement av subtrahenden. Minuendens nedre byte konverteras inte till tvåskomplement eftersom de sexton bitarna i hela minuänden redan måste vara i tvåskomplement (med en 0 som första bit till vänster). I detta första tillägg läggs en obligatorisk överföring av 1 till på grund av 1=0 SEC-instruktionen.

I den aktuella effektiva subtraktionen finns en överföring av 1 (av addition) från den åttonde biten till den nionde biten (från höger). Eftersom detta i praktiken är subtraktion, kompletteras (inverteras) vilken bit som helst som antas vara i bärflaggan i statusregistret. Så bärandet av 1 blir 0 i C-flaggan. I den andra operationen läggs den högre byten av minuend till de högre tvås komplementbyte för subtrahenden. Den automatiskt kompletterade bärflaggbiten i statusregistret (i detta fall är 0) läggs också till (till de högre byten). Varje 1 som går bortom den sextonde biten från höger ignoreras.

Nästa sak är bara att koda allt det schemat enligt följande:

SEC
LDA $0213
SBC $0215
; ingen clearing eftersom det inverterade bärflagganvärdet behövs
STA $0217
LDA $0214
SBC $0216
STA $0218

Kom ihåg att med assemblerspråket 6502 börjar ett semikolon en kommentar som inte ingår i den översatta programversionen i minnet. De två 16-bitarstalen för subtraktion upptar fyra byte minne med absolut adressering; två per nummer (minnet är en serie byte). Dessa ingångar kommer inte från tangentbordet. Det summerande resultatet är två byte och måste också placeras i minnet på en annan plats. Denna utdata går inte till bildskärmen eller skrivaren; det går till minnet. Detta ger totalt 6 10 = 6 16 byte för ingångar och utdata som ska placeras i minnet (RAM).

Innan ett program körs måste det finnas i minnet först. Om man tittar på programkoden kan man se att instruktionerna utan kommentaren utgör 19 10 = 13 16 bytes. Eftersom alla program i det här kapitlet börjar från minnesplatsen $0200, tar programmet från $0200 byteplatsen i minnet till $0200 + $13 – $1 = $0212 byteplatsen (med början från $0200 och inte $0201). Detta intervall inkluderar inte regionen för ingångs- och utdatabyte. De två ingångsnumren tar 4 byte och det ena utgångsnumret tar 2 byte. Genom att lägga till de 6 byten för ingångs- och utmatningsnumren blir intervallet för programmet som slutar på $0212 + $6 = $0218. Den totala längden på programmet är 19 16 = 25 10 .

Minuendens lägre byte ska finnas i $0213-adressen, och den högre byten av samma minuend ska finnas i $0214-adressen – little endianness. På samma sätt bör den lägre byten av subtrahenden vara i $0215-adressen, och den högre byten av samma subtrahend bör vara i $0216-adressen – little endianness. Den lägre byten av resultatet (skillnaden) bör vara i $0217-adressen, och den högre byten av samma resultat bör vara i $0218-adressen – little endianness.

Op-koden för 38 16 för SEC (implied addressing) finns i $0200-adressen. Alla program i detta kapitel antas starta vid minnesplatsen $0200, vilket annullerar alla program som skulle ha varit där; om inte annat anges. Op-koden för 'LDA $0213', dvs AD 16 , för LDA (absolut adressering) är på $0201 byte-platsen. Minuändens nedre byte, som är 10111111, finns i minnesbyteplatsen $0213. Kom ihåg att varje opkod upptar en byte. '$0213'-adressen för 'LDA $0213' är på byteplatserna $0202 och $0203. 'LDA $0213'-instruktionen laddar den nedre byten av minuend till ackumulatorn.

Op-koden för 'SBC $0215', dvs ED 16 , för SBC (absolut adressering) är på $0204 byte-platsen. Den nedre byten av subtrahenden som är 01101010 är på $0215 byteplatsen. '$0215'-adressen för 'ADC $0215' är på byteplatserna $0205 och $0206. 'SBC $0215'-instruktionen subtraherar den nedre byten av subtrahenden från den lägre byten på minuend som redan finns i ackumulatorn. Detta är tvås komplementsubtraktion. Resultatet placeras tillbaka i ackumulatorn. Komplementet (inversionen) av varje överföring efter den åttonde biten sänds till överföringsflaggan i statusregistret. Denna bärflagga får inte rensas före den andra subtraktionen med de högre byten. Denna överföring läggs till subtraktionen av de högre byten automatiskt.

Kommentaren tar nästa 57 10 = 3916 16 bytes. Detta finns dock bara kvar i textfilen '.asm'. Den når inte minnet. Det tas bort av översättningen som görs av assemblern (ett program).

För nästa instruktion som är 'STA $0217', op-koden för STA, dvs. 8D 16 (absolut adressering), är på $0207 byte-platsen. '$0217'-adressen för 'STA $0217' finns i minnesplatserna $0208 och $0209. 'STA $0217'-instruktionen kopierar ackumulatorns åttabitars innehåll till minnesplatsen $0217.

Den högre byten av minuend som är 00101010 är i minnesplatsen $0214, och den högre byten av subtrahenden som är 00010101 är i byteplatsen $0216. Op-koden för 'LDA $0214', dvs AD 16 för LDA (absolut adressering), är på $020A byte-platsen. '$0214'-adressen för 'LDA $0214' är på platserna $020B och $020C. 'LDA $0214'-instruktionen laddar den högre byten av minuend till ackumulatorn och raderar allt som finns i ackumulatorn.

Op-koden för 'SBC $0216', dvs ED 16 för SBC (absolut adressering), är på $020D byte-platsen. '$0216'-adressen för 'SBC $0216' är på byteplatserna $020E och $020F. 'SBC $0216'-instruktionen subtraherar den högre byten av subtrahenden från den högre byten av minuend (två-komplement) som redan finns i ackumulatorn. Resultatet placeras tillbaka i ackumulatorn. Om det finns en bärighet på 1 för denna andra subtraktion, placeras dess komplement automatiskt i statusregistrets bärcell. Även om överföringen bortom den sextonde biten (vänster) inte krävs för detta problem, är det trevligt att kontrollera om komplementöverföringen inträffar genom att kontrollera bärflaggan.

För nästa och sista instruktion som är 'STA $0218', op-koden för STA, dvs. 8D 16 (absolut adressering), är på $0210 byte-platsen. '$0218'-adressen för 'STA $0218' finns i minnesplatserna $0211 och $0212. 'STA $0218'-instruktionen kopierar ackumulatorns åttabitars innehåll till minnesplatsen $0218. Resultatet av subtraktionen med de två sextonbitarstalen är 0001010101010101 med den nedre byten 01010101 i minnesplatsen $0217 och den högre byten på 00010101 i minnesplatsen $0218 - liten endianness.

6502 µP har enbart kretsar för addition och indirekt för de tvås komplementsubtraktion. Den har inga kretsar för multiplikation och division. För att göra multiplikationen och divisionen bör ett assemblerprogram med detaljer, inklusive förskjutning av delprodukter och delutdelning, skrivas.

4.4 Logiska operationer

I 6502 µP är mnemoniken för OR ORA och mnemoniken för exklusiv OR är EOR. Observera att de logiska operationerna inte har den underförstådda adresseringen. Den underförstådda adresseringen tar ingen operand. Var och en av de logiska operatorerna måste ta två operander. Den första finns i ackumulatorn och den andra finns i minnet eller i instruktionen. Resultatet (8-bitar) är tillbaka i ackumulatorn. Den första i ackumulatorn läggs antingen dit genom en omedelbar instruktion eller kopieras från minnet med absolut adressering. I det här avsnittet används endast nollsidig adressering som illustration. Dessa logiska operatorer är alla Bitwise-operatorer.

OCH
Följande tabell illustrerar bitvis OCH i binär, hexadecimal och decimal:

Alla program i det här kapitlet bör starta på minnesbyteplatsen $0200. Programmen i detta avsnitt är dock på sidan noll, med syftet att illustrera användningen av sidan noll utan den högre byten på 00000000 2 . Den tidigare AND-ningen kan kodas enligt följande:

LDA #$9A ; inte från minnet – omedelbar adressering
OCH #$CD ; inte från minnet – omedelbar adressering
STA $30 ; lagrar $88 till nollbaserade $0030

ELLER
Följande tabell illustrerar bitvis ELLER i binär, hexadecimal och decimal:

LDA #$9A ; inte från minnet – omedelbar adressering
ORA #$CD ; inte från minnet – omedelbar adressering
STA $30 ; lagrar $CF till nollbaserade $0030

FRI
Följande tabell illustrerar Bitwise XOR i binär, hexadecimal och decimal:

LDA #$9A ; inte från minnet – omedelbar adressering
EOR #$CD ; inte från minnet – omedelbar adressering
STA $30 ; lagrar $57 till nollbaserade $0030

4.5 Skift- och rotationsoperationer

Mnemoniken och opkoderna för skift- och rotationsoperatorerna är:

ASL: Flytta vänster en bit av ackumulatorn eller minnesplatsen, infoga 0 i den lediga cellen längst till höger.

LSR: Flytta åt höger en bit av ackumulatorn eller minnesplatsen, infoga 0 i den lediga cellen längst till vänster.
ROL: Rotera en bit till vänster om ackumulatorn eller minnesplatsen och sätt in den bit som tappas ut till vänster i den lediga cellen längst till höger.
ROR: Rotera en bit till höger om ackumulatorn eller minnesplatsen och sätt in den bit som tappas ut till höger i den lediga cellen längst till vänster.

För att göra en växling eller rotation med ackumulatorn är instruktionen ungefär så här:

LSR A

Detta använder ett annat adresseringsläge som kallas ackumulatoradresseringsläget.

För att göra en växling eller rotation med en byte-minnesplats är instruktionen ungefär så här:

ROR $2BCD

Där 2BCD är minnesplatsen.

Observera att det inte finns något omedelbart eller underförstått adresseringsläge för att växla eller rotera. Det finns inget omedelbart adresseringsläge eftersom det inte är någon idé att flytta eller rotera ett nummer som bara finns kvar i instruktionen. Det finns inget underförstått adresseringsläge eftersom konstruktörerna av 6502 µP vill att endast innehållet i ackumulatorn (A-registret) eller en minnesbyteplats ska flyttas eller roteras.

4.6 Relativt adresseringsläge

Mikroprocessorn ökar alltid (med 1, 2 eller 3 enheter) programräknaren (PC) för att peka på nästa instruktion som ska exekveras. 6502 µP har en instruktion vars minnesminne är BVS vilket betyder Branch on Overflow Set. Datorn består av två byte. Denna instruktion får PC:n att ha en annan minnesadress för att nästa instruktion ska exekveras som inte är ett resultat av ett normalt inkrement. Det gör det genom att lägga till eller subtrahera ett värde, kallat en offset, till innehållet på datorn. Och så pekar datorn sedan på en annan (förgrenad) minnesplats för datorn att fortsätta köra därifrån. Offseten är ett heltal från -128 10 till +127 10 (tvåkomplement). Så, offset kan få hoppet att gå vidare i minnet. Om det är positivt eller bakom i minnet, eller om det är negativt.

BVS-instruktionen tar bara en operand som är offset. BVS använder den relativa adresseringen. Tänk på följande instruktion:

BVS $7F

I bas två, 7F H är 01111111 2 = 127 10 . Antag att innehållet i datorn för nästa instruktion är $0300. BVS-instruktionen gör att $7F (ett positivt tal redan i tvås komplement) läggs till $0300 för att ge $037F. Så istället för nästa instruktion som ska köras på minnesplatsen $0300, är ​​den på minnesplatsen $037F (ungefär en halv sidskillnad).

Det finns andra greninstruktioner, men BVS är mycket bra att använda för att illustrera den relativa adresseringen. Relativ adressering handlar om greninstruktioner.

4.7 Indexerad adressering och indirekt adressering separat

Dessa adresseringslägen gör det möjligt för 6502 µP att hantera de enorma mängderna data på korta tidsperioder med minskat antal instruktioner. Det finns 64KB platser för hela Comodore-64-minnet. Så för att komma åt valfri byteplats, på 16 bitar, behövs två byte. Det enda undantaget från behovet av två byte är för sida noll där den högre byten på $00 utelämnas för att spara på utrymmet som tas upp av instruktionen i minnet. Med ett adresseringsläge som inte är sida-noll, indikeras oftast både de högre och lägre byten av 16-bitars minnesadressen på något sätt.

Grundläggande indexerad adressering

Absolut indexadressering
Kom ihåg att X- eller Y-registret kallas indexregistret. Tänk på följande instruktion:

LDA $C453,X

Antag att värdet på 6 H finns i X-registret. Observera att 6 inte skrivs någonstans i instruktionen. Denna instruktion lägger till värdet 6H till C453 H som är en del av den maskinskrivna instruktionen i textfilen som fortfarande ska monteras – C453 H + 6 H = C459 H . LDA betyder att ladda en byte till ackumulatorn. Byten som ska laddas i ackumulatorn kommer från $C459-adressen. $C459 som är summan av $C453 som skrivs med instruktionen och 6 H som finns i X-registret blir den effektiva adressen från vilken byten som ska laddas in i ackumulatorn kommer. Om 6 H fanns i Y-registret, skrivs Y i stället för X i instruktionen.

I den inskrivna instruktionssatsen är $C453 känd som basadressen och 6:an H i X- eller Y-registret kallas räkne- eller indexdelen för den effektiva adressen. Basadressen kan referera till vilken byteadress som helst i minnet och nästa 256 10 adresser kan nås, förutsatt att det startade indexet (eller antalet) i X- eller Y-registret är 0. Kom ihåg att en byte kan ge ett kontinuerligt intervall på upp till 256 10 siffror (dvs. 00000000 2 till 11111111 2 ).

Så, den absoluta adresseringen lägger till det som redan finns (har lagts av en annan instruktion) i X- eller Y-registret till de 16 adresserna som skrivs in med instruktionen för att erhålla den effektiva adressen. I den inskrivna instruktionen särskiljs de två indexregistren av X eller Y som skrivs efter ett kommatecken. Antingen X eller Y skrivs; inte båda.

När allt har skrivits in i en textredigerare och sparas med filnamnstillägget '.asm', måste assemblern, som är ett annat program, översätta det maskinskrivna programmet till det som finns (laddat) i minnet. Den tidigare instruktionen, som är 'LDA $C453,X', upptar tre byteplatser i minnet och inte fem.

Kom ihåg att ett minnesminne som LDA kan ha mer än en opcode (olika byte). Opkoden för instruktionen som använder X-registret skiljer sig från opkoden som använder Y-registret. Montören vet vilken opcode som ska användas baserat på den inskrivna instruktionen. Enbyte-opkoden för 'LDA $C453,X' skiljer sig från enbyte-opkoden för 'LDA $C453,Y'. Faktum är att opkoden för LDA i 'LDA $C453,X' är BD, och opkoden för LDA i 'LDA $C453,9' är BD.

Om op-koden för LDA är på $0200 byte-platsen. Sedan tar 16-bitarsadressen för $C453 nästa byteplatser i minnet som är $0201 och $0202. Den speciella opcode-byten indikerar om det är X-registret eller Y-registret som är involverat. Och så, den sammansatta språkinstruktionen som är 'LDA $C453,X' eller 'LDA $C453,Y' upptar tre på varandra följande byte i minnet, och inte fyra eller fem.

Noll-sida indexerad adressering
Den nollsidiga indexadresseringen är som den absoluta indexadresseringen som beskrivits tidigare, men målbyten måste endast vara på sidan noll (från $0000 till $00FF). Nu, när det gäller nollsidan, den högre byten som alltid är 00 H för minnesplatserna undviks vanligtvis. Så det nämns normalt att sida noll börjar från $00 till FF. Och så, den tidigare instruktionen för 'LDA $C453,X' är:

LDA $53,X

$C4, en högre byte som refererar till en sida ovanför sidan noll, kan inte användas i denna instruktion eftersom den placerar den förväntade målbyten som ska laddas in i den ackumulerade byten utanför och ovanför sidan noll.

När värdet som skrivs i instruktionen läggs till värdet i indexregistret ska summan inte ge ett resultat över sidan noll (FF H ). Så det är uteslutet att ha en instruktion som 'LDA $FF, X' och ett värde som FF H i indexregistret eftersom FF H + FF H = 200 H som är den första byte-platsen ($0200) på sida 2 (tredje sidan) i minnet, är ett stort avstånd från sida 0. Så, med nollsidig indexerad adressering, måste den effektiva adressen ligga på sidan noll.

Indirekt adressering

Hoppa absolut adressering
Innan vi diskuterar den absoluta indirekta adresseringen är det bra att först titta på JMP:s absoluta adressering. Antag att adressen som har värdet av intresse (målbyte) är $8765. Detta är 16-bitar som består av två byte: den högre byten som är 87 H och den nedre byten som är 65 H . Så de två byten för $8765 placeras i PC:n (programräknaren) för nästa instruktion. Det som skrivs i assemblerspråksprogrammet (filen) är:

JMP $8765

Det exekverande programmet i minnet hoppar från vilken adress det än nådde till $8765. JMP-mnemoniken har tre opkoder som är 4C, 6C och 7C. Op-koden för denna absoluta adressering är 4C. Op-koden för JMP:s absoluta indirekta adressering är 6C (se följande illustrationer).

Absolut indirekt adressering
Detta används endast med hoppinstruktionen (JMP). Antag att adressen som har byten av intresse (målbyte) är $8765. Detta är 16-bitar som består av två byte: den högre byten som är 87 H och den nedre byten som är 65 H . Med absolut indirekt adressering är dessa två byte faktiskt placerade på två på varandra följande byteplatser någon annanstans i minnet.

Antag att de finns i minnesplatserna $0210 och $0211. Sedan den nedre byten för adressen av intresse som är 65 H finns i $0210-adressen och den högre byten som är 87 H finns i $0211-adressen. Det betyder att den lägre minnesbyten av intresse går till lägre konsekutiv adress, och den högre minnesbyten av intresse går till den högre konsekutiva adressen - little endianness.

16-bitars adressen kan referera till två på varandra följande adresser i minnet. I det ljuset hänvisar $0210-adressen till adresserna $0210 och $0211. Adressparet $0210 och $0211 innehåller den ultimata adressen (16-bitar av två byte) för målbyten, med den nedre byten på 65 H i $0210 och den högre byten på 87 H i $0211. Så, hoppinstruktionen som skrivs är:

JMP (0 210 USD)

JMP-mnemoniken har tre opkoder som är 4C, 6C och 7C. Op-koden för absolut indirekt adressering är 6C. Det som skrivs i textfilen är 'JMP ($0210)'. På grund av parenteserna använder assemblern (översättaren) opkoden 6C för JMP, och inte 4C eller 7C.

Med absolut indirekt adressering finns det faktiskt tre minnesregioner. Den första regionen kan bestå av byteplatserna $0200, $0201 och $0202. Detta har tre byte för 'JMP ($0210)'-instruktionen. Den andra regionen, som inte nödvändigtvis ligger bredvid den första, består av de två på varandra följande byteplatserna $0210 och $0211. Det är den nedre byten här ($0210) som skrivs in i assembly-språkprograminstruktionen. Om adressen av intresse är $8765, den nedre byten på 65 H är på $0210-byteplatsen och den högre byten på 87 H är på $0211 byte-platsen. Den tredje regionen består av bara en byteplats. Den är av $8765-adressen för den riktade byten (den ultimata byten av intresse). Paret av på varandra följande adresser, $0210 och $0211, innehåller $8765-pekaren som är adressen av intresse. Efter datortolkningen är det $8765 som går in i PC:n (Program Counter) för att komma åt målbyten.

Noll sida indirekt adressering
Denna adressering är densamma som den absoluta indirekta adresseringen, men pekaren måste vara på sidan noll. Den nedre byteadressen för pekarregionen är vad som finns i den inskrivna instruktionen enligt följande:

JMP ($50)

Den högre byten av pekaren är på $51 byte-platsen. Den effektiva adressen (spetsad) behöver inte vara på sidan noll.

Så med indexadressering läggs värdet i ett indexregister till den basadress som ges i instruktionen att ha den effektiva adressen. Indirekt adressering använder en pekare.

4.8 Indexerad indirekt adressering

Absolut indexerad indirekt adressering
Detta adresseringsläge används endast med JMP-instruktionen.
Med absolut indirekt adressering finns det spetsvärde (byte) med sina egna två på varandra följande byteadresser. Dessa två på varandra följande adresser bildar pekaren att vara i pekarområdet för två på varandra följande bytes i minnet. Den nedre byten i pekarområdet är det som skrivs in i instruktionen inom parentes. Pekaren är adressen till det spetsiga värdet. I den tidigare situationen är $8765 adressen till det spetsiga värdet. $0210 (följt av $0211) är adressen vars innehåll är $8765 som är pekaren. Med det absoluta indirekta adresseringsläget är det ($0210) som skrivs in i programmet (textfil), inklusive parenteser.

Å andra sidan, med det absoluta indexerade indirekta adresseringsläget, bildas den lägre adressbyten för pekarregionen genom att addera värdet i X-registret till den inskrivna adressen. Till exempel, om pekaren är på adressplatsen $0210, kan den inskrivna instruktionen vara ungefär så här:

JMP ($020A,X)

Där X-registret har värdet 6 H . 020A H + 6 H = 0210 H . Y-registret används inte med detta adresseringsläge.

Noll sida indexerad indirekt adressering
Detta adresseringsläge använder X-registret och inte Y-registret. Med detta adresseringsläge finns det fortfarande det spetsiga värdet och pekaren i dess tvåbyte-adresspekareområde. Det måste finnas två på varandra följande byte på sidan noll för pekaren. Adressen som skrivs in i instruktionen är en enbyte-adress. Detta värde läggs till värdet i X-registret och eventuell överföring kasseras. Resultatet pekar på pekarområdet på sidan 0. Till exempel, om adressen av intresse (pekad) är $8765 och den är på byteplatserna $50 och $51 på sida 0, och värdet i X-registret är $30, maskinskriven instruktion är ungefär så här:

LDA ($20,X)

Eftersom $20 + $30 = $50.

Indirekt indexerad adressering
Detta adresseringsläge använder Y-registret och inte X-registret. Med denna adresseringsmod finns det fortfarande det spetsiga värdet och pekarområdet, men innehållet i pekarområdet fungerar annorlunda. Det måste finnas två på varandra följande byte på sidan noll för pekarområdet. Den nedre adressen för pekarområdet skrivs in i instruktionen. Detta antal (bytepar) som finns i pekarområdet läggs till värdet i Y-registret för att få den verkliga pekaren. Låt till exempel adressen av intresse (pekad) vara $8765, värdet på 6H vara i Y-registret och numret (två byte) vara på adressen 50 H och 51 H . De två byten tillsammans är $875F eftersom $875F + $6 = $8765. Den maskinskrivna instruktionen är ungefär så här:

LDA ($50),Y

4.9 Instruktioner för ökning, minskning och test-BIT

Följande tabell visar hur instruktionerna för ökning och minskning fungerar:

INA och DEA ​​ökar respektive minskar ackumulatorn. Det kallas ackumulatoradressering. INX, DEX, INY och DEY är för X- respektive Y-registren. De tar ingen operand. Så de använder det implicita adresseringsläget. Inkrement innebär att lägga till 1 till registret eller minnesbyten. Dekrementering innebär att subtrahera 1 från registret eller minnesbyten.

INC och DEC ökar respektive minskar en minnesbyte (och inte ett register). Användning av nollsidesadresseringen istället för den absoluta adresseringen är att spara på minnet för instruktionen. Nollsidesadressering är en byte mindre än den absoluta adresseringen för instruktionen i minnet. Emellertid påverkar nollsidans adresseringsläge endast sidan noll.

BIT-instruktionen testar bitarna i en byte i minnet med de 8 bitarna i ackumulatorn, men ändrar ingendera. Endast vissa flaggor i processorstatusregistret 'P' är inställda. Bitarna för den specificerade minnesplatsen är logiskt OCH-försedda med ackumulatorns bitar. Sedan ställs följande statusbitar in:

  • N som är bit 7 och den sista biten (vänster) i statusregistret, tar emot bit 7 i minnesplatsen före OCH-ningen.
  • V som är bit 6 i statusregistret tar emot bit 6 i minnesplatsen före OCH-ningen.
  • Z-flaggan för statusregistret sätts (görs till 1) om resultatet av OCH är noll (00000000 2 ). Annars rensas den (görs till 0).

4.10 Jämför instruktioner

Jämförelseinstruktionsmnemoniken för 6502 µP är CMP, CPX och CPY. Efter varje jämförelse påverkas N-, Z- och C-flaggorna i processorstatusregistret 'P'. N-flaggan sätts (görs till 1) när resultatet är ett negativt tal. Z-flaggan sätts (görs till 1) när resultatet är en nolla (000000002). C-flaggan sätts (görs till 1) när det finns en överföring från den åtta till den nionde biten. Följande tabell ger en detaljerad illustration

Betyder 'större än'. Med det borde jämförelsetabellen vara självförklarande.

4.11 Hopp- och greninstruktioner

Följande tabell sammanfattar hopp- och greninstruktionerna:

JMP-instruktionen använder den absoluta och indirekta adresseringen. Resten av instruktionerna i tabellen är greninstruktioner. De använder endast den relativa adresseringen med 6502 µP. Med det blir tabellen självförklarande om den läses från vänster till höger och uppifrån och ned.

Observera att grenarna endast kan tillämpas på adresser inom -128 till +127 byte från den givna adressen. Detta är relativ adressering. För både JMP- och filialinstruktionerna påverkas programräknaren (PC) direkt. 6502 µP tillåter inte grenarna till en absolut adress, även om hoppet kan göra den absoluta adresseringen. JMP-instruktionen är inte en filialinstruktion.

Notera: Relativ adressering används endast med greninstruktioner.

4.12 Stackområdet

En subrutin är som ett av de tidigare korta programmen att lägga till två tal eller subtrahera två tal. Stackområdet i minnet börjar från $0100 till $01FF inklusive. Detta område kallas helt enkelt för stack. När mikroprocessorn utför ett hopp till subrutininstruktionen (JSR – se följande diskussion), måste den veta var den ska återvända när den är klar. 6502 µP håller denna information (returadress) i lågt minne från $0100 till $01FF (stackområdet) och använder stackpekarregisterinnehållet som är 'S' i mikroprocessorn som en pekare (9 bitar) till den senast returnerade adressen som lagras på sida 1 ($0100 till $01FF) i minnet. Stacken växer ner från $01FF och gör det möjligt att kapsla subrutinerna upp till 128 nivåer djupa.

En annan användning av stackpekaren är att hantera avbrotten. 6502 µP har stiften märkta som IRQ och NMI. Det är möjligt för några små elektriska signaler att appliceras på dessa stift och få 6502 µP att sluta köra ett program och få det att börja köra ett annat. I detta fall avbryts det första programmet. Liksom subrutiner kan avbrottskodsegmenten kapslas. Avbrottsbehandling diskuteras i nästa kapitel.

Notera : Stackpekaren har 8 bitar för den lägre byteadressen för att adressera platserna från $0100 till $01FF. Den högre byten på 00000001 2 är antaget.

Följande tabell ger instruktionerna som relaterar stackpekaren 'S' med A-, X-, Y- och P-registren till stackområdet i minnet:

4.13 Subrutin för samtal och retur

En subrutin är en uppsättning instruktioner som uppnår ett visst mål. Det tidigare additions- eller subtraktionsprogrammet är en mycket kort subrutin. Subrutiner kallas ibland bara rutiner. Instruktionen för att anropa en subrutin är:

JSR : Hoppa till SubRoutine

Instruktionen för att återvända från en subrutin är:

RTS : Återvänd från subrutin

Mikroprocessorn har en tendens att kontinuerligt utföra instruktionerna i minnet, en efter en. Antag att mikroprocessorn för närvarande exekverar ett kodsegment och den stöter på en hoppinstruktion (JMP) för att gå och exekvera ett kodsegment som är kodat bakom det som det kanske redan exekveras. Den exekverar det kodsegmentet bakom och fortsätter att exekvera alla kodsegment (instruktioner) efter kodsegmentet bakom, tills det kör om det aktuella kodsegmentet igen och fortsätter nedanför. JMP skickar inte nästa instruktion till stacken.

Till skillnad från JMP skjuter JSR adressen till nästa instruktion efter sig själv från PC:n (programräknaren) till stacken. Stackpositionen för denna adress placeras i stackpekaren 'S'. När en RTS-instruktion påträffas (exekveras) i subrutinen, drar adressen som trycks på stacken av stacken och programmet återupptas vid den avdragna adressen som är nästa instruktionsadress precis före subrutinanropet. Den sista adressen som tas bort från stacken skickas till programräknaren. Följande tabell ger de tekniska detaljerna för JSR- och RTS-instruktionerna:

Se följande illustration för användningen av JSR och RTS:

4.14 Exempel på en nedräkningsslinga

Följande subrutin räknar ner från $FF till $00 (totalt 256 10 räknas):

starta LDX #$FF ; ladda X med $FF = 255
loop DEX ; X = X – 1
BNE loop ; om X inte är noll så gå till loop
RTS ; lämna tillbaka

Varje rad har en kommentar. Kommentarer hamnar aldrig i minnet för exekvering. Den assembler (översättaren) som konverterar ett program till vad det finns i minnet för körning (kör) tar alltid bort kommentarerna. En kommentar börjar med ';' . 'Start' och 'loop' i detta program kallas etiketter. En etikett identifierar (namnet) för instruktionens adress. Om instruktionen är en enkelbyte-instruktion (implicit adressering), är etiketten adressen för den instruktionen. Om instruktionen är en multibyte-instruktion identifierar etiketten den första byten för multibyte-instruktionen. Den första instruktionen för detta program består av två byte. Förutsatt att den börjar på $0300-adressen, kan $0300-adressen ersättas med 'start' nere i programmet. Den andra instruktionen (DEX) är en enkelbyte-instruktion och bör vara på $0302-adressen. Detta innebär att $0302-adressen kan ersättas med 'loop', nere i programmet, vilket faktiskt är så i 'BNE loop'.

'BNE loop' betyder grenen till den angivna adressen när Z-flaggan i statusregistret är 0. När värdet i A- eller X- eller Y-registret är 00000000 2 , på grund av den senaste operationen är Z-flaggan 1 (inställd). Så medan det är 0 (inte 1), upprepas de andra och tredje instruktionerna i programmet i den ordningen. I varje upprepad sekvens minskas värdet (hela talet) i X-registret med 1. DEX betyder X = X – 1. När värdet i X-registret är $00 = 00000000 2 , Z blir 1. Vid den tidpunkten finns det ingen mer upprepning av de två instruktionerna. Den sista RTS-instruktionen i programmet, som är en enkelbyte-instruktion (implicit adressering), returnerar från subrutinen. Effekten av denna instruktion är att göra programräknarens adress i stacken för koden som ska exekveras före subrutinanropet och gå tillbaka till programräknaren (PC). Denna adress är adressen till instruktionen som ska exekveras innan subrutinen anropas.

Notera: När du skriver ett assemblerspråksprogram för 6502 µP måste endast en etikett börja i början av en rad; alla andra radkoder måste flyttas minst ett mellanslag åt höger.

Ringer en subrutin
Om man ignorerar minnesutrymmet som tas upp av de tidigare etiketterna, tar programmet 6 byte av på varandra följande platser i minnet (RAM) från $0300 till $0305. I det här fallet är programmet:

LDX #$FF ; ladda X med $FF = 255
DEX ; X = X – 1
BNE $0302 ; om X inte är noll så gå till loop
RTS ; lämna tillbaka

Börjar från $0200-adressen i minnet kan anropet för subrutinen. Anropsinstruktionen är:

JSR start ; start är adressen $0300, dvs JSR $0300

Subrutinen och dess anrop som är korrekt skrivna i textredigeringsfilen är:

starta LDX #$FF; ladda X med $FF = 255
loop DEX ; X = X – 1

BNE loop ; om X inte är noll så gå till loop
RTS ; lämna tillbaka

JSR start: hoppa till rutin som börjar på $0300

Nu kan det finnas många subrutiner i ett långt program. Alla kan inte ha namnet 'start'. De borde ha olika namn. Faktum är att ingen av dem kanske har namnet 'start'. 'Start' används här av undervisningsskäl.

4.15 Översätta ett program

Att översätta ett program eller sätta ihop det betyder samma sak. Tänk på följande program:

starta LDX #$FF : ladda X med $FF = 255
loop DEX : X = X – 1
BNE loop : om X inte är noll så gå till loop
RTS : återvända
JSR start: hoppa till rutin som börjar på $0300

Detta är programmet som tidigare skrivits. Den består av subrutinen, start och anropet till subrutinen. Programmet räknar ner från 255 10 till 0 10 . Programmet börjar vid användarens startadress på $0200 (RAM). Programmet skrivs in i en textredigerare och sparas på disken. Den har ett namn som 'sample.asm' där 'sample' är namnet på programmerarens val men '.asm'-tillägget för assemblerspråket måste associeras med filnamnet.

Det sammansatta programmet produceras av ett annat program som kallas en assembler. Monteringsenheten levereras av tillverkaren av 6502 µP eller av en tredje part. Assembleren reproducerar programmet på ett sådant sätt att det finns i minnet (RAM) när det körs (körs).

Antag att JSR-instruktionen börjar vid $0200-adressen och subrutinen börjar vid $0300-adressen. Montören tar bort alla kommentarer och blanksteg. Kommentarerna och vita utrymmen slösar bort minnet som alltid är ont om. En möjlig tom rad mellan det föregående subrutinkodsegmentet och subrutinanropet är ett exempel på blanksteg. Den sammansatta filen är fortfarande sparad på disken, och den heter något som 'sample.exe'. 'Samplet' är namnet på programmerarens val, men tillägget '.exe' bör finnas där för att indikera att det är en körbar fil.

Det sammansatta programmet kan dokumenteras enligt följande:

Att producera ett dokument som detta sägs vara att sätta ihop för hand. Observera att kommentarerna i detta dokument inte visas i minnet (för exekvering). Adresskolumnen i tabellen anger startadresserna för instruktionerna i minnet. Observera att 'JSR start', det vill säga 'JSR $0300', som förväntas kodas som '20 03 00', faktiskt är kodad som '20 00 03' med den nedre minnesbyteadressen som tar den lägre byten i minnet och högre minnesbyte-adress tar den högre byten i minnet – lite endianness. Op-koden för JSR är 20 16 .

Observera att förskjutningen till en greninstruktion som BNE är ett tvåkomplementnummer i intervallet 128 10 till +127 10 . Så, 'BNE loop' betyder 'BNE -1 10 ” som egentligen är ”D0 FF” i kodformen FF 16 är -1 i tvås komplement som skrivs som = 11111111 i bas två. Assemblerprogrammet ersätter etiketterna och fälten till faktiska hexadecimala tal (hexadecimala tal är binära tal som är grupperade i fyra bitar). De faktiska adresserna där varje instruktion börjar ingår faktiskt.

Notera: 'JSR start'-instruktionen ersätts av kortare instruktioner som skickar det aktuella innehållet (hög och låg byte) i programräknaren till stacken med stackpekaren som minskas två gånger (en gång för hög byte och en gång för låg byte) och laddar sedan om datorn med $0300-adressen. Stackpekaren pekar nu på $00FD, förutsatt att den är initialiserad till $01FF.

RTS-instruktionen ersätts också av ett antal kortare instruktioner som ökar stackpekaren 'S' två gånger (en gång för låg byte och en gång för hög byte) och drar motsvarande två byte med adress från stackpekaren till PC:n för nästa instruktion.

Notera: En etiketttext bör inte ha mer än 8 tecken.

'BNE loop' använder den relativa adresseringen. Det betyder att lägga till -3 10 till nästa programräknare innehåll på $0305. Byten för 'BNE loop' är 'D0 FD' där FD är de tvås komplement till -3 10 .

Obs: Detta kapitel innehåller inte alla instruktioner för 6502 µP. Alla instruktioner och deras detaljer finns i dokumentet med titeln 'SY6500 8-bitars mikroprocessorfamilj'. Det finns en PDF-fil med namnet '6502.pdf' för detta dokument som är fritt tillgänglig på Internet. 6502 µP som beskrivs i detta dokument är 65C02.

4.16 Avbrott

Signalerna från alla enheter som är anslutna till de externa portarna (vertikal yta) på Commodore 64 måste passera antingen CIA 1- eller CIA 2-kretsarna (IC) innan de når 6502-mikroprocessorn. Signalerna från databussen på 6502 µP måste passera antingen genom CIA 1- eller CIA 2-chippet innan de når någon extern enhet. CIA står för Complex Interface Adapter. I Fig 4.1 'Blockdiagram av Commodore_64-moderkortet' representerar blockinmatnings-/utgångsenheterna CIA 1 och CIA 2. När ett program körs kan det avbrytas för att köra någon annan kod innan du fortsätter. Det finns hårdvaruavbrott och mjukvaruavbrott. För hårdvaruavbrott finns det två ingångssignalstift till 6502 µP. Namnen på dessa stift är IRQ och NMI . Dessa är inte µP-datalinjer. Datalinjerna för µP är D7, D6, D5, D4, D3, D2, D1 och D0; med D0 för den minst signifikanta biten och D7 för den mest signifikanta biten.

IRQ står för Interrupt ReQuest 'active' low. Denna ingångsledning till µP är normalt hög, cirka 5 volt. När den går ner till ungefär 0 volt är det en avbrottsbegäran som signalerar µP. Så snart begäran beviljas går raden tillbaka högt. Att bevilja avbrottsbegäran innebär att µP grenar till koden (subrutinen) som hanterar avbrottet.

NMI står för Non-Maskable Interrupt 'active' low. Medan koden för IRQ avrättas NMI kan gå lågt. I detta fall, NMI hanteras (dess egen kod exekveras). Efter det kommer koden för IRQ fortsätter. Efter koden för IRQ avslutas fortsätter huvudprogramkoden. Det är, NMI avbryter IRQ hanterare. Signalen för NMI kan fortfarande ges till µP även när µP är inaktiv och inte hanterar någonting eller inte kör ett huvudprogram.

Notera: Det är faktiskt övergången från högt till lågt, av NMI , det är NMI signal – mer om det senare. IRQ kommer normalt från CIA 1 och NMI kommer normalt från CIA 2. NMI , som står för Non-Maskable Interrupt, kan betraktas som non-stopable interrupt.

Hantering av avbrott
Om förfrågan är från IRQ eller NMI , måste den aktuella instruktionen slutföras. 6502 har bara A-, X- och Y-registren. Medan en subrutin fungerar kan den använda dessa tre register tillsammans. En avbrottshanterare är fortfarande en subrutin, även om den inte ses som sådan. Efter att den aktuella instruktionen är klar, sparas innehållet i A-, X- och Y-registren för 65C02 µP i stacken. Adressen till nästa instruktion av programräknaren skickas också till stacken. µP förgrenas sedan till koden för avbrottet. Därefter återställs innehållet i A-, X- och Y-registren från stacken i omvänd ordning som de skickas till.

Exempelkodning för ett avbrott
För enkelhets skull, antag att rutinen för µP IRQ avbryta är bara att lägga till siffrorna $01 och $02 och spara resultatet av $03 på minnesadressen $0400. Koden är:

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

ISR är en etikett och identifierar minnesadressen där PHA-instruktionen finns. ISR betyder Interrupt Service Rutin. PHA, PHX och PHY skickar innehållet i A-, X- och Y-registren till stacken med hopp om att de kommer att behövas av vilken kod (program) som helst som körs precis innan avbrottet. De följande tre instruktionerna utgör kärnan i avbrottshanteraren. PLY-, PLX- och PLA-instruktionerna måste vara i den ordningen, och de tar tillbaka innehållet i Y-, X- och A-registren. Den sista instruktionen, som är RTI, (utan en operand) returnerar fortsättningen av exekveringen till vilken kod (program) som än körs före avbrott. RTI drar adressen till nästa instruktion i koden som körs från stacken tillbaka till programräknaren. RTI betyder ReTurn from Interrupt. Därmed är avbrottshanteringen (subrutinen) över.

Programavbrott
Det huvudsakliga sättet att få ett mjukvaruavbrott för 6502 µP är att använda BRK-underförstådd adressinstruktion. Antag att huvudprogrammet körs och att det stöter på BRK-instruktionen. Från den punkten ska adressen till nästa instruktion i PC:n skickas till stacken när den aktuella instruktionen är klar. En subrutin för att hantera programvaruinstruktionen bör kallas 'nästa'. Denna avbrottssubrutin bör skjuta A-, X- och Y-registerinnehållet till stacken. Efter att kärnan av subrutinen exekveras, bör innehållet i A-, X- och Y-registren dras tillbaka från stacken till deras register av den fullbordande subrutinen. Det sista uttalandet i rutinen är RTI. PC-innehållet dras också tillbaka från stacken till datorn automatiskt på grund av RTI.

Jämföra och kontrastera rutin för subrutin och avbrottstjänst
Följande tabell jämför och kontrasterar rutinerna för subrutiner och avbrottstjänster:

4.17 Sammanfattning av 6502 huvudadresseringslägen

Varje instruktion för 6502 är en byte, följt av noll eller fler operander.

Omedelbart adresseringsläge
Med omedelbart adresseringsläge, efter operanden, är värdet och inte en minnesadress. Värdet måste föregås av #. Om värdet är hexadecimalt måste '#' följas av '$'. De omedelbara adresseringsinstruktionerna för 65C02 är: ADC, AND, BIT, CMP, CPX, CPY, EOR, LDA, LDX, LDY, ORA, SBC. Läsaren bör konsultera dokumentationen för 65C02 µP för att veta hur man använder instruktionerna som listas här och som inte förklaras i detta kapitel. En exempelinstruktion är:

LDA #77 USD

Absolut adresseringsläge
I absolut adresseringsläge finns det en operand. Denna operand är adressen till värdet i minnet (vanligtvis i hexadecimal eller en etikett). Det finns 64K 10 = 65,536 10 minnesadresser för 6502 µP. Vanligtvis finns enbytevärdet på en av dessa adresser. De absoluta adresseringsinstruktionerna för 65C02 är: 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äsaren bör konsultera dokumentationen för 65C02 µP för att veta hur man använder instruktionerna som listas här, såväl som för resten av adresseringslägena som inte förklaras i detta kapitel. En exempelinstruktion är:

DE ÄR $1234

Underförstått adresseringsläge
I implicit adresseringsläge finns det ingen operand. Alla inblandade µP-register antyds av instruktionen. De underförstådda adresseringsinstruktionerna för 65C02 är: 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 exempelinstruktion är:

DEX : Minska X-registret med en enhet.

Relativt adresseringsläge
Relativt adresseringsläge behandlar endast greninstruktioner. I relativ adresseringsmod finns det bara en operand. Det är ett värde från -128 10 till +127 10 . Detta värde kallas en offset. Baserat på tecknet läggs detta värde till eller subtraheras från nästa instruktion av programräknaren för att resultera i adressen till den avsedda nästa instruktionen. De relativa adresslägesinstruktionerna är: BCC, BCS, BEQ, BMI, BNE, BPL, BRA, BVC, BVS. Instruktionsexemplen är:

BNE $7F : (gren om Z = 0 i statusregistret, P)

Som lägger till 127 till den aktuella programräknaren (adress att köra) och börjar exekvera instruktionen på den adressen. Liknande:

BEQ $F9 : (gren om Z = : i statusregistret, P)

Som lägger till en -7 till den aktuella programräknaren och startar exekvering på den nya programräknarens adress. Operanden är ett tvåkomplementnummer.

Absolut indexerad adressering
Vid absolut indexadressering läggs innehållet i X- eller Y-registret till den givna absoluta adressen (var som helst från $0000 till $FFFF, d.v.s. från 0 10 till 65536 10 ) för att ha den riktiga adressen. Denna givna absoluta adress kallas basadressen. Om X-registret används är monteringsinstruktionen ungefär så här:

LDA $C453,X

Om Y-registret används är det något i stil med:

LDA $C453,Y

Värdet för X- eller Y-registret kallas räknings- eller indexvärde, och det kan vara allt från $00 (0) 10 ) till $FF (250 10 ). Det kallas inte offset.

De absoluta indexadresseringsinstruktionerna är: ADC, AND, ASL (endast X), BIT (med ackumulator och minne, endast med X), CMP, DEC (endast minne och X), EOR, INC (endast minne och X), LDA , LDX, LDY, LSR (endast X), ORA, ROL (endast X), ROR (endast X), SBC, STA, STZ (endast X).

Absolut indirekt adressering
Detta används endast med hoppinstruktionen. Med detta har den givna absoluta adressen en pekadress. Pekaradressen består av två byte. Tvåbytepekaren pekar på (är adressen till) destinationsbytevärdet i minnet. Så instruktionen för assemblerspråk är:

JMP ($3456)

Med parentes, och $13 är i adressplatsen $3456 medan $EB är i adressplatsen $3457 (= $3456 + 1). Då är destinationsadressen $13EB och $13EB är pekaren. Den absoluta $3456 står inom parentes i instruktionen där 34 är den lägre byten och 56 är den högre byten.

4.18 Skapa en sträng med 6502 µP Assembly Language

Som visas i nästa kapitel, efter att ha skapat en fil i minnet, kan filen sparas på disken. Filen måste få ett namn. Namnet är ett exempel på en sträng. Det finns många andra exempel på strängar i programmering.

Det finns två huvudsakliga sätt att skapa en sträng av ASCII-koder. På båda sätten tar alla ASCII-koder (tecken) på varandra följande byteplatser i minnet. På ett av sätten föregås denna sekvens av byte av en heltalsbyte som är längden (antal tecken) i sekvensen (strängen). På det andra sättet efterföljs teckensekvensen (omedelbart följt) av nollbyten som är 00 16 , dvs $00. Strängens längd (antal tecken) anges inte på detta annat sätt. Null-tecknet används inte på det första sättet.

Tänk till exempel på 'Jag älskar dig!' sträng utan citattecken. Längden här är 11; ett mellanslag räknas som en ASCII-byte (tecken). Antag att strängen måste placeras i minnet med det första tecknet på adressen $0300.

Följande tabell visar strängminnesinställningen när den första byten är 11 10 = 0B 16 :

Följande tabell visar strängminnesinställningen när den första byten är 'I' och den sista byten är Null ($00):

Följande instruktion kan användas för att börja skapa strängen:

DE KOSTAR 0300 $

Antag att den första byten finns i ackumulatorn som ska skickas till adressplatsen $0300. Denna instruktion gäller för båda fallen (båda typerna av strängar).

Efter att ha passat in alla tecken i minnescellerna, en i taget, kan strängen läsas med hjälp av en slinga. För det första fallet läses antalet tecken efter längden upp. I det andra fallet läses tecknen från 'I' tills nolltecknet som är 'Null' uppfylls.

4.19 Skapa en array med 6502 µP Assembly Language

En matris med enkla byte-heltal består av på varandra följande minnesbyteplatser med heltal. Sedan finns det en pekare som pekar på platsen för det första heltal. Så en matris med heltal består av två delar: pekaren och serien av platser.

För en uppsättning strängar kan varje sträng finnas på en annan plats i minnet. Sedan finns det på varandra följande minnesplatser med pekare där varje pekare pekar på den första platsen för varje sträng. En pekare i detta fall består av två byte. Om en sträng börjar med sin längd pekar motsvarande pekare på platsen för den längden. Om en sträng inte börjar med sin längd utan slutar med ett nolltecken, pekar motsvarande pekare på platsen för det första tecknet i strängen. Och det finns en pekare som pekar på den nedre byteadressen för den första pekaren av på varandra följande pekare. Så, en array av strängar består av tre delar: strängarna på olika platser i minnet, motsvarande på varandra följande pekare och pekaren till den första pekaren av de på varandra följande pekarna.

4.20 Problem

Läsaren rekommenderas att lösa alla problem i ett kapitel innan du går vidare till nästa kapitel.

  1. Skriv ett assemblerspråksprogram som börjar på $0200 för 6502 µP och lägger till de osignerade numren för 2A94 H (lägg till) till 2ABF H (augend). Låt ingångarna och utgångarna finnas i minnet. Ta också fram det sammansatta programdokumentet för hand.
  2. Skriv ett assemblerprogram som börjar på $0200 för 6502 µP och subtraherar de osignerade talen på 1569 H (subtrahend) från 2ABF H (minuend). Låt in- och utgångarna finnas i minnet. Ta också fram det sammansatta programdokumentet för hand.
  3. Skriv ett assemblerspråksprogram för 6502 µP som räknas upp från $00 till $09 med hjälp av en loop. Programmet bör börja på $0200. Ta också fram det sammansatta programdokumentet för hand.
  4. Skriv ett assemblerprogram som börjar på $0200 för 6502 µP. Programmet har två subrutiner. Den första subrutinen lägger till de osignerade numren för 0203 H (augend) och 0102H (tillägg). Den andra subrutinen adderar summan från den första subrutinen som är 0305H till 0006 H (augend). Det slutliga resultatet lagras i minnet. Ring den första subrutinen som är FSTSUB och den andra subrutinen som är SECSUB. Låt in- och utgångarna finnas i minnet. Ta också fram det sammansatta programdokumentet för hela programmet för hand.
  5. Med tanke på att en IRQ hanteraren lägger till $02 till $01 vid ackumulatorn som kärnhantering medan NMI utfärdas och kärnhanteringen för NMI lägger till $05 till $04 vid ackumulatorn, skriv ett assemblerspråk för båda hanterarna inklusive deras samtal. Uppmaningen till IRQ hanteraren ska vara på adressen $0200. De IRQ hanteraren bör börja på adressen $0300. De NMI hanteraren bör börja på adressen $0400. Resultatet av IRQ hanteraren bör placeras på adressen $0500, och resultatet av NMI hanteraren ska placeras på adressen $0501.
  6. Förklara kort hur BRK-instruktionen används för att producera mjukvaruavbrottet i en 65C02-dator.
  7. Skapa en tabell som jämför och kontrasterar en normal subrutin med en rutin för avbrottstjänst.
  8. Förklara kortfattat de huvudsakliga adresseringslägena för 65C02 µP givet assemblerspråksinstruktionsexemplen.
  9. a) Skriv ett 6502 maskinspråksprogram för att sätta 'Jag älskar dig!' sträng av ASCII-koder i minnet, med början från $0300-adressen med strängens längd. Programmet bör börja på $0200-adressen. Få varje karaktär från ackumulatorn en efter en, förutsatt att de skickas dit, av någon subrutin. Sätt också ihop programmet för hand. (Om du behöver veta ASCII-koderna för 'I love you!'. Här är de: 'I':49 16 , utrymme: 20 16 , 'l': 6C 16 , 'o':6F 16 , 'i':76 16 , 'e':65, 'y':79 16 , 'in':75 16 , och '!':21 16 (Obs: varje kod upptar 1 byte).
    b) Skriv ett 6502 maskinspråksprogram för att sätta 'Jag älskar dig!' sträng av ASCII-koder i minnet, med början från $0300-adressen utan längden på strängen men slutar på 00 16 . Programmet bör börja på $0200-adressen. Få varje karaktär från ackumulatorn, förutsatt att de skickas dit, en efter en, av någon subrutin. Sätt också ihop programmet för hand.