Intel x86 Assembly Language & Microarchitecture
Registrera grundläggande
Sök…
16-bitars register
När Intel definierade den ursprungliga 8086 var det en 16-bitars processor med en 20-bitars adressbuss (se nedan). De definierade 8 allmänna 16-bitarsregister - men gav dem specifika roller för vissa instruktioner:
-
AXAckumulatorregistret.
Många opcoder antog antingen detta register eller var snabbare om det anges. -
DXDataregistret.
Detta kombinerades ibland som de höga 16 bitarna med ett 32-bitarsvärde medAX- till exempel som ett resultat av en multiplikation. -
CXRäknaregistret.
Detta användes i ett antal looporienterade instruktioner som den implicita räknaren för dessa slingor - till exempelLOOPNE(loop om inte lika) ochREP(upprepad flyttning / jämförelse) -
BXBasregistret.
Detta kan användas för att indexera basen för en struktur i minnet - inget av ovanstående register kan användas för att direkt indexera i minnet. -
SIKällindexregistret.
Detta var det implicita källindexet i minnet för vissa rörelser och jämför operationer. -
DIDestinationsindexregistret.
Detta var det implicita destinationsindexet i minnet för vissa flytta och jämföra operationer. -
SPStack Pointer-registret.
Detta är det minst allmänna registret i uppsättningen! Det pekade på den aktuella positionen i stacken, som användes uttryckligen förPUSHochPOPoperationer, implicit förCALLochRETmed subroutines, och mycket implicit under avbrott. Som sådan var det farligt för ditt program att använda det för allt annat! -
BPBase Pointer-registret.
När subroutines kallar andra subroutines, innehåller stacken flera "stack frames".BPkan användas för att hålla den aktuella stapelramen, och sedan när en ny subroutin kallades skulle den kunna sparas på stacken, den nya stapelramen skapades och användes, och vid återgång från den inre subroutinen kunde det gamla stapelramvärdet återställas .
Anmärkningar:
De tre första registren kan inte användas för indexering i minnet.
BX,SIochDIstandardindex i det aktuella datasegmentet (se nedan).MOV AX, [BX+5] ; Point into Data Segment MOV AX, ES:[DI+5] ; Override into Extra SegmentDI, när den används i minne-till-minne-operationer somMOVSochCMPS, använder endast Extra-segmentet (se nedan). Detta kan inte åsidosättas.SPochBPanvänder stapelsegmentet (se nedan) som standard.
32-bitars register
När Intel tillverkade 80386 uppgraderade de från en 16-bitars processor till en 32-bitars. 32-bitarsbehandling innebär två saker: både data som manipulerades var 32-bitars och minnesadresserna som åtkom var 32-bitars. För att göra detta, men fortfarande förbli kompatibla med sina tidigare processorer, introducerade de helt nya lägen för processorn. Det var antingen i 16-bitarsläge eller 32-bitarsläge - men du kan åsidosätta det här läget på en instruktionsbaserad instruktion för antingen data, adressering eller båda!
Först av allt var de tvungna att definiera 32-bitars register. De gjorde detta genom att helt enkelt utöka de befintliga åtta från 16 bitar till 32 bitar och ge dem "utökade" namn med ett E prefix: EAX , EBX , ECX , EDX , ESI , EDI , EBP och ESP . De nedre 16 bitarna av dessa register var desamma som tidigare, men de övre halvorna av registren var tillgängliga för 32-bitars operationer såsom ADD och CMP . De övre halvorna var inte separat tillgängliga, som de hade gjort med 8-bitarsregistren.
Processorn måste ha separata 16-bitars- och 32-bitarslägen eftersom Intel använde samma opcoder för många av operationerna: CMP AX,DX i 16-bitarsläge och CMP EAX,EDX i 32-bitarsläge hade exakt samma opcoder ! Detta innebar att samma kod INTE kunde köras i något av lägena:
Opoden för "Flytta omedelbart till
AX" är0xB8, följt av två byte med det omedelbara värdet:0xB8 0x12 0x34
Opoden för "Flytta omedelbart till
EAX" är0xB8, följt av fyra byte med det omedelbara värdet:0xB8 0x12 0x34 0x56 0x78
Så assember måste veta vilket läge processorn är i när koden körs, så att den vet att avge rätt antal byte.
8-bitars register
De första fyra 16-bitarsregistrema kan ha sina övre och nedre halva byte åtkomst direkt som sina egna register:
-
AHochALär de höga och låga halvorna iAXregistret. -
BHochBLär de höga och låga halvorna iBXregistret. -
CHochCLär de höga och låga halvorna iCXregistret. -
DHochDLär de höga och låga halvorna iDXregistret.
Observera att detta innebär att förändring av AH eller AL omedelbart kommer att förändra AX också! Observera också att alla operationer i ett 8-bitarsregister inte kunde påverka dess "partner" - att AL ökar så att den överflödade från 0xFF till 0x00 skulle inte förändra AH .
64-bitars-register har också 8-bitarsversioner som representerar deras lägre byte:
-
SILförRSI -
DILförRDI -
BPLförRBP -
SPLförRSP
Detsamma gäller för register R8 och med R15 : deras respektive nedre R8B heter R8B - R15B .
Segmentregister
segmente~~POS=TRUNC
När Intel utformade den ursprungliga 8086 fanns det redan ett antal 8-bitars processorer som hade 16-bitars kapacitet - men de ville producera en riktig 16-bitars processor. De ville också producera något bättre och mer kapabelt än vad som redan fanns där ute, så de ville ha tillgång till mer än maximalt 65 536 byte minne implicit av 16-bitars adressregister.
Original segmentregister
Så de implementerade idén om "Segment" - ett 64 kilobyte minnesblock indexerat av 16-bitars adressregister - som kan baseras på nytt för att adressera olika områden i det totala minnet. För att hålla dessa segmentbaser inkluderade de segmentregister:
-
CSKodsegmentet register.
Detta håller segmentet av koden som för närvarande körs, indexerat av det implicitaIP(Instruction Pointer) -registret. -
DSDatasegmentregistret.
Detta håller standardsegmentet för data som manipuleras av programmet. -
ESExtra-segmentet.
Detta har ett andra datasegment för samtidig datafunktioner över hela minnet. -
SSStack-segmentregistret.
Detta håller det segment av minnet som har den aktuella stacken.
Segmentstorlek?
Segmentregistrerna kan vara av alla storlekar, men genom att göra dem 16 bitar brett gjorde det lätt att samverka med de andra registerna. Nästa fråga var: ska segmenten överlappa varandra, och i så fall hur mycket? Svaret på den frågan skulle diktera den totala minnesstorleken som kan nås.
Om det inte fanns någon överlappning alls skulle adressutrymmet vara 32 bitar - 4 gigabyte - en helt ojämn storlek vid den tiden! En mer "naturlig" överlappning av 8 bitar skulle ge ett 24-bitars adressutrymme, eller 16 megabyte. I slutändan beslutade Intel att spara ytterligare fyra adressstift på processorn genom att göra adressutrymmet 1 megabyte med en 12-bitars överlappning - de ansåg detta vara tillräckligt stort för tiden!
Fler segmentregister!
När Intel utformade 80386 insåg de att den befintliga sviten med 4 segmentregister inte var tillräckligt för komplexiteten i program som de ville att den skulle kunna stödja. Så de lägger till ytterligare två:
-
FSThe Far Segment-registret -
GSDet globala segmentregistret
Dessa nya segmentregister hade inga processorer som användes: de var bara tillgängliga för vad programmeraren ville ha.
Vissa säger att namnen valdes för att helt enkelt fortsätta
C,D,Etemat i den befintliga uppsättningen ...
64-bitars register
AMD är en processortillverkare som hade licensierat designen av 80386 från Intel för att producera kompatibla - men konkurrerande - versioner. De gjorde interna förändringar i designen för att förbättra genomströmningen eller andra förbättringar av designen, medan de fortfarande kunde köra samma program.
För en av Intel, de kom med 64-bitars tillägg till Intel 32-bitars design och producerade det första 64-bitars chip som fortfarande kunde köra 32-bitars x86-kod. Intel slutade efter AMDs design i sina versioner av 64-bitarsarkitekturen.
64-bitarsdesignen gjorde ett antal ändringar i registermängden, medan de fortfarande var bakåtkompatibla:
- De befintliga allmänna registren utvidgades till 64 bitar och namngavs med ett
Rprefix:RAX,RBX,RCX,RDX,RSI,RDI,RBPochRSP.Återigen var de nedre halvorna av dessa register samma
Ereferensregister som tidigare, och de övre halvorna kunde inte nås oberoende. - Ytterligare 8 64-bitars register lades till och namngavs utan bara numrerades:
R8,R9,R10,R11,R12,R13,R14ochR15.- Den 32-bitars låga halvan av dessa register är
R8DtillR15D(D för DWORD som vanligt). - De lägsta 16 bitarna av dessa register kan nås genom att eftertrycka ett
Wtill registernamnet:R8WtillR15W.
- Den 32-bitars låga halvan av dessa register är
- De lägsta 8 bitarna av alla 16 register kan nu nås:
- Den traditionella
AL,BL,CLochDL; - De låga bytena i (traditionellt) pekarregistret:
SIL,DIL,BPLochSPL; - Och de låga bytena från de 8 nya registren:
R8BtillR15B. -
AH,BH,CHochDHär emellertid otillgängliga i instruktioner som använder ett REX-prefix (för 64 bit operandstorlek, eller för att komma åt R8-R15, eller för att få åtkomst tillSIL,DIL,BPLellerSPL). Med ett REX-prefix betyder maskinkodets bitmönster som brukade betydaAHiställetSPL, och så vidare. Se tabell 3-1 i Intels instruktionshandbok (volym 2).
- Den traditionella
Att skriva till ett 32-bitars register nollar alltid de övre 32 bitarna i fullbreddregistret, till skillnad från att skriva till ett 8 eller 16-bitarsregister (som smälter samman med det gamla värdet, vilket är ett extra beroende för exekvering av ordningen ).
Flaggor register
När x86 Arithmetic Logic Unit (ALU) utför operationer som NOT och ADD , flaggas resultaten av dessa operationer ("blev noll", "överflöde", "blev negativ") i ett speciellt 16-bitars FLAGS register. 32-bitars processorer uppgraderade detta till 32 bitar och kallade det EFLAGS , medan 64-bitars processorer uppgraderade detta till 64 bitar och kallade det RFLAGS .
Konditionskoder
Men oavsett namn är registret inte direkt tillgängligt (förutom några instruktioner - se nedan). I stället hänvisas till enskilda flaggor i vissa instruktioner, till exempel villkorad hopp eller villkorlig uppsättning, känd som Jcc och SETcc där cc betyder "villkorskod" och refererar till följande tabell:
| Tillståndskod | namn | Definition |
|---|---|---|
E , Z | Lika, noll | ZF == 1 |
NE , NZ | Inte lika, inte noll | ZF == 0 |
O | Svämma över | OF == 1 |
NO | Inget överflöde | OF == 0 |
S | Signerad | SF == 1 |
NS | Inte undertecknad | SF == 0 |
P | Paritet | PF == 1 |
NP | Ingen paritet | PF == 0 |
| -------------- | ---- | ---------- |
C , B , NAE | Bär nedanför, inte över eller lika | CF == 1 |
NC , NB , AE | Ingen bärning, inte under, ovan eller lika | CF == 0 |
A , NBE | Ovan, inte under eller lika | CF == 0 och ZF == 0 |
NA , BE | Inte ovan, under eller lika | CF == 1 eller ZF == 1 |
| --------------- | ---- | ---------- |
GE , NL | Större eller lika, inte mindre | SF == OF |
NGE , L | Inte större eller lika, mindre | SF ! = OF |
G , NLE | Större, inte mindre eller lika | ZF == 0 och SF == OF |
NG , LE | Inte större, mindre eller lika | ZF == 1 eller SF ! = OF |
I 16 bitar är subtraktion av 1 från 0 antingen 65,535 eller -1 beroende på om osignerad eller signerad aritmetik används - men destinationen har 0xFFFF alla fall. Det är bara genom att tolka villkorskoderna att betydelsen är tydlig. Det är ännu mer uppenbart om 1 dras från 0x8000 : i osignerad aritmetik förändras det bara 32,768 till 32,767 ; medan det i signerad aritmetik förändras -32,768 till 32,767 - ett mycket mer anmärkningsvärt överflöde!
Betingelsekoderna grupperas i tre block i tabellen: tecken-irrelevant, osignerad och signerad. Namngivningen inuti de två senare blocken använder "Ovan" och "Nedan" för osignerade och "Större" eller "Mindre" för signerade. Så JB skulle vara "Jump if below" (osignerad), medan JL skulle vara "Jump if Less" (signerad).
Åtkomst till FLAGS direkt
Ovanstående villkorskoder är användbara för att tolka fördefinierade koncept, men de faktiska flaggbitarna finns också tillgängliga direkt med följande två instruktioner:
-
LAHFLaddaAHregister med flaggor -
SAHFStoreAHregister i flaggor
Endast vissa flaggor kopieras över med dessa instruktioner. Hela FLAGS / EFLAGS / RFLAGS registret kan sparas eller återställas på bunten:
-
PUSHF/POPFTryck / pop 16-bitarsFLAGStill / från stacken -
PUSHFD/POPFDTryck / pop 32-bitarsEFLAGStill / från stacken -
PUSHFQ/POPFQTryck / pop 64-bitarsRFLAGStill / från stacken
Observera att avbrott sparar och återställer det nuvarande [R/E]FLAGS registret automatiskt.
Andra flaggor
Förutom de ovan FLAGS ALU-flaggorna definierar FLAGS registret andra systemstatliga flaggor:
-
IFAvbrytande flaggan.
Detta ställs in medSTIinstruktionen för att globalt möjliggöra avbrott och rensas medCLIinstruktionen för att globalt avaktivera avbrott. -
DFRiktningsflaggan.
Minne-till-minne-operationer somCMPSochMOVS(för att jämföra och flytta mellan minnesplatser) ökar eller minskar indexregistrerna automatiskt som en del av instruktionen.DFflaggan dikterar vilken som händer: om den rensas medCLDinstruktionen ökas de; om de ställs in medSTDinstruktionen, dekrementeras. -
TFTrap Flag. Detta är en felsökningsflagg. Om du ställer in den kommer processorn i "enkelsteg" -läge: efter att varje instruktion har utförts kommer den att ringa "Single Step Interrupt Handler", som förväntas hanteras av en felsökare. Det finns inga instruktioner för att ställa in eller rensa denna flagga: du måste manipulera biten medan den är i minnet.
80286 Flaggor
För att stödja de nya multitasking-anläggningarna i 80286 har Intel lagt till FLAGS flaggor till FLAGS registret:
-
IOPLI / O-privilegienivå.
För att skydda multitaskingskod behövde vissa uppgifter privilegier för att få åtkomst till I / O-portar, medan andra måste stoppas från att komma åt dem. Intel introducerade en fyra nivåer Privilege skala, där002 var mest privilegierade och112 som minst. OmIOPLvar lägre än den nuvarande behörighetsnivån skulle alla försök att komma åt I / O-portar, eller aktivera eller inaktivera interrups, i stället orsaka ett allmänt skyddsfel. -
NTNested Task flagga.
Denna flagga ställdes in om en uppgiftCALLredigerade en annan uppgift, vilket orsakade en kontextomkopplare. Den inställda flaggan berättade för processorn att göra en kontextomkopplare närRETkördes.
80386 Flaggor
386 behövde extra flaggor för att stödja extra funktioner designade i processorn.
-
RFResume Flag.
386 tillagda felsökningsregister, vilket kan påkalla felsökaren på olika hårdvarutillgångar som att läsa, skriva eller köra en viss memerplats. Men när felsökningshanteraren återvände för att utföra instruktionen skulle åtkomsten omedelbart återkalla felsökningshanteraren! Eller åtminstone skulle det göra om det inte var för återupptagningsflaggan, som automatiskt ställs in vid inträde i felsökningshanteraren och rensas automatiskt efter varje instruktion. Om Resume Flag är inställt startas inte felsökningshanteraren. -
VMDen virtuella 8086-flaggan.
För att stödja äldre 16-bitars kod såväl som nyare 32-bitars kod kan 80386 köra 16-bitarsuppgifter i ett "Virtual 8086" -läge med hjälp av en Virtual 8086-verkställande.VMflaggan indikerade att denna uppgift var en virtuell 8086-uppgift.
80486 Flaggor
När Intel-arkitekturen förbättrades blev det snabbare genom teknik som cachar och superskalär exekvering. Det måste optimera åtkomsten till systemet genom att göra antaganden. För att kontrollera dessa antaganden behövdes fler flaggor:
-
ACAlignment Kontrollera flaggan x86-arkitekturen kan alltid komma åt minnesvärden för flera byte på valfri byte-gräns, till skillnad från vissa arkitekturer som krävde att de skulle vara i linje med storleken (4-byte-värden måste vara på 4-byte-gränser). Men det var mindre effektivt att göra det, eftersom flera minnesåtkomst behövdes för att få åtkomst till ojusterad data. OmACflaggan var inställd, skulle en ojusterad åtkomst höja ett undantag snarare än att köra koden. På så sätt kan kod förbättras under utveckling medACset, men stängs av för produktionskod.
Pentium-flaggor
Pentium har lagt till mer stöd för virtualisering, plus stöd för CPUID instruktionen:
-
VIFThe Virtual Interrupt Flag.
Detta är en virtuell kopia av denna uppgiftsIF- oavsett om denna uppgift vill inaktivera avbrott utan att påverka Globala avbrott eller inte. -
VIPDen flagga somVIPvirtuellt avbrott.
Detta indikerar att ett avbrott nästan blockerades avVIF, så när uppgiften gör enSTIett virtuellt avbrott höjas för det. -
IDCPUIDtillåtna flaggan.
Huruvida detta uppdrag ska utföraCPUIDinstruktionen eller inte. En virtuell bildskärm kan avvisa den och "ljuga" till den begärande uppgiften om den kör instruktionen.