Intel x86 Assembly Language & Microarchitecture
Styrningsflöde
Sök…
Oförutsedda hopp
jmp a_label ;Jump to a_label
jmp bx ;Jump to address in BX
jmp WORD [aPointer] ;Jump to address in aPointer
jmp 7c0h:0000h ;Jump to segment 7c0h and offset 0000h
jmp FAR WORD [aFarPointer] ;Jump to segment:offset in aFarPointer
Relativt nära hopp
jmp a_label är:
- nära
Den anger bara förskjutningsdelen av destinationens logiska adress . Segmentet antas varaCS. - relativ
Instruktionen semantisk är jump rel bytes framåt 1 från nästa instruktionsadress ellerIP = IP + rel.
Instruktionen är kodad som antingen EB <rel8> eller EB <rel16/32> , varvid monteraren tar upp den lämpligaste formen, föredrar vanligtvis en kortare.
Per montering av åsidosättande är möjlig, till exempel med NASM jmp SHORT a_label , jmp WORD a_label och jmp DWORD a_label genererar de tre möjliga formerna.
Absolut indirekt nära hopp
jmp bx och jmp WORD [aPointer] är:
- nära
De anger bara förskjutningsdelen av destinationens logiska adress. Segmentet antas varaCS. - absolut indirekt
Instruktionens semantiska är att hoppa till adressen i reg eller mem ellerIP = reg,IP = mem.
Instruktionen är kodad som FF /4 , för indirekt minne bestäms operandens storlek som för alla andra minnesåtkomst.
Absolut långa hopp
jmp 7c0h:0000h är:
långt
Den anger båda delarna av den logiska adressen: segmentet och offset.absolut Instruktionens semantiska är hopp till adresssegmentet: offset eller
CS = segment, IP = offset.
Instruktionen är kodad som EA <imm32/48> beroende på kodstorlek.
Det är möjligt att välja mellan de två formerna i vissa monterare, till exempel med NASM jmp 7c0h: WORD 0000h och jmp 7c0h: DWORD 0000h genererar den första och den andra formen.
Absolut indirekta långa hopp
jmp FAR WORD [aFarPointer] är:
far Det specificerar båda delarna av den logiska adressen: segmentet och offset.
Absolut indirekt Instruktionens semantiska hoppar till segmentet: offset lagrat i mem 2 eller
CS = mem[23:16/32], IP = [15/31:0].
Instruktionen är kodad som FF /5 , storleken på operand kan styras med storleksspecifikationerna.
I NASM, lite inte intuitivt, är de jmp FAR WORD [aFarPointer] för en 16:16 operand och jmp FAR DWORD [aFarPointer] för en 16:32 operand.
Saknade hopp
nära absolut
Kan emuleras med ett nära indirekt hopp.mov bx, target ;BX = absolute address of target jmp bxlångt relativ
Inte vettigt eller för smalt att använda ändå.
1 Två komplement används för att specificera en signerad offset och därmed hoppa bakåt.
2 Vilket kan vara en seg16: off16 eller en seg16: off32 , i storlekarna 16:16 och 16:32 .
Testförhållanden
För att använda ett villkorat hopp måste ett tillstånd testas. Att testa ett tillstånd här avser bara handlingen för att kontrollera flaggorna, den faktiska hoppningen beskrivs under Villkorade hopp .
x86 testar villkor genom att förlita sig på EFLAGS-registret, som innehåller en uppsättning flaggor som varje instruktion potentiellt kan ställa in.
Aritmetiska instruktioner, som sub eller add , och logiska instruktioner, som xor eller and , uppenbarligen "ställa in flaggorna". Detta innebär att flaggorna CF , OF , SF , ZF , AF , PF modifieras av dessa instruktioner. Alla instruktioner tillåts ändra flaggorna, till exempel cmpxchg modifierar ZF .
Kontrollera alltid instruktionsreferensen för att veta vilka flaggor som modifieras av en specifik instruktion.
x86 har en uppsättning villkorade hopp , som tidigare nämnts, som hoppar om och bara om vissa flaggor är inställda eller vissa är tydliga eller båda.
flaggor
Aritmetiska och logiska operationer är mycket användbara för att ställa in flaggorna. Till exempel efter en sub eax, ebx , för att nu inneha osignerade värden, har vi:
| Flagga | När inställd | När det är klart |
|---|---|---|
| ZF | När resultatet är noll. EAX - EBX = 0 ⇒ EAX = EBX | När resultatet inte är noll. EAX - EBX ≠ 0 ⇒ EAX ≠ EBX |
| CF | När resultatet behövde bäras för MSb. EAX - EBX <0 ⇒ EAX <EBX | När resultatet inte behövde bäras för MSb. EAX - EBX ≮ 0 ⇒ EAX ≮ EBX |
| SF | När resultat MSb är inställt. | När resultat MSb inte är inställt. |
| AV | När ett signerat överflöd inträffade. | När ett signerat överflöde inte inträffade. |
| PF | När antalet bitar som ställts in i minst betydande byte av resultat är jämnt. | När antalet bitar som ställts in i minst signifikant byte av resultat är udda. |
| AF | När den lägre BCD-siffran genererade en bär. Det är bit 4 bär. | När den lägre BCD-siffran inte genererade en bär. Det är bit 4 bär. |
Icke-destruktiva tester
Den sub och and instruktioner ändra sin destination operand och skulle kräva två extra kopior (spara och återställa) för att hålla destination omodifierad.
För att utföra ett icke-destruktivt test finns instruktionerna cmp och test . De är identiska med deras destruktiva motsvarighet förutom att resultatet av operationen kastas, och endast flaggorna sparas .
| Destruktiv | Ej förstörande |
|---|---|
sub | cmp |
and | test |
test eax, eax ;and eax, eax
;ZF = 1 iff EAX is zero
test eax, 03h ;and eax, 03h
;ZF = 1 if both bit[1:0] are clear
;ZF = 0 if at least one of bit[1:0] is set
cmp eax, 241d ;sub eax, 241d
;ZF = 1 iff EAX is 241
;CF = 1 iff EAX < 241
Undertecknade och osignerade tester
CPU ger ingen speciell betydelse för att registrera värden 1 , tecken är en programmerare konstruktion. Det är ingen skillnad när du testar signerade och osignerade värden. Processorn beräknar tillräckligt med flaggor för att testa de vanliga aritmetiska förhållandena (lika, mindre än, större än, etc.) båda om operanderna skulle betraktas som signerade och osignerade.
1 Även om det har några instruktioner som är meningsfulla endast med specifika format, som två komplement. Detta är för att effektivisera koden eftersom implementering av algoritmen i programvara kräver mycket kod.
Villkorade hopp
Baserat på flaggernas tillstånd kan CPU antingen köra eller ignorera ett hopp. En instruktion som utför ett hopp baserat på flaggorna faller under det generiska namnet Jcc - Jump on Condition Code 1 .
Synonymer och terminologi
För att förbättra läsbarheten för monteringskoden definierade Intel flera synonymer för samma tillståndskod. Till exempel jae , jnb och jnc är alla samma tillståndskod CF = 0 .
Även om instruktionsnamnet kan ge ett mycket starkt tips om när du ska använda det eller inte, är det enda meningsfulla tillvägagångssättet att känna igen flaggorna som måste testas och sedan välja instruktionerna på lämpligt sätt.
Intel gav dock instruktionerna namn som är vettigt när de används efter en cmp instruktion. För denna diskussions cmp antas cmp att ha ställt flaggorna före ett villkorat hopp.
Jämlikhet
Operandarna är lika om ZF har ställts in, de skiljer sig annorlunda ut. För att testa för jämlikhet behöver vi ZF = 1 .
je a_label ;Jump if operands are equal
jz a_label ;Jump if zero (Synonym)
jne a_label ;Jump if operands are NOT equal
jnz a_label ;Jump if not zero (Synonym)
| Instruktion | flaggor |
|---|---|
je , jz | ZF = 1 |
jne , jnz | ZF = 0 |
Större än
För osignerade operander är destinationen större än källan om transporter inte behövdes, det vill säga om CF = 0 . När CF = 0 är det möjligt att operanderna var lika kommer testning av ZF att utvetydiga.
jae a_label ;Jump if above or equal (>=)
jnc a_label ;Jump if not carry (Synonym)
jnb a_label ;Jump if not below (Synonym)
ja a_label ;Jump if above (>)
jnbe a_label ;Jump if not below and not equal (Synonym)
| Instruktion | flaggor |
|---|---|
jae , jnc , jnb | CF = 0 |
ja , jnbe | CF = 0, ZF = 0 |
För signerade operander måste vi kontrollera att SF = 0 , såvida det inte har skett ett signerat överflöde, i vilket fall den resulterande SF är omvänd. Eftersom OF = 0 om inget signerat överflöde inträffade och 1 annars, måste vi kontrollera att SF = OF .
ZF kan användas för att genomföra ett strikt / icke strikt test.
jge a_label ;Jump if greater or equal (>=)
jnl a_label ;Jump if not less (Synonym)
jg a_label ;Jump if greater (>)
jnle a_label ;Jump if not less and not equal (Synonym)
| Instruktion | flaggor |
|---|---|
jge , jnl | SF = OF |
jg , jnle | SF = OF, ZF = 0 |
Mindre än
Dessa använder ovanstående omvända förhållanden.
jbe a_label ;Jump if below or equal (<=)
jna a_label ;Jump if not above (Synonym)
jb a_label ;Jump if below (<)
jc a_label ;Jump if carry (Synonym)
jnae a_label ;Jump if not above and not equal (Synonym)
;SIGNED
jle a_label ;Jump if less or equal (<=)
jng a_label ;Jump if not greater (Synonym)
jl a_label ;Jump if less (<)
jnge a_label ;Jump if not greater and not equal (Synonym)
| Instruktion | flaggor |
|---|---|
jbe , jna | CF = 1 eller ZF = 1 |
jb , jc , jnae | CF = 1 |
jle , jng | SF! = OF eller ZF = 1 |
jl , jnge | SF! = OF |
Specifika flaggor
Varje flagga kan testas individuellt med j<flag_name> där flaggnamn inte innehåller släpet F (till exempel CF → C , PF → P ).
De återstående koderna som inte täckts tidigare är:
| Instruktion | Flagga |
|---|---|
js | SF = 1 |
jns | SF = 0 |
jo | OF = 1 |
jno | OF = 0 |
jp , jpe (e = jämn) | PF = 1 |
jnp , jpo (o = udda) | PF = 0 |
Ytterligare ett villkorat hopp (extra ett)
Ett speciellt villkorat hopp med x86 testar inte flaggan. Istället testar det värdet för cx eller ecx register (baserat på det aktuella CPU-adressläget är 16 eller 32 bitar), och hoppet utförs när registret innehåller noll.
Denna instruktion var avsedd för validering av räknarregister ( cx/ecx ) framåt av rep -liknande instruktioner, eller före loop slingor.
jcxz a_label ; jump if cx (16b mode) or ecx (32b mode) is zero
jecxz a_label ; synonym of jcxz (recommended in source code for 32b target)
| Instruktion | Registrera (inte flagga) |
|---|---|
jcxz , jecxz | cx = 0 (16b-läge) |
jcxz , jecxz | ecx = 0 (32b-läge) |
1 Eller något liknande.
Test aritmetiska relationer
Osignerade heltal
Större än
cmp eax, ebx
ja a_label
Större än eller lika med
cmp eax, ebx
jae a_label
Mindre än
cmp eax, ebx
jb a_label
Mindre än eller lika
cmp eax, ebx
jbe a_label
Likvärdig
cmp eax, ebx
je a_label
Inte jämnlikt
cmp eax, ebx
jne a_label
Signerade heltal
Större än
cmp eax, ebx
jg a_label
Större än eller lika med
cmp eax, ebx
jge a_label
Mindre än
cmp eax, ebx
jl a_label
Mindre än eller lika
cmp eax, ebx
jle a_label
Likvärdig
cmp eax, ebx
je a_label
Inte jämnlikt
cmp eax, ebx
jne a_label
a_label
I exemplen ovan är a_label för CPU när det testade tillståndet är "sant". När testat tillstånd är "falskt" fortsätter CPU: n vid nästa instruktion efter det villkorade hoppet.
synonymer
Det finns instruktionssynonymer som kan användas för att förbättra kodens läsbarhet.
Till exempel ja och jnbe (Hoppa icke under eller lika) är samma instruktion.
Signerade icke signerade följeslagarkoder
| Drift | Osignerad | Signerad |
|---|---|---|
| > | ja | jg |
| > = | jae | jge |
| < | jb | jl |
| <= | jbe | jle |
| = | je | je |
| ≠,! =, <> | jne | jne |