Delen via


x86-architectuur

De Intel x86-processor maakt gebruik van een complexe CISC-architectuur (instructiesetcomputer), wat betekent dat er een bescheiden aantal speciale registers is in plaats van grote hoeveelheden algemene registers. Het betekent ook dat complexe speciale instructies predomineren.

De x86-processor traceert zijn erfgoed ten minste zo ver terug als de 8-bits Intel 8080-processor. Veel eigenaardigheden in de x86-instructieset zijn te wijten aan de achterwaartse compatibiliteit met die processor (en met de Zilog Z-80-variant).

Microsoft Win32 maakt gebruik van de x86-processor in 32-bits flat mode. Deze documentatie richt zich alleen op de platte modus.

Registers

De x86-architectuur bestaat uit de volgende ongeprivilegieerde registers voor gehele getallen.

eax

Accumulator

ebx

Basisregister

ecx

Tellerregister

edx

Gegevensregister : kan worden gebruikt voor I/O-poorttoegang en rekenkundige functies

esi

Indexregister van de bron

edi-

Bestemmingsindexregister

ebp-

Basispointerregister

esp

Stackpointer

Alle gehele getallenregisters zijn 32 bits. Veel daarvan hebben echter 16-bit of 8-bit subregisters.

ax

Lage 16 bits van eax

bx

Lage 16 bits van ebx-

cx

Lage 16 bits van ecx-

dx

Lage 16 bits van edx-

si

Lage 16 bits van esi-

di

Lage 16 bits van edi-

Lage 16 bits van ebp-

sp

Lage 16 bits van esp

al

Lage 8 bits van eax-

ah

De hoogste 8 bits van ax

bl

Laag 8 bits van ebx

bh

Bovenste 8 bits van bx

cl

Lage 8 bits van ecx-

ch

Hoge 8 bits van cx-

dl

Lage 8 bits van edx-

dh

De hoogste 8 bits van register dx

Het werken met een subregister is alleen van invloed op het subregister en niet op de onderdelen buiten het subregister. Als u bijvoorbeeld opslaat in het ax-register, blijven de hoge 16 bits van het eax-register ongewijzigd.

Wanneer u de (Evaluate Expression)-opdracht gebruikt, moeten registers worden voorafgegaan door een "at"-teken (@). U moet bijvoorbeeld gebruiken? @ax in plaats van ? ax. Dit zorgt ervoor dat het foutopsporingsprogramma ax herkent als een register in plaats van een symbool.

De opdracht (@) is echter niet vereist in de r (registers) opdracht. Zo wordt r ax=5 altijd correct geïnterpreteerd.

Twee andere registers zijn belangrijk voor de huidige status van de processor.

eip

instructie aanwijzer

vlaggen

Vlaggen

De instructiepointer is het adres van de instructie die wordt uitgevoerd.

Het vlagregister is een verzameling single-bit vlaggen. Veel instructies wijzigen de vlaggen om het resultaat van de instructie te beschrijven. Deze vlaggen kunnen vervolgens worden getest door springinstructies met een voorwaarde. Zie x86-vlaggen voor meer informatie.

Oproepconventies

De x86-architectuur heeft verschillende aanroepende conventies. Gelukkig volgen ze allemaal dezelfde register- en functieterugkeerregels.

  • Functies moeten alle registers behouden, met uitzondering van eax-, ecxen edx-, die kunnen worden gewijzigd in een functie-aanroep en esp, die moeten worden bijgewerkt volgens de aanroepconventie.

  • De eax- register ontvangt functiewaarden als het resultaat 32 bits of kleiner is. Als het resultaat 64 bits is, wordt het resultaat opgeslagen in de edx:eax paar.

Hier volgt een lijst met aanroepende conventies die worden gebruikt in de x86-architectuur:

  • Win32 (__stdcall)

    Functieparameters worden op de stack geplaatst, van rechts naar links gepusht, en de aangeroepen functie schoont de stack.

  • Systeemeigen C++-methode-aanroep (ook wel bekend als thiscall)

    Functieparameters worden doorgegeven aan de stack, van rechts naar links gepusht, de 'this' pointer wordt doorgegeven in het ecx- register en de opgeroepene schoont de stack op.

  • COM (__stdcall voor aanroepen van C++-methoden)

    Functieparameters worden op de stack geplaatst, van rechts naar links, vervolgens wordt de 'this'-pointer op de stack geplaatst en vervolgens wordt de functie aangeroepen. De aangeroepene schoont de stapel.

  • __fastcall

    De eerste twee DWORD-of-kleinere argumenten worden doorgegeven in de registers ecx en edx. De resterende parameters worden doorgegeven aan de stack en van rechts naar links gepusht. De aangeroepene leegt de stapel.

  • __cdecl

    Functieparameters worden op de stack geplaatst, van rechts naar links gepusht, en de aanroeper maakt de stack schoon. De __cdecl oproepconventie wordt gebruikt voor alle functies met parameters voor variabele lengte.

Weergave van registers en vlaggen in Debugger

Hier volgt een voorbeeld van een registerweergave voor foutopsporing:

eax=00000000 ebx=008b6f00 ecx=01010101 edx=ffffffff esi=00000000 edi=00465000
eip=77f9d022 esp=05cffc48 ebp=05cffc54 iopl=0         nv up ei ng nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00000286

In debugging in de gebruikersmodus kunt u de iopl en de volledige laatste regel van de debugger negeren.

x86-vlaggen

In het voorgaande voorbeeld zijn de codes van twee letters aan het einde van de tweede regel vlaggen. Dit zijn enkelvoudige registers en hebben verschillende toepassingen.

De volgende tabel bevat de x86-vlaggen:

Vlagcode Vlagnaam Waarde Vlagstatus Beschrijving
van Overloop-vlag 0 1 nvov- Geen overloop - Overloop
df Richtingsvlag 0 1 updn Richting omhoog - Richting omlaag
als Interrupt-vlag 0 1 diei Onderbrekingen uitgeschakeld - Onderbrekingen ingeschakeld
sf Vlag ondertekenen 0 1 plng Positief (of nul) - Negatief
zf Nulvlag 0 1 nzzr Nonzero - Nul
af Hulpdraagvlag 0 1 naac- Geen hulp dragen - Hulp dragen
pf Pariteitsvlag 0 1 pepo Pariteit oneven - Pariteit even
cf Vlag dragen 0 1 nccy Geen dragen - Dragen
tf - Trapvlag Als tf- gelijk is aan 1, genereert de processor een STATUS_SINGLE_STEP uitzondering na de uitvoering van één instructie. Deze vlag wordt gebruikt door een foutopsporingsprogramma voor het implementeren van tracering met één stap. Het mag niet worden gebruikt door andere toepassingen.
iopl I/O-bevoegdheidsniveau I/O-bevoegdheidsniveau Dit is een twee-bits geheel getal, met waarden tussen nul en 3. Het wordt gebruikt door het besturingssysteem om de toegang tot hardware te beheren. Het mag niet worden gebruikt door toepassingen.

Wanneer registers worden weergegeven als gevolg van een opdracht in het venster met foutopsporingsopdrachten, wordt de status van de -vlag weergegeven. Als u echter een vlag wilt wijzigen met behulp van de opdracht r (Registers), moet u ernaar verwijzen door de vlagcode.

In het venster Registers van WinDbg wordt de vlagcode gebruikt om vlaggen weer te geven of te wijzigen. De vlagstatus wordt niet ondersteund.

Hier volgt een voorbeeld. In de voorgaande weergave van het register wordt de vlagstatus ng- weergegeven. Dit betekent dat de tekenvlag momenteel is ingesteld op 1. Gebruik de volgende opdracht om dit te wijzigen:

r sf=0

Hiermee stelt u de tekenvlag in op nul. Als u een andere registratieweergave uitvoert, wordt de ng-statuscode niet weergegeven. In plaats daarvan wordt de pl statuscode weergegeven.

De tekenvlag, Zero Flag en Carry Flag zijn de meestgebruikte vlaggen.

Voorwaarden

Een voorwaarde beschrijft de status van een of meer vlaggen. Alle voorwaardelijke bewerkingen op x86 worden uitgedrukt in voorwaarden.

De assemblyer gebruikt een afkorting van een of twee letters om een voorwaarde weer te geven. Een voorwaarde kan worden vertegenwoordigd door meerdere afkortingen. AE ('boven of gelijk aan') is bijvoorbeeld dezelfde voorwaarde als NB ('niet hieronder'). De volgende tabel bevat enkele algemene voorwaarden en hun betekenis.

Voorwaardenaam Vlaggen Betekenis

Z

ZF=1

Resultaat van de laatste bewerking was nul.

NZ

ZF=0

Het resultaat van de laatste bewerking was niet nul.

C

CF=1

Laatste bewerking vereist een draag- of leenbewerking. (Voor niet-ondertekende gehele getallen geeft dit de overloop aan.)

NC

CF=0

Voor de laatste bewerking was geen dragen of lenen vereist. (Voor niet-ondertekende gehele getallen geeft dit de overloop aan.)

S

SF=1

Het resultaat van de laatste bewerking heeft de hoge bitset.

NS

SF=0

Het resultaat van de laatste bewerking heeft zijn hoogste bit gewist.

O

VAN=1

Wanneer de bewerking wordt behandeld als een ondertekend geheel getal, heeft de laatste bewerking een overloop of onderloop veroorzaakt.

NEE

OF=0

Bij behandeling als gepoolde integerbewerking heeft de laatste bewerking geen overflow of underflow veroorzaakt.

Voorwaarden kunnen ook worden gebruikt om twee waarden te vergelijken. De cmp instructie vergelijkt de twee operanden en stelt vervolgens vlaggen in alsof de ene operand van de andere wordt afgetrokken. De volgende voorwaarden kunnen worden gebruikt om het resultaat van cmpwaarde1, waarde2te controleren.

Voorwaardenaam Vlaggen De betekenis na een CMP-bewerking.

E

ZF=1

waarde1 == waarde2.

NE

ZF=0

waarde1 != waarde2.

GE NL

SF=OF

waarde1>= waarde2. Waarden worden behandeld als ondertekende gehele getallen.

LE NG

ZF=1 of SF!=OF

waarde1<= waarde2. Waarden worden behandeld als ondertekende gehele getallen.

G NLE

ZF=0 en SF=OF

waarde1>waarde2. Waarden worden behandeld als ondertekende gehele getallen.

L NGE

SF!=OF

waarde1<waarde2. Waarden worden behandeld als ondertekende gehele getallen.

AE NB

CF=0

waarde1>= waarde2. Waarden worden behandeld als niet-ondertekende gehele getallen.

BE NA

CF=1 of ZF=1

waarde1<= waarde2. Waarden worden behandeld als niet-ondertekende gehele getallen.

Een NBE

CF=0 en ZF=0

waarde1>waarde2. Waarden worden behandeld als niet-ondertekende gehele getallen.

B NAE

CF=1

waarde1<waarde2. Waarden worden behandeld als niet-ondertekende gehele getallen.

Condities worden meestal gebruikt om te reageren op het resultaat van een cmp- of test-instructie. Bijvoorbeeld

cmp eax, 5
jz equal

vergelijkt de eax- register met het getal 5 door de expressie (eax - 5) te berekenen en vlaggen in te stellen op basis van het resultaat. Als het resultaat van de aftrekking nul is, wordt de vlag zr ingesteld en wordt de jz voorwaarde waar, zodat de sprong wordt genomen.

Gegevenstypen

  • byte: 8 bits

  • woord: 16 bits

  • dword: 32 bits

  • qword: 64 bits (inclusief dubbele drijvende komma)

  • tweede: 80 bits (inclusief dubbele drijvende komma)

  • oword: 128 bits

Notatie

De volgende tabel geeft de notatie aan die wordt gebruikt om de taalinstructies voor assembly's te beschrijven.

Notatie Betekenis

r, r1, r2...

Registers

m

Geheugenadres (zie het gedeelte Adresseringsmodi voor meer informatie.)

#n

Onmiddellijke constante

r/m

Registreren of geheugen

r/#n

Registreren of onmiddellijke constante

r/m/#n

Register, geheugen of onmiddellijke constante

CC-

Een voorwaardecode die wordt vermeld in de voorgaande sectie Voorwaarden.

T-

"B", "W" of "D" (byte, woord of dword)

accT-

Grootte T van de accumulator: al indien T = "B", ax indien T = "W", of eax indien T = "D"

Adresseringsmodi

Er zijn verschillende adresseringsmodi, maar ze hebben allemaal de vorm T ptr [expr], waarbij T- een bepaald gegevenstype is (zie de voorgaande sectie Gegevenstypen) en expr- een expressie is met constanten en registers.

De notatie voor de meeste modi kan zonder veel moeite worden afgeleid. Bijvoorbeeld: BYTE PTR [esi+edx*8+3] betekent 'neem de waarde van het esi--register, voeg er acht keer de waarde van het edx--register aan toe, voeg drie toe en open vervolgens de byte op het resulterende adres.'

Pipelining

De Pentium is dual-issue, wat betekent dat het tot twee acties in één kloktik kan uitvoeren. De regels voor wanneer twee acties tegelijkertijd kunnen worden uitgevoerd (bekend als koppelen) zijn echter erg ingewikkeld.

Omdat x86 een CISC-processor is, hoeft u zich geen zorgen te maken over jump delay slots.

Gesynchroniseerde geheugentoegang

Instructies voor laden, wijzigen en opslaan kunnen een lock voorvoegsel hebben, waarmee de instructie als volgt wordt aangepast:

  1. Voordat de instructie wordt uitgegeven, worden alle in behandeling zijnde geheugenbewerkingen door de CPU leeggemaakt om de coherentie te garanderen. Alle gegevens-prefetches worden geannuleerd.

  2. Tijdens het uitgeven van de instructie heeft de CPU exclusieve toegang tot de bus. Dit zorgt voor de atomiciteit van de bewerking laden/wijzigen/opslaan.

De xchg-instructie voldoet automatisch aan de vorige regels wanneer deze een waarde met geheugen uitwisselt.

Alle andere instructies worden standaard niet vergrendeld.

Sprongvoorspelling

Onvoorwaardelijke sprongen worden voorspeld te worden genomen.

Er wordt voorspeld of voorwaardelijke sprongen wel of niet zullen worden genomen, afhankelijk van of ze de laatste keer wel of niet werden genomen toen ze werden uitgevoerd. De cache voor opnamespronggeschiedenis is beperkt in grootte.

Als de CPU geen record heeft of de voorwaardelijke sprong is genomen of niet de laatste keer dat deze werd uitgevoerd, voorspelt het voorwaardelijke sprongen naar achteren zoals genomen en vooruit voorwaardelijke sprongen zoals niet genomen.

Uitlijning

De x86-processor corrigeert automatisch niet-uitgelijnde geheugentoegang, met een prestatiestraf. Er wordt geen uitzondering gegenereerd.

Een geheugentoegang wordt beschouwd als uitgelijnd als het adres een geheel veelvoud van de objectgrootte is. Alle BYTE-toegangen worden bijvoorbeeld uitgelijnd (alles is een geheel getal van 1), WORD-toegang tot even adressen wordt uitgelijnd en DWORD-adressen moeten een veelvoud van 4 zijn om te worden uitgelijnd.

Het lock-voorvoegsel mag niet worden gebruikt voor niet-uitgelijnde geheugentoegangen.

Zie ook

x64-architectuur

X86-64 Wikipedia