Besoin d'explications sur les flags

Signaler
Messages postés
18
Date d'inscription
mercredi 9 avril 2003
Statut
Membre
Dernière intervention
17 juin 2011
-
Messages postés
540
Date d'inscription
dimanche 23 mars 2003
Statut
Membre
Dernière intervention
5 octobre 2007
-
salut à tous,
je programme habituellement en VB, donc je n'ai pas vraiment la notion de flags, même si en réalité on peut comparer un IF avec un flags->saut...!! Bref, j'ai du mal à comprendre avec quelle instruction ils sont actifs! Par exemple:
-je crois savoir que l'instruction ADD n'a pas de retenue (CF) mais que l'instruction ADC en propose une, alors que faut-il faire pour activer cette retenue?

-si AX vaut 10 et que BX vaut 10, avec l'instruction ADD AX,BX j'ai un overflow?

Si vous connaissez une tuto qui décrit tres clairement a quel moment un flag est actif avec des exemples, merci de me l'indiquer.

merci par avance

@+

4 réponses

Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
salut,

la documentation intel est ce qu'il y a de mieux:
http://www.orangetide.com/computing/programming/standards/386intel/chp17-03.htm#17-03

un overflow ce produit quand tu dépasse la capacité de l'accumulateur de destination.
ADD AX,BX ne provoque un overflow que si AX+BX > 65535.

@++
Messages postés
540
Date d'inscription
dimanche 23 mars 2003
Statut
Membre
Dernière intervention
5 octobre 2007
1
C'est les bases de l'arithmétique binaire que tu as aussi en VB
les plus importants à connaitre sont CF (retenue), ZF (zéro), et OF (overflow)

CF est mis à un lorsqu'une opération à pour résultat une valeur supérieure à la valeur max, qui sont:
BYTE: >255
WORD: >65535
DWORD: >4294967295
en valeur non signée, et pour les valeur signée tout résultat >-1 donc positif ou nul met à 1 le flag CF car les valeur max non signée ont la même représentation que -1
En effet, que tu sois en signé ou non cela ne change rien pour le processeur, c'est toi dans ta programmation, qui défini si les nombre seront signé ou non, le processeur s'en fout

ZF est mis à un lorsque le résultat d'une opération est nul

OF sert surtout d'indicateur losque tu veux travailler en nombres signés
OF est mis à un lorsque le MSB du résultat a changé par rapport au MSB des opérandes et ceci quand le MSB des opérandes sont les mêmes
mais en pratique il est mis à un lorsque le résultat d'une opération déborde, donc:
BYTE: <-128 ou >127
WORD: <-32768 ou >32767
DWORD: <-2147483648 ou >2147483647

donc pour répondre à ta question 10+10=20 donc pas d'overflow car le MSB de 20 est 0 et le MSB de 10 est 0, il n'a pas changé, par contre 127+127 produit un overflow si on utilise des octets (BYTE)

mov al, 127
mov ah, 127
add al, ah ; OF=1
mais
mov ax, 127
mov bx, 127
mov ax, bx ; OF=0

de plus
mov al, 255
mov ah, 1
add al, ah ; ZF=1,CF=1, mais OF=0

Core Breaker
Messages postés
18
Date d'inscription
mercredi 9 avril 2003
Statut
Membre
Dernière intervention
17 juin 2011

Merci à tous les 2 pour votre aide, c'est beaucoup plus clair maintenant! Je crois qu'il ne me reste plus qu'a faire quelques manip.
Encore merci pour m'avoir aidé à démarrer dans ce langage
@+
Messages postés
540
Date d'inscription
dimanche 23 mars 2003
Statut
Membre
Dernière intervention
5 octobre 2007
1
De rien.
Je me suis aperçu que j'ai oublié un flag important dont le processeur se sert, c'est le flag SF qui est l'image du bit de signe (le MSB) du résultat d'une opération.

J'ai oublié de dire aussi que les instructions de saut (jxx) se sert des flags pour déterminer s'il y a saut ou pas.

Voici quelques intructions de saut conditionnel:
JA: (Jump if After) saut si CF OR ZF = 0
JAE: (Jump if After or Equal) saut si CF = 0
JB: (Jump if Before) saut si CF = 1
JBE: (Jump if Before or Equal) saut si CF OR ZF = 1
JE: (Jump if Equal) saut si ZF = 1
JG: (Jump if Greater) saut si (SF XOR OF) OR ZF = 0
JGE: (Jump if Greater or Equal) saut si SF XOR OF = 0
JL: (Jump if Less) saut si SF XOR OF = 1
JLE: (Jump if Less or Equal) saut si (SF XOR OF) OR ZF = 1
JNA: (Jump if Not After) saut si CF OR ZF = 1
JNAE: (Jump if Not After or Equal) saut si CF = 1
JNB: (Jump if Not Before) saut si CF = 0
JNBE: (Jump if Not Before or Equal) saut si CF OR ZF = 0
JNE: (Jump if Not Equal) saut si ZF = 1
JG: (Jump if Not Greater) saut si (SF XOR OF) OR ZF = 1
JGE: (Jump if Not Greater or Equal) saut si SF XOR OF = 1
JL: (Jump if Not Less) saut si SF XOR OF = 0
JLE: (Jump if Not Less or Equal) saut si (SF XOR OF) OR ZF = 0

Les instructions CMP AL, BL et SUB AL, BL font la soustration AL-BL, à la différence que le résultat est placé dans AL pour l'instruction SUB, mais que l'instruction CMP ne modifie pas AL

CMP AL, BL
JB dest ; saute si AL<BL, donc si AL-BL produit une retenue (CF=1)
En effet, si AL<BL, AL-BL<0, et si le résultat est négatif, une retenue est forcément produite

CMP AL, BL
JL dest ; saute si AL<BL

pour JB et JL, ce ne sont pas les même flag qui sont utilisé
JB est utilisé pour les nombres non signés, et JL pour les nombres signés: si AL=10 et BL=250, il y a un saut avec JB mais pas avec JL
La raison est simple, si on considère les valeurs non signées,
AL-BL=10-250=-240, le résultat est négatif, il y a donc saut.
Mais si on considère les valeurs non signées, alors AL=+10, et BL=-6, on a donc AL-BL=(+10)-(-6)=+16, le résultat est positif, il n'y a pas de saut
Donc pour les nombres signés on ne peut se fier à CF

J'ai aussi oublié de répondre à une autre de tes questions:
ADD peut produire une retenue, tout comme ADC, mais ADD n'utilise pas CF, alors ADC le fait.
ADC AX, BX ; effectue l'intruction AX=AX+BX+CF
En fait, la combinaison ADD/ADC permet de faire l'addition de grands nombre, voici comment additionner 2 nombre de 1024 octets (1Ko)

data segment
nb1 db 1024 dup(?)
nb2 db 1024 dup(?)
result db 1024 dup(?)
data ends

code segment
mov ax, data
mov ds, ax
mov es, ax
cld

mov si, offset nb1
mov bx, offset nb2
mov di, offset result

mov cx, 1024 / 2 ; on travaille en WORD donc on divise par 2
clc ; on met CF à zéro

boucle:
lodsb
adc ax, word ptr [bx]
stosb
lea bx, [bx+2]
loop boucle
code ends

et de manière plus classique voici comment additionner 2 nombres de 32bit en 16bits:

data segment
nb1 dd 654644
nb2 dd 44485457
result dd ?
data ends

code segment word public use16
mov ax, word ptr [nb1][0]
mov bx, word ptr [nb2][0]

mov cx, word ptr [nb1][2]
mov dx, word ptr [nb2][2]

add ax, bx ; addition des word de poids faible
adc cs, dx ; addition des word de poids fort en tenant compte
; de la retenue produit par l'addtion des word de poids faible

mov word ptr [result][0], ax
mov word ptr [result][2], cx
code ends

Core Breaker