Intel x86 Assembly Language & Microarchitecture
Controle stroom
Zoeken…
Onvoorwaardelijke sprongen
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
Relatief in de buurt van sprongen
jmp a_label is:
- in de buurt
Het specificeert alleen het offset-gedeelte van het logische adres van bestemming. Het segment wordt verondersteldCS. - familielid
De semantische instructie is jump rel bytes vooruit 1 vanaf het volgende instructieadres ofIP = IP + rel.
De instructie is gecodeerd als EB <rel8> of EB <rel16/32> , waarbij de assembler de meest geschikte vorm EB <rel16/32> , meestal de voorkeur aan een kortere.
Per assembler is overschrijven mogelijk, bijvoorbeeld met NASM jmp SHORT a_label , jmp WORD a_label en jmp DWORD a_label genereren de drie mogelijke formulieren.
Absoluut indirect in de buurt van sprongen
jmp bx en jmp WORD [aPointer] zijn:
- in de buurt
Ze specificeren alleen het offset-gedeelte van het logische adres van bestemming. Het segment wordt verondersteldCS. - absoluut indirect
De semantiek van de instructies is springen naar het adres in reg of mem ofIP = reg,IP = mem.
De instructie is gecodeerd als FF /4 , voor indirect geheugen wordt de grootte van de operand bepaald zoals voor elke andere geheugentoegang.
Absoluut ver springt
jmp 7c0h:0000h is:
ver
Het specificeert beide delen van het logische adres: het segment en de offset.absoluut De semantiek van de instructie is springen naar het adressegment: offset of
CS = segment, IP = offset.
De instructie is gecodeerd als EA <imm32/48> afhankelijk van de EA <imm32/48> .
Het is mogelijk om te kiezen tussen de twee vormen in sommige assembler, bijvoorbeeld met NASM jmp 7c0h: WORD 0000h en jmp 7c0h: DWORD 0000h genereert de eerste en tweede vorm.
Absoluut indirect verre sprongen
jmp FAR WORD [aFarPointer] is:
ver Het specificeert beide delen van het logische adres: het segment en de offset.
Absoluut indirect De semantiek van de instructie is springen naar het segment: offset opgeslagen in mem 2 of
CS = mem[23:16/32], IP = [15/31:0].
De instructie is gecodeerd als FF /5 , de grootte van de operand kan een controller zijn met de maataanduidingen.
In NASM, een beetje niet intuïtief, zijn ze jmp FAR WORD [aFarPointer] voor een 16:16 operand en jmp FAR DWORD [aFarPointer] voor een 16:32 operand.
Ontbrekende sprongen
bijna absoluut
Kan worden nagebootst met een bijna indirecte sprong.mov bx, target ;BX = absolute address of target jmp bxver familielid
Sowieso niet logisch of te beperkt.
1 Twee complement wordt gebruikt om een ondertekende offset te specificeren en dus achteruit te springen.
2 Dat kan een seg16 zijn: off16 of een seg16: off32 , in de maten 16:16 en 16:32 .
Testomstandigheden
Om een voorwaardelijke sprong te gebruiken, moet een voorwaarde worden getest. Het testen van een voorwaarde verwijst hier alleen naar het controleren van de vlaggen, het daadwerkelijke springen wordt beschreven onder Voorwaardelijke sprongen .
x86 test voorwaarden door te vertrouwen op het EFLAGS-register, dat een set vlaggen bevat die elke instructie mogelijk kan instellen.
Rekenkundige instructies, zoals sub of add , en logische instructies, zoals xor of and , uiteraard "stel de vlaggen in". Dit betekent dat de vlaggen CF , OF , SF , ZF , AF , PF door die instructies zijn gewijzigd. Elke instructie is toegestaan om de vlaggen te wijzigen, bijvoorbeeld, cmpxchg wijzigt de ZF .
Controleer altijd de instructiereferentie om te weten welke vlaggen door een specifieke instructie zijn gewijzigd.
x86 heeft een reeks voorwaardelijke sprongen , waarnaar eerder wordt verwezen, die springen als en alleen als sommige vlaggen zijn ingesteld of sommige duidelijk zijn of beide.
vlaggen
Rekenkundige en logische bewerkingen zijn erg handig bij het instellen van de vlaggen. Bijvoorbeeld, na een sub eax, ebx , die nu niet-ondertekende waarden bevat, hebben we:
| Vlag | Wanneer ingesteld | Wanneer duidelijk |
|---|---|---|
| ZF | Wanneer het resultaat nul is. EAX - EBX = 0 ⇒ EAX = EBX | Wanneer het resultaat niet nul is. EAX - EBX ≠ 0 ⇒ EAX ≠ EBX |
| CF | Wanneer het resultaat nodig was voor de MSb. EAX - EBX <0 ⇒ EAX <EBX | Wanneer het resultaat niet nodig was voor de MSb. EAX - EBX ≮ 0 ⇒ EAX ≮ EBX |
| SF | Wanneer resultaat MSb is ingesteld. | Wanneer resultaat MSb niet is ingesteld. |
| VAN | Wanneer een ondertekende overloop plaatsvond. | Wanneer een ondertekende overloop niet heeft plaatsgevonden. |
| PF | Als het aantal bits dat is ingesteld als minst significante byte van het resultaat even is. | Als het aantal bits dat is ingesteld als minst significante byte van het resultaat oneven is. |
| AF | Toen het lagere BCD-cijfer een carry genereerde. Het is bit 4 carry. | Wanneer de onderste BCD cijfer heeft een carry genereren. Het is bit 4 carry. |
Niet-destructieve tests
De sub en and instructies wijzigen hun bestemmingsoperand en vereisen twee extra exemplaren (opslaan en herstellen) om de bestemming ongewijzigd te houden.
Om een niet-destructieve test uit te voeren, zijn er de instructies cmp en test . Ze zijn identiek aan hun destructieve tegenhanger, behalve dat het resultaat van de operatie wordt verwijderd en alleen de vlaggen worden opgeslagen .
| vernietigend | Niet destructief |
|---|---|
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
Ondertekende en niet-ondertekende tests
De CPU geeft geen speciale betekenis aan het registreren van waarden 1 , teken is een programmeurconstructie. Er is geen verschil bij het testen van ondertekende en niet-ondertekende waarden. De processor berekent voldoende vlaggen om de gebruikelijke rekenkundige relaties (gelijk, kleiner dan, groter dan, enz.) Te testen, beide als de operanden als ondertekend en niet-ondertekend moeten worden beschouwd.
1 Hoewel het enkele instructies heeft die alleen zinvol zijn met specifieke formaten, zoals het complement van twee. Dit is om de code efficiënter te maken, omdat het implementeren van het algoritme in software veel code zou vereisen.
Voorwaardelijke sprongen
Op basis van de status van de vlaggen kan de CPU een sprong uitvoeren of negeren. Een instructie die een sprong uitvoert op basis van de vlaggen, valt onder de generieke naam Jcc - Jump on Condition Code 1 .
Synoniemen en terminologie
Om de leesbaarheid van de assemblagecode te verbeteren, heeft Intel verschillende synoniemen voor dezelfde staatscode gedefinieerd. jae , jnb en jnc zijn bijvoorbeeld allemaal dezelfde voorwaardecode CF = 0 .
Hoewel de naam van de instructie een zeer sterke hint kan geven over wanneer deze moet worden gebruikt of niet, is de enige zinvolle benadering om de vlaggen te herkennen die moeten worden getest en vervolgens de juiste instructies te kiezen.
Intel gaf echter de instructies namen die volkomen logisch zijn wanneer ze worden gebruikt na een cmp instructie. Voor de toepassing van deze discussie, cmp zal worden uitgegaan van de vlaggen te hebben ingesteld voordat een voorwaardelijke sprong.
Gelijkheid
De operand is gelijk als ZF is ingesteld, ze verschillen anders. Om gelijkheid te testen hebben we ZF = 1 nodig .
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)
| Instructie | vlaggen |
|---|---|
je , jz | ZF = 1 |
jne , jnz | ZF = 0 |
Groter dan
Voor niet-ondertekende operanden is de bestemming groter dan de bron als carry niet nodig was, dat wil zeggen, als CF = 0 . Wanneer CF = 0 is het mogelijk dat de operanden gelijk waren, het testen van ZF zal ondubbelzinnig zijn.
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)
| Instructie | vlaggen |
|---|---|
jae , jnc , jnb | CF = 0 |
ja , jnbe | CF = 0, ZF = 0 |
Voor ondertekende operanden moeten we controleren of SF = 0 , tenzij er een ondertekende overloop is geweest, in welk geval de resulterende SF wordt omgekeerd. Omdat OF = 0 als er geen ondertekende overloop heeft plaatsgevonden en anders 1, moeten we controleren of SF = OF .
ZF kan worden gebruikt om een strikte / niet-strikte test uit te voeren.
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)
| Instructie | vlaggen |
|---|---|
jge , jnl | SF = OF |
jg , jnle | SF = OF, ZF = 0 |
Minder dan
Deze gebruiken de omgekeerde voorwaarden van hierboven.
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)
| Instructie | vlaggen |
|---|---|
jbe , jna | CF = 1 of ZF = 1 |
jb , jc , jnae | CF = 1 |
jle , jng | SF! = OF of ZF = 1 |
jl , jnge | SF! = OF |
Specifieke vlaggen
Elke vlag kan afzonderlijk worden getest met j<flag_name> waarbij vlagnaam niet de volgende F bevat (bijvoorbeeld CF → C , PF → P ).
De resterende codes die niet eerder zijn behandeld, zijn:
| Instructie | Vlag |
|---|---|
js | SF = 1 |
jns | SF = 0 |
jo | OF = 1 |
jno | OF = 0 |
jp , jpe (e = even) | PF = 1 |
jnp , jpo (o = oneven) | PF = 0 |
Nog een voorwaardelijke sprong (extra)
Een speciale x86 voorwaardelijke sprong test de vlag niet. In plaats daarvan test het de waarde van cx of ecx register (gebaseerd op de huidige CPU-adresmodus die 16 of 32 bit is), en wordt de sprong uitgevoerd wanneer het register nul bevat.
Deze gebruiksaanwijzing is bestemd voor de validatie van teller register ( cx/ecx ) vooruit rep -achtige instructies of vooruit loop loops.
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)
| Instructie | Registreren (geen vlag) |
|---|---|
jcxz , jecxz | cx = 0 (16b-modus) |
jcxz , jecxz | ecx = 0 (32b-modus) |
1 Of zoiets.
Test rekenkundige relaties
Niet-ondertekende gehele getallen
Groter dan
cmp eax, ebx
ja a_label
Groter dan of gelijk aan
cmp eax, ebx
jae a_label
Minder dan
cmp eax, ebx
jb a_label
Minder dan of gelijk
cmp eax, ebx
jbe a_label
Gelijk
cmp eax, ebx
je a_label
Niet gelijk
cmp eax, ebx
jne a_label
Getekende gehele getallen
Groter dan
cmp eax, ebx
jg a_label
Groter dan of gelijk aan
cmp eax, ebx
jge a_label
Minder dan
cmp eax, ebx
jl a_label
Minder dan of gelijk
cmp eax, ebx
jle a_label
Gelijk
cmp eax, ebx
je a_label
Niet gelijk
cmp eax, ebx
jne a_label
a_label
In bovenstaande voorbeelden is het a_label doelbestemming voor CPU wanneer de geteste voorwaarde "waar" is. Wanneer de geteste voorwaarde "onwaar" is, gaat de CPU verder met de volgende instructie na de voorwaardelijke sprong.
Synoniemen
Er zijn instructiesynoniemen die kunnen worden gebruikt om de leesbaarheid van de code te verbeteren.
ja en jnbe (Springen niet lager of gelijk) zijn bijvoorbeeld dezelfde instructie.
Ondertekende niet-ondertekende begeleidende codes
| Operatie | ongetekend | Getekend |
|---|---|---|
| > | ja | jg |
| > = | jae | jge |
| < | jb | jl |
| <= | jbe | jle |
| = | je | je |
| ≠,! =, <> | jne | jne |