Intel x86 Assembly Language & Microarchitecture
Fundamentals registreren
Zoeken…
16-bits registers
Toen Intel de originele 8086 definieerde, was het een 16-bit processor met een 20-bit adresbus (zie hieronder). Ze definieerden 8 16-bits registers voor algemeen gebruik - maar gaven ze specifieke rollen voor bepaalde instructies:
-
AXHet accumulatorregister.
Veel opcodes namen dit register aan of waren sneller als het werd gespecificeerd. -
DXHet gegevensregister.
Dit werd soms gecombineerd als de hoge 16 bits van een 32-bits waarde metAX- bijvoorbeeld als resultaat van een vermenigvuldiging. -
CXHet telregister.
Dit werd gebruikt in een aantalLOOPNEinstructies als de impliciete teller voor die lussen - bijvoorbeeldLOOPNE(lus indien niet gelijk) enREP(herhaalde verplaatsing / vergelijking) -
BXHet basisregister.
Dit kan worden gebruikt om de basis van een structuur in het geheugen te indexeren - geen van de bovenstaande registers kan worden gebruikt om direct in het geheugen te indexeren. -
SIHet bronindexregister.
Dit was de impliciete bronindex in het geheugen voor bepaalde verplaatsings- en vergelijkingsbewerkingen. -
DIHet register met bestemmingsindex.
Dit was de impliciete bestemmingsindex in het geheugen voor bepaalde verplaatsings- en vergelijkingshandelingen. -
SPHet Stack Pointer-register.
Dit is het minst algemene register in de set! Het wees naar de huidige positie in de stapel, die expliciet werd gebruikt voorPUSHenPOPbewerkingen, impliciet voorCALLenRETmet subroutines en ZEER impliciet tijdens interrupts. Als zodanig was het gebruiken voor iets anders gevaarlijk voor uw programma! -
BPHet basispointerregister.
Wanneer subroutines andere subroutines aanroepen, bevat de stapel meerdere "stapelframes".BPkan worden gebruikt om het huidige stapelframe vast te houden, en wanneer een nieuwe subroutine wordt genoemd, kan deze op de stapel worden opgeslagen, het nieuwe stapelframe worden gemaakt en gebruikt, en bij terugkeer vanuit de binnenste subroutine kan de oude stapelframe-waarde worden hersteld .
Opmerkingen:
De eerste drie registers kunnen niet worden gebruikt voor indexering in het geheugen.
BX,SIenDIindexeren standaard in het huidige gegevenssegment (zie hieronder).MOV AX, [BX+5] ; Point into Data Segment MOV AX, ES:[DI+5] ; Override into Extra SegmentDI, wanneer gebruikt in geheugen-naar-geheugen-bewerkingen zoalsMOVSenCMPS, gebruikt alleen het extra segment (zie hieronder). Dit kan niet worden opgeheven.SPenBPgebruiken standaard het stapelsegment (zie hieronder).
32-bit registers
Toen Intel de 80386 produceerde, werden ze geüpgraded van een 16-bits processor naar een 32-bits processor. 32-bit verwerking betekent twee dingen: zowel de gemanipuleerde gegevens waren 32-bit, en de geheugenadressen waartoe toegang werd verkregen waren 32-bit. Om dit te doen, maar toch compatibel te blijven met hun eerdere processors, introduceerden ze hele nieuwe modi voor de processor. Het was in de 16-bits modus of de 32-bits modus, maar je kon deze modus op instructie voor instructie overschrijven voor gegevens, adressering of beide!
Allereerst moesten ze 32-bit registers definiëren. Ze deden dit door de bestaande acht eenvoudig uit te breiden van 16 bits naar 32 bits en ze "uitgebreide" namen te geven met een E voorvoegsel: EAX , EBX , ECX , EDX , ESI , EDI , EBP en ESP . De onderste 16 bits van deze registers waren hetzelfde als voorheen, maar de bovenste helften van de registers waren beschikbaar voor 32-bits bewerkingen zoals ADD en CMP . De bovenste helften waren niet afzonderlijk toegankelijk zoals ze hadden gedaan met de 8-bit registers.
De processor moest afzonderlijke 16-bits en 32-bits modi hebben, omdat Intel voor veel van de bewerkingen dezelfde opcodes gebruikte: CMP AX,DX in 16-bits modus en CMP EAX,EDX in 32-bits modus had exact dezelfde opcodes ! Dit betekende dat dezelfde code NIET in beide modi kon worden uitgevoerd:
De opcode voor "Direct naar
AXverplaatsen" is0xB8, gevolgd door twee bytes van de onmiddellijke waarde:0xB8 0x12 0x34
De opcode voor "Direct naar
EAXverplaatsen" is0xB8, gevolgd door vier bytes van de onmiddellijke waarde:0xB8 0x12 0x34 0x56 0x78
De assember moet dus weten in welke modus de processor zich bevindt wanneer hij de code uitvoert, zodat hij weet dat hij het juiste aantal bytes uitzendt.
8-bit registers
De eerste vier 16-bits registers kunnen hun bovenste en onderste halve bytes direct als hun eigen registers openen:
-
AHenALzijn de hoge en lage helften van hetAXregister. -
BHenBLzijn de hoge en lage helften van hetBXregister. -
CHenCLzijn de hoge en lage helften van hetCXregister. -
DHenDLzijn de hoge en lage helften van hetDXregister.
Merk op dat dit betekent dat het wijzigen van AH of AL ook meteen AX zal veranderen! Merk ook op dat elke bewerking op een 8-bit register zijn "partner" niet kon beïnvloeden - AL verhogen zodat het overstroomde van 0xFF naar 0x00 zou AH niet veranderen.
64-bit registers hebben ook 8-bit versies die hun lagere bytes vertegenwoordigen:
-
SILvoorRSI -
DILvoorRDI -
BPLvoorRBP -
SPLvoorRSP
Hetzelfde geldt voor registers R8 tot en met R15 : hun respectieve lagere R8B worden R8B - R15B .
Segmentregisters
Segmentatie
Toen Intel de originele 8086 aan het ontwerpen was, waren er al een aantal 8-bits processors met 16-bits mogelijkheden, maar ze wilden een echte 16-bits processor produceren. Ze wilden ook iets beters en capabeler produceren dan wat er al was, dus wilden ze toegang hebben tot meer dan het maximum van 65.536 bytes geheugen, geïmpliceerd door 16-bit adresseringsregisters.
Originele segmentregisters
Dus implementeerden ze het idee van "Segmenten" - een 64 kilobyte geheugenblok geïndexeerd door de 16-bit adresregisters - die opnieuw kunnen worden gebaseerd om verschillende delen van het totale geheugen te adresseren. Om deze segmentbases te behouden, omvatten ze segmentregisters:
-
CSHet codesegmentregister.
Dit bevat het segment van de code dat momenteel wordt uitgevoerd, geïndexeerd door het implicieteIPregister (Instruction Pointer). -
DSHet gegevenssegmentregister.
Dit bevat het standaardsegment voor gegevens die door het programma worden gemanipuleerd. -
ESHet extra segmentregister.
Dit bevat een tweede gegevenssegment, voor gelijktijdige gegevensbewerkingen in het totale geheugen. -
SSHet Stack Segment-register.
Dit bevat het geheugensegment dat de huidige stapel bevat.
Segmentgrootte?
De segmentregisters kunnen elke grootte hebben, maar door ze 16 bits breed te maken, is het eenvoudig om met de andere registers te werken. De volgende vraag was: moeten de segmenten elkaar overlappen, en zo ja, hoeveel? Het antwoord op die vraag zou de totale geheugengrootte bepalen waartoe toegang kon worden verkregen.
Als er helemaal geen overlapping was, dan zou de adresruimte 32 bits zijn - 4 gigabytes - een totaal ongekende grootte op dat moment! Een meer "natuurlijke" overlapping van 8 bits zou een 24-bits adresruimte of 16 megabytes produceren. Uiteindelijk besloot Intel om nog vier adrespinnen op de processor te besparen door de adresruimte 1 megabyte te maken met een 12-bit overlap - ze vonden dit voldoende groot voor die tijd!
Meer segmentregisters!
Toen Intel de 80386 aan het ontwerpen was, zagen ze in dat het bestaande pakket van 4 segmentregisters niet genoeg was voor de complexiteit van programma's die ze wilden ondersteunen. Dus voegden ze er nog twee toe:
-
FSHet verre segmentregister -
GSHet wereldwijde segmentregister
Deze nieuwe segmentregisters hadden geen door de processor afgedwongen toepassingen: ze waren alleen beschikbaar voor wat de programmeur wilde.
Sommigen zeggen dat de namen zijn gekozen om gewoon door te gaan met het
C,D,Ethema van de bestaande set ...
64-bit registers
AMD is een processorfabrikant die het ontwerp van de 80386 van Intel in licentie had gegeven om compatibele - maar concurrerende - versies te produceren. Ze hebben interne wijzigingen aangebracht in het ontwerp om de doorvoer of andere verbeteringen aan het ontwerp te verbeteren, terwijl ze nog steeds dezelfde programma's konden uitvoeren.
Voor one-up Intel kwamen ze met 64-bit uitbreidingen van het Intel 32-bit ontwerp en produceerden ze de eerste 64-bit chip die nog steeds 32-bit x86 code kon draaien. Intel volgde het ontwerp van AMD in hun versies van de 64-bit architectuur.
Het 64-bits ontwerp heeft een aantal wijzigingen aangebracht in de registerset, maar is nog steeds achterwaarts compatibel:
- De bestaande registers voor algemene doeleinden werden uitgebreid tot 64 bits en kregen een
Rvoorvoegsel:RAX,RBX,RCX,RDX,RSI,RDI,RBPenRSP.Nogmaals, de onderste helften van deze registers waren dezelfde
Epreffix-registers als voorheen en de bovenste helften konden niet onafhankelijk worden benaderd. - 8 meer 64-bit registers werden toegevoegd, en niet genoemd maar alleen genummerd:
R8,R9,R10,R11,R12,R13,R14enR15.- De 32-bit lage helft van deze registers zijn
R8DtotR15D(D voor DWORD zoals gewoonlijk). - De laagste 16 bits van deze registers kunnen worden benaderd door een
WteR8Wmet de registernaam:R8WtotR15W.
- De 32-bit lage helft van deze registers zijn
- De laagste 8 bits van alle 16 registers zijn nu toegankelijk:
- De traditionele
AL,BL,CLenDL; - De lage bytes van de (traditioneel) aanwijzerregisters:
SIL,DIL,BPLenSPL; - En de lage bytes van de 8 nieuwe registers:
R8BtotR15B. -
AH,BH,CHenDHzijn echter niet toegankelijk in instructies die een REX-voorvoegsel gebruiken (voor 64-bits operandgrootte of voor toegang tot R8-R15, of voor toegang totSIL,DIL,BPLofSPL). Met een REX-voorvoegsel betekent het bitcode van de machinecode dat vroegerAHbetekende in plaats daarvanSPL, enzovoort. Zie tabel 3-1 van de instructiehandleiding van Intel (deel 2).
- De traditionele
Schrijven naar een 32-bits register zet altijd de bovenste 32 bits van het volledige register op nul, in tegenstelling tot schrijven naar een 8- of 16-bits register (dat samengaat met de oude waarde, wat een extra afhankelijkheid is voor uitvoering buiten de orde ).
Vlaggen registreren
Wanneer de x86 Arithmetic Logic Unit (ALU) bewerkingen uitvoert als NOT en ADD , markeert deze de resultaten van deze bewerkingen ("werd nul", "overstroomd", "werd negatief") in een speciaal 16-bits FLAGS register. 32-bits processors hebben dit geüpgraded naar 32 bits en noemden het EFLAGS , terwijl 64-bits processors dit opwaardeerden naar 64 bits en het RFLAGS .
Voorwaardecodes
Maar ongeacht de naam, het register is niet direct toegankelijk (behalve enkele instructies - zie hieronder). In plaats daarvan wordt naar bepaalde vlaggen verwezen in bepaalde instructies, zoals voorwaardelijke Jump of voorwaardelijke Set, bekend als Jcc en SETcc waarbij cc "conditiecode" betekent en verwijst naar de volgende tabel:
| Voorwaarde Code | Naam | Definitie |
|---|---|---|
E , Z | Gelijk aan nul | ZF == 1 |
NE , NZ | Niet gelijk, niet nul | ZF == 0 |
O | Overloop | OF == 1 |
NO | Geen overloop | OF == 0 |
S | Getekend | SF == 1 |
NS | Niet ondertekend | SF == 0 |
P | Pariteit | PF == 1 |
NP | Geen pariteit | PF == 0 |
| -------------- | ---- | ---------- |
C , B , NAE | Draag, onder, niet boven of gelijk | CF == 1 |
NC , NB , AE | Niet dragen, niet onder, boven of gelijk | CF == 0 |
A , NBE | Boven, niet onder of gelijk | CF == 0 en ZF == 0 |
NA , BE | Niet boven, onder of gelijk | CF == 1 of ZF == 1 |
| --------------- | ---- | ---------- |
GE , NL | Groter of gelijk, niet minder | SF == OF |
NGE , L | Niet groter of gelijk, minder | SF ! = OF |
G , NLE | Groter, niet kleiner of gelijk | ZF == 0 en SF == OF |
NG , LE | Niet groter, kleiner of gelijk | ZF == 1 of SF ! = OF |
In 16 bits is het aftrekken van 1 van 0 65,535 of -1 afhankelijk van het feit of niet-ondertekende of ondertekende rekenkunde wordt gebruikt - maar de bestemming heeft hoe dan ook 0xFFFF . Het is alleen door de voorwaardecodes te interpreteren dat de betekenis duidelijk is. Het is nog veelzeggender of 1 wordt afgetrokken van 0x8000 : in niet-ondertekende rekenkunde verandert dat slechts 32,768 in 32,767 ; terwijl het in ondertekende rekenkunde -32,768 verandert in 32,767 - een veel opmerkelijkere overstroming!
De conditiecodes zijn gegroepeerd in drie blokken in de tabel: sign-irrelevant, niet-ondertekend en ondertekend. De naamgeving in de laatste twee blokken gebruikt "Boven" en "Onder" voor niet-ondertekende en "Groter" of "Minder" voor ondertekend. Dus JB zou "Springen als hieronder" (niet ondertekend) zijn, terwijl JL "Springen als minder" (ondertekend) zou zijn.
Direct toegang tot FLAGS
De bovenstaande voorwaardecodes zijn nuttig voor het interpreteren van vooraf gedefinieerde concepten, maar de werkelijke vlagbits zijn ook direct beschikbaar met de volgende twee instructies:
-
LAHFLaadAHregister met vlaggen -
SAHFStoreAHregistreren in vlaggen
Alleen bepaalde vlaggen worden met deze instructies gekopieerd. Het hele FLAGS / EFLAGS / RFLAGS register kan worden opgeslagen of hersteld op de stapel:
-
PUSHF/POPFPush / pop 16-bitFLAGSnaar / van de stapel -
PUSHFD/POPFD32-bitsEFLAGSop / van de stapel duwen / poppen -
PUSHFQ/POPFQDruk / pop 64-bitRFLAGSop / van de stapel
Merk op dat het opslaan en herstellen van het huidige [R/E]FLAGS register automatisch wordt onderbroken.
Andere vlaggen
Naast de ALU-vlaggen die hierboven zijn beschreven, definieert het FLAGS register andere vlaggen van de systeemstatus:
-
IFde onderbrekingsvlag.
Dit wordt ingesteld met deSTIinstructie om interrupts globaal in te schakelen, en gewist met deCLIinstructie om interrupts globaal uit te schakelen. -
DFDe richtingsvlag.
Geheugen naar-geheugenbewerkingen zoalsCMPSenMOVS(te vergelijken en te bewegen tussen geheugenplaatsen) automatisch verhogen of verlagen de indexregisters kader van de instructie. DeDFvlag dicteert welke er gebeurt: indien gewist met deCLDinstructie, worden ze verhoogd; indien ingesteld met deSTDinstructie, zijn ze verlaagd. -
TFDe valvlag. Dit is een foutopsporingsvlag. Als u dit instelt, wordt de processor in de modus "één stap" gezet: nadat elke instructie is uitgevoerd, wordt de "Single Step Interrupt Handler" opgeroepen, die naar verwachting door een debugger wordt afgehandeld. Er zijn geen instructies om deze vlag in te stellen of te wissen: u moet het bit manipuleren terwijl het in het geheugen is.
80286 vlaggen
Ter ondersteuning van de nieuwe multitasking-voorzieningen in de 80286 heeft Intel extra vlaggen toegevoegd aan het FLAGS register:
-
IOPLHet I / O-bevoegdheidsniveau.
Om multitasking-code te beschermen, hadden sommige taken rechten nodig om toegang te krijgen tot I / O-poorten, terwijl andere moesten worden verhinderd om toegang te krijgen tot deze poorten. Intel introduceerde een Privilege-schaal met vier niveaus, waarbij002 het meest bevoorrecht is en112 het minst. AlsIOPLlager was dan het huidige Privilege-niveau, zou elke poging om toegang te krijgen tot I / O-poorten of interrups in of uit te schakelen in plaats daarvan een algemene beschermingsfout veroorzaken. -
NTGenestelde taakvlag.
Deze vlag werd ingesteld als een TaskCALLed een andere taak, die een context switch veroorzaakt. De ingestelde vlag gaf de processor de opdracht om terug te schakelen naar context wanneer deRETwerd uitgevoerd.
80386 vlaggen
De '386 had extra vlaggen nodig om extra functies te ondersteunen die in de processor zijn ontworpen.
-
RFDe vlag Hervatten.
De `386 voegde Debug-registers toe, die de debugger konden oproepen op verschillende hardwaretoegangen zoals lezen, schrijven of uitvoeren van een bepaalde memry-locatie. Wanneer de debug-handler echter terugkeerde om de instructie uit te voeren, zou de toegang de debug-handler onmiddellijk opnieuw oproepen! Of in ieder geval zou het zijn als het niet voor de CV-vlag was, die automatisch wordt ingesteld bij binnenkomst in de debug-handler en automatisch wordt gewist na elke instructie. Als de vlag Hervatten is ingesteld, wordt de handler Debug niet aangeroepen. -
VMDe vlag Virtual 8086.
Om zowel oudere 16-bit code als nieuwere 32-bit code te ondersteunen, kan de 80386 16-bit taken uitvoeren in een "Virtual 8086" -modus, met behulp van een Virtual 8086 executive. DeVMvlag gaf aan dat deze taak een virtuele 8086-taak was.
80486 vlaggen
Naarmate de Intel-architectuur verbeterde, werd deze sneller door technologie zoals caches en super-scalaire uitvoering. Dat moest de toegang tot het systeem optimaliseren door aannames te doen. Om die veronderstellingen te beheersen, waren meer vlaggen nodig:
-
ACAlignment Check flag De x86-architectuur heeft altijd toegang tot multi-byte geheugenwaarden op elke bytegrens, in tegenstelling tot sommige architecturen waarvoor ze qua grootte moesten worden uitgelijnd (4-byte waarden moesten op 4-byte grenzen zijn). Het was echter minder efficiënt om dit te doen, omdat meerdere geheugentoegangen nodig waren om toegang te krijgen tot niet-uitgelijnde gegevens. Als deACvlag was ingesteld, zou een niet-gekoppelde toegang een uitzondering veroorzaken in plaats van de code uit te voeren. Op die manier kon code worden verbeterd tijdens de ontwikkeling metACset, maar uitgeschakeld voor productiecode.
Pentium vlaggen
Het Pentium heeft meer ondersteuning toegevoegd voor virtualisatie, plus ondersteuning voor de CPUID instructie:
-
VIFDe virtuele onderbrekingsvlag.
Dit is een virtuele kopie van deIFvan deze taak - ongeacht of deze taak interrupts wil uitschakelen, zonder Global Interrupts daadwerkelijk te beïnvloeden. -
VIPDe vlag voor virtueel onderbreken in afwachting.
Dit geeft aan dat een interrupt vrijwel werd geblokkeerd doorVIF, dus wanneer de taak eenSTIVIF, kan er een virtuele interrupt voor worden opgeworpen. -
IDDeCPUIDvlag.
Of deze taak wel of niet deCPUIDinstructie mag uitvoeren. Een virtuele monitor kan het niet toestaan en "liegen" tegen de verzoekende taak als het de instructie uitvoert.