Ik begrijp de JG/JNLE/JL/JNGE
instructies, die na CMP komen.
Als ik bijvoorbeeld heb:
CMP al,dl
jg label1
wanneer al=101; dl =200
.
Over wat we de jg
vragen? Staat het op al>dl
? of al-dl>0
?
Dezelfde prolbeem in de volgende code:
test al,dl
jg label1
Ik begrijp niet wat we vergelijken, en over wat we de “jg
” vragen.
Met andere woorden, ik begrijp het niet wanneer we naar Label1 zouden springen, en wanneer we dat niet zouden doen.
Antwoord 1, Autoriteit 100%
Wanneer u een cmp a,b
doet, worden de vlaggen ingesteld alsof u het a - b
hebt berekend.
Dan de jmp
-TYPE-instructies controleren die vlaggen om te zien of de sprong moet worden gedaan.
Met andere woorden, het eerste blok code dat u hebt (met mijn opmerkingen toegevoegd):
cmp al,dl ; set flags based on the comparison
jg label1 ; then jump based on the flags
springt naar label1
indien en alleen als al
groter was dan dl
.
U bent waarschijnlijk beter af, denk eraan als al>dl
Maar de twee keuzes die u hebt zijn wiskundig equivalent:
al > dl
al - dl > dl - dl (subtract dl from both sides)
al - dl > 0 (cancel the terms on the right hand side)
U moet voorzichtig zijn bij gebruik van jg
Voor zover het aangenomen dat uw waarden zijn ondertekend. Dus, als u de bytes 101 (101 in de aanvulling van twee) vergelijkt met 200 (-56 in de aanvulling van twee), zal de eerste daadwerkelijk groter zijn. Als dat niet gewenst was, zou u de equivalente niet-ondertekende vergelijking moeten gebruiken.
Zie hiervoor meer details over sprongselectie, hieronder weergegeven voor de volledigheid. Eerst degenen waar ondertekendheid niet gepast is:
+--------+------------------------------+-------------+--------------------+
|Instr | Description | signed-ness | Flags |
+--------+------------------------------+-------------+--------------------+
| JO | Jump if overflow | | OF = 1 |
+--------+------------------------------+-------------+--------------------+
| JNO | Jump if not overflow | | OF = 0 |
+--------+------------------------------+-------------+--------------------+
| JS | Jump if sign | | SF = 1 |
+--------+------------------------------+-------------+--------------------+
| JNS | Jump if not sign | | SF = 0 |
+--------+------------------------------+-------------+--------------------+
| JE/ | Jump if equal | | ZF = 1 |
| JZ | Jump if zero | | |
+--------+------------------------------+-------------+--------------------+
| JNE/ | Jump if not equal | | ZF = 0 |
| JNZ | Jump if not zero | | |
+--------+------------------------------+-------------+--------------------+
| JP/ | Jump if parity | | PF = 1 |
| JPE | Jump if parity even | | |
+--------+------------------------------+-------------+--------------------+
| JNP/ | Jump if no parity | | PF = 0 |
| JPO | Jump if parity odd | | |
+--------+------------------------------+-------------+--------------------+
| JCXZ/ | Jump if CX is zero | | CX = 0 |
| JECXZ | Jump if ECX is zero | | ECX = 0 |
+--------+------------------------------+-------------+--------------------+
Dan de niet-ondertekende:
+--------+------------------------------+-------------+--------------------+
|Instr | Description | signed-ness | Flags |
+--------+------------------------------+-------------+--------------------+
| JB/ | Jump if below | unsigned | CF = 1 |
| JNAE/ | Jump if not above or equal | | |
| JC | Jump if carry | | |
+--------+------------------------------+-------------+--------------------+
| JNB/ | Jump if not below | unsigned | CF = 0 |
| JAE/ | Jump if above or equal | | |
| JNC | Jump if not carry | | |
+--------+------------------------------+-------------+--------------------+
| JBE/ | Jump if below or equal | unsigned | CF = 1 or ZF = 1 |
| JNA | Jump if not above | | |
+--------+------------------------------+-------------+--------------------+
| JA/ | Jump if above | unsigned | CF = 0 and ZF = 0 |
| JNBE | Jump if not below or equal | | |
+--------+------------------------------+-------------+--------------------+
En tot slot de ondertekende:
+--------+------------------------------+-------------+--------------------+
|Instr | Description | signed-ness | Flags |
+--------+------------------------------+-------------+--------------------+
| JL/ | Jump if less | signed | SF <> OF |
| JNGE | Jump if not greater or equal | | |
+--------+------------------------------+-------------+--------------------+
| JGE/ | Jump if greater or equal | signed | SF = OF |
| JNL | Jump if not less | | |
+--------+------------------------------+-------------+--------------------+
| JLE/ | Jump if less or equal | signed | ZF = 1 or SF <> OF |
| JNG | Jump if not greater | | |
+--------+------------------------------+-------------+--------------------+
| JG/ | Jump if greater | signed | ZF = 0 and SF = OF |
| JNLE | Jump if not less or equal | | |
+--------+------------------------------+-------------+--------------------+
Antwoord 2, autoriteit 3%
Wikibooks heeft een redelijk goede samenvatting van springinstructies. Er zijn eigenlijk twee fasen:
cmp_instruction op1, op2
Die verschillende vlaggen instelt op basis van het resultaat, en
jmp_conditional_instruction address
die de sprong zal uitvoeren op basis van de resultaten van die vlaggen.
Compare (cmp
) berekent in principe de aftrekking op1-op2
, maar dit wordt niet opgeslagen; in plaats daarvan worden alleen vlagresultaten ingesteld. Dus als je cmp eax, ebx
deed, is dat hetzelfde als zeggen eax-ebx
– en vervolgens beslissen op basis van of dat positief, negatief of nul is welke vlaggen je moet instellen.
Meer gedetailleerde referentie hier.
Antwoord 3
Optellen en aftrekken in het complement van twee is hetzelfde voor getekende en niet-ondertekende getallen
De belangrijkste observatie is dat CMP in feite aftrekken is, en:
In two’s complement(integer-representatie gebruikt door x86), ondertekende en niet-ondertekende toevoeging zijn precies dezelfde bewerking
Hierdoor kunnen bijvoorbeeld hardwareontwikkelaars het efficiënter implementeren met slechts één circuit.
Dus als je bijvoorbeeld invoerbytes aan de x86 ADD-instructie geeft, maakt het niet uit of ze zijn ondertekend of niet.
ADD stelt echter wel een paar vlaggen in, afhankelijk van wat er tijdens de operatie is gebeurd:
-
carry: resultaat van optellen of aftrekken zonder teken past niet in bitgrootte, bijv.: 0xFF + 0x01 of 0x00 – 0x01
Daarnaast zouden we 1 naar het volgende niveau moeten brengen.
-
teken: resultaat heeft topbit ingesteld. D.w.z.: is negatief indien geïnterpreteerd als ondertekend.
-
overloop: invoer top bits zijn zowel 0 als 0 of 1 en 1 en uitvoer omgekeerd is het tegenovergestelde.
D.w.z. ondertekende bewerking veranderde de handtekening op een onmogelijke manier (bijv. positief + positief of negatief
We kunnen die vlaggen vervolgens zo interpreteren dat de vergelijking overeenkomt met onze verwachtingen voor ondertekende of niet-ondertekende nummers.
Deze interpretatie is precies wat JA vs JG en JB vs JL voor ons doen!
Codevoorbeeld
Hier is GNU GAS een codefragment om dit concreter te maken:
/* 0x0 ==
*
* * 0 in 2's complement signed
* * 0 in 2's complement unsigned
*/
mov $0, %al
/* 0xFF ==
*
* * -1 in 2's complement signed
* * 255 in 2's complement unsigned
*/
mov $0xFF, %bl
/* Do the operation "Is al < bl?" */
cmp %bl, %al
Merk op dat de AT&T-syntaxis “achterwaarts” is: mov src, dst
. Dus je moet mentaal de operanden omdraaien om de conditiecodes logisch te maken met cmp
. In Intel-syntaxis zou dit cmp al, bl
. zijn
Na dit punt zouden de volgende sprongen worden gemaakt:
- JB, omdat 0 < 255
- JNA, omdat !(0 > 255)
- JNL, omdat !(0 < -1)
- JG, omdat 0 > -1
Merk op hoe in dit specifieke voorbeeld de ondertekendheid van belang was, b.v. JB is bezet, maar niet JL.
Uitvoerbaar voorbeeld met beweringen.
Gelijk aan/ontkende versies zoals JLE/JNG zijn slechts aliassen
Door te kijken naar de Intel 64 en IA-32 Architectures Software Developer’s Manuals Volume 2sectie “Jcc – Jump if Condition Is Vold” zien we dat de coderingen identiek zijn, voor voorbeeld:
Opcode Instruction Description
7E cb JLE rel8 Jump short if less or equal (ZF=1 or SF ≠ OF).
7E cb JNG rel8 Jump short if not greater (ZF=1 or SF ≠ OF).
Antwoord 4
Het commando JG betekent simpelweg: Spring indien groter. Het resultaat van de voorgaande instructies wordt opgeslagen in bepaalde processorvlaggen (hierin zou het testen of ZF=0 en SF=OF) en springinstructies werken volgens hun status.