IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Assembleur Discussion :

Instructions cmp et dérivées


Sujet :

Assembleur

  1. #1
    Membre du Club Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Points : 55
    Points
    55
    Par défaut Instructions cmp et dérivées
    Bonjour,

    Je suis rendu en ce moment dans mon livre au chapitre où ils traitent des instructions cmp et de ses dérivées (jumps conditionnels).
    L'auteur, après avoir mentionné que, dans l'instruction
    L'ordinateur effectue l'opération "op1 - op2", comme dans une instruction "sub", à la seule différence que l'opérande 1 n'est pas modifiée, puis le processeur interprète les bits de EFLAGS pour savoir si op1 est plus grand, plus petit ou égal à op2.
    Il donne en gros ce schéma:


    Voilà, je ne comprends pas dutout. EN effet, il semble y avoir des CF=1 là ou il ne devrait pas y en avoir...
    Par exemple, prenons la ligne 2.
    Si je fais "3B - 15" (en hex), cela donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      11101011
    + 00111011
    ------------
    100100110
    Ici, le résultat de l'addition a bien 9 bits, donc un "carry out". Par conséquent, le bit CF devrait être 1, pas 0. Pourquoi en est-il autrement ici?


    Cordialement,

    Array

  2. #2
    Membre émérite
    Avatar de Eric2a
    Homme Profil pro
    Technicien
    Inscrit en
    Septembre 2005
    Messages
    1 225
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Corse (Corse)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 225
    Points : 2 411
    Points
    2 411
    Par défaut
    Salut,

    C'est une soustraction, donc si op1 est supérieur à op2 alors nous obtenons un nombre positif, et donc, le flag CF n'est pas posé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
         3Bh
    -    15h
      ------
         26h
     
     
          59
    -     21
      ------
          38
     
     
      111011
    - 010101
      ------
      100110

  3. #3
    Membre actif Avatar de golden boy
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2010
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2010
    Messages : 120
    Points : 230
    Points
    230
    Par défaut
    0x3b - 0x15 = 0x26 et ça tient en 6 bits, donc aucun problème.

  4. #4
    Membre du Club Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Points : 55
    Points
    55
    Par défaut
    Mais de quoi parlez-vous?
    Le x86 ne sait faire que l'addition, il ne fait pas directement une soustraction, et donc il convertit en plutôt complément de deux un nombre négatif puis l'additionne.

    Ici, comme j'ai dit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    3Bh - 15h =
      11101011
    + 00111011
    ------------
    100100110
    Où -15h = 11101011.

    Le résultat donne effectivement 9 bits. Le 9e bit est censé se retrouver dans CF. Pourquoi CF=0 ici?!

    À moins que je me sois trompé quelque part...

    COrdialement,
    Array

  5. #5
    Membre émérite
    Avatar de Eric2a
    Homme Profil pro
    Technicien
    Inscrit en
    Septembre 2005
    Messages
    1 225
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Corse (Corse)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 225
    Points : 2 411
    Points
    2 411
    Par défaut
    Citation Envoyé par Array
    Le x86 ne sait faire que l'addition


    Citation Envoyé par Array
    il convertit en plutôt complément de deux un nombre négatif puis l'additionne.
    La méthode dite de "complement à deux" permet juste de trouver l'opposé d'un nombre permetant ainsi de représenter un nombre relatif où le bit de plus haut rang sert de signe (0 = positif ; 1 = négatif).

  6. #6
    Membre du Club Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Points : 55
    Points
    55
    Par défaut
    Non...
    Voir ici pour plus d'infos.

    Two's complement subtraction is the binary addition of the minuend to the 2's complement of the subtrahend (adding a negative number is the same as subtracting a positive one).
    Cela concorde aussi avec ce que je lis! Le complément à deux n'est pas une sorte de system ou on fait qqch du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    si [le bit de gauche = 1]; alors
            on soustrait
    sinon
            on additionne

  7. #7
    Membre actif Avatar de golden boy
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2010
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2010
    Messages : 120
    Points : 230
    Points
    230
    Par défaut
    Faire un soustracteur binaire (même un qui prend 32 bits de donnée) avec des portes OR et des AND n'est certainement pas un soucis, c'est facile à faire alors je doute que les fondeurs n'ait pas implémenté directement ça sur le processeur (on fait même les log et les fonctions trigonométriques depuis quelques années).

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Sur le plan purement arithmétique, dans la mesure où l'on se retrouve avec 1 - 3 = FFFFFFFE, il me paraît logique de retrouver cette « extension de signe » dans la retenue.

    Sur le plan électronique, on réalise effectivement un additionneur-soustracteur en ajoutant une ligne pilotant des OU exclusifs sur l'un des opérandes, servant donc à le complémenter, et en reliant cette même ligne à la retenue d'entrée pour provoquer le +1 nécessaire.

    Dans les faits, quand on pose l'opération correspondante sur papier, on se retrouve systématiquement avec une retenue contenant le contraire de ce à quoi on s'attend. Du coup, je ne serais pas surpris que la retenue de sortie soit elle-aussi bufferisée via un OU exclusif.

    Il faudrait que je revoie un peu l'arithmétique binaire de ce côté-là pour être catégorique.

  9. #9
    Membre du Club Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Points : 55
    Points
    55
    Par défaut
    Obsidian, le soustracteur fait donc la complémentation lui même utilise XOR? Donc il fait bien une addition utilisant le complément à deux, non une soustraction directe? Où le x86 comporte-t-il bien une circuiterie spéciale pour la soustraction, distincte de l'addtion?
    Je croyais que l'avantage d'utiliser le complément à deux était *justement* de ne pas avoir à implémenter une circuiterie spéciale de soustraction...


    Quant à la question de départ... Ce que je voulais savoir en fait c'est: en quelles circonstances le bit CF est mis à 1 dans l'addition et la soustraction, car je suis un peux mélangé... On m'a parle de CF=1 dans le cas d'un "borrow" quand avec l'instruction SUB et de CF=1 dans le cas d'un ADD.
    Pourriez-vous confirmer?


    Merci!


    Array

  10. #10
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Citation Envoyé par Array Voir le message
    Je croyais que l'avantage d'utiliser le complément à deux était *justement* de ne pas avoir à implémenter une circuiterie spéciale de soustraction...
    Oui, mais comment obtiens-tu ce complément à 2 ? :-)

  11. #11
    Membre du Club
    Inscrit en
    Décembre 2004
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 33
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par Array Voir le message
    Bonjour,

    le processeur interprète les bits de EFLAGS pour savoir si op1 est plus grand, plus petit ou égal à op2.

    Voilà, je ne comprends pas dutout. EN effet, il semble y avoir des CF=1 là ou il ne devrait pas y en avoir...
    Array
    donc je compare 3Bh pour savoir
    si op1 est plus grand, plus petit ou égal à op2.

    interprète les bits de EFLAGS
    Instructions cmp et dérivées
    CMP
    Comparaison de deux valeur en tenant compte de la valeur de la retenue.
    Format: cmp opérande1, opérande2

    EFLAGS Influence (Flags)

    C: s´active si la valeur absolue de op1 est supérieure à op2 = un Carry

    Par exemple, prenons la ligne 2.op1>op2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
      00111011   3Bh 
      00010101   15h                            
    ------------ 
      00100110  =26h pas de carry puisque 3B est plus grand que 15
    Par exemple, prenons la ligne 3.op1<op2

    carry s´active si la valeur absolue de op1 est inferieur à op2 = un Carry
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
      00010101   15h 
      00111011   3Bh 
    ------------ 
      11011010   =DA  carry puisque 15 est plus petit que 3B

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 99
    Points : 122
    Points
    122
    Par défaut
    A - B == A + NEG(B) = A + NOT(B) +1

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    ; cmp 0x3b - 0x15
    mov eax, 0x3b
    mov ecx, 0x15
    cmp eax, ecx  ; CF=0 OK
    
    ; 0x3b -0x15
    mov eax, 0x3b
    mov ecx, 0x15
    sub eax, ecx  ; CF=0 OK
    
    ; 0x3b + NEG(0x15)
    mov eax, 0x3b
    mov ecx, 0x15
    neg ecx
    add eax, ecx ; CF=1 
    
    ; 0x3b + NOT(0x15) + 1
    mov eax, 0x3b
    mov ecx, 0x15 ; ou not 15 directement
    not ecx 
    add eax, ecx
    add eax, 1   ; CF=0
    Je pense donc que le proc réalise A -B par A + NOT(B) + 1

  13. #13
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Bonjour,

    Citation Envoyé par realpasso Voir le message
    Je pense donc que le proc réalise A -B par A + NOT(B) + 1
    Si, par là, tu entends que le processeur fait l'opération en deux fois (oubliant la retenue au passage, donc), ce n'est pas valable non plus car, selon le tableau du premier message, « 15 - 3B » doit positionner la retenue à 1. Or :

    15 + /3B =

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        00010101
      + 11000100
      ------------
        11011001
    … et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        11011001
      + 00000001
      ------------
    011011010
    Le seul moyen d'obtenir une retenue non-nulle dans ce cas est d'additionner 1 à FF.

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 99
    Points : 122
    Points
    122
    Par défaut
    Tu as raison. Je vais directement poser la question à Intel car je trouve ce "problème" interessant.

  15. #15
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Citation Envoyé par Array Voir le message
    Ici, le résultat de l'addition a bien 9 bits, donc un "carry out". Par conséquent, le bit CF devrait être 1, pas 0. Pourquoi en est-il autrement ici ?
    Citation Envoyé par Obsidian Voir le message
    Dans les faits, quand on pose l'opération correspondante sur papier, on se retrouve systématiquement avec une retenue contenant le contraire de ce à quoi on s'attend. Du coup, je ne serais pas surpris que la retenue de sortie soit elle-aussi bufferisée via un OU exclusif.
    Voila. Soupçons confirmés à la page 5 de ce document.

  16. #16
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 99
    Points : 122
    Points
    122
    Par défaut
    Merci pour le doc, ça m'évite de poser la question.

    Grand bravo à Array pour avoir soulevé ce point. J'ai toujours utilisé cmp sans jamais me poser la question ! IMHO, ça vaut le coup que tu en fasses un article.

  17. #17
    Membre éclairé
    Avatar de edfed
    Profil pro
    être humain
    Inscrit en
    Décembre 2007
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : Décembre 2007
    Messages : 476
    Points : 701
    Points
    701
    Billets dans le blog
    1
    Par défaut
    petite remarques à propos du sujet.

    peu importe comment le CPU le fait, du moment que l'operation le fait de manière claire et precise.

    donc, si cmp sur un 8086 est fait avec un sub sans enregistrement, un sub est un add precedé d'un neg
    un neg est un not suivit d'un inc
    un not c'est un xor avec 0FFh
    un inc, c'est un add, 1

    et un add c'est un tas de portes logiques inimaginable en 32 bits pour le commun des mortels.

    peu importe comment, le resultat, c'est que ça prend pas beaucoup de temps de travailler sur les registres avec des operations paralellisables, c'est à dire les operations simples sont à privilegier lors de l'ecriture d'un code.
    sur les X86 recents, presque toutes les instructions à usage general sont paralellisables.

    une autre remarque, c'est lorsqu'il faut effectuer plusieurs comparaisons, par exemple, pour couvrir plusieurs plages avec des traitements differents, il est avantageur d'effectuer des sub, car le resultat sera ajusté de sorte à ce que la precedente plage soit le point de depart de la comparaison suivante. ce qui permet de couper une plage de données en plusieurs intervales distincts avec juste un sub et un jcc. l'avantage est que l'on récupere à la fin une valeur egale à l'offset de notre variable par rapport au minimum, ou par rapport au maximum, selon le les sub et les cmp utilisés.

    il existe aussi des moyens de se passer de cmp, qui sont tout les resultats consecutifs à l'execution de n'importe quelle instruction sur une variable, ce qui permet, en jonglant avec les drapeaux de se passer de toute instruction conditionelle, la condition etant assurée par une operation sur une variable avec un drapeau, du type adc, sbb, rcr, rcl, etc...

  18. #18
    Membre du Club
    Inscrit en
    Décembre 2004
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 33
    Points : 40
    Points
    40
    Par défaut
    Lorsque une soustraction de deux nombres A et B se présentent
    Que A > B et Que A < B

    pour effectuer la soustraction dans le premier cas Que A > B
    où le diminuent A est supérieure au soustrayant B
    on fait le complement a 1 du soustrayant (15h)


    on fait le complement a 1 de (15h) qui serait

    11101010 Où -15h = 11101010.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
        00111011      3Bh
        11101010  +  -15h
     ----------
    = 1 00100101    = (1) 00100101
                       .
                       ..........1>
                     --------------
                          00100110 = 26h
     
    Ce Carry se joint aux résultats précédents
    Pour realisé la soustraction dans le deuxieme cas Que A < B
    où le diminuent A est inferieur au soustrayant B

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      00010101   15h
      00111011 - 3Bh
    -------------
    on fait le complement a 1 de (3Bh) qui serait 11000100-3B
     
     
       00010101     15h
     + 11000100   - 3Bh
     ______________
       11011001    
       00100110  = on fait le complement a 1 de la somme = (- 26 ) = DA

  19. #19
    Membre éclairé
    Avatar de edfed
    Profil pro
    être humain
    Inscrit en
    Décembre 2007
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : Décembre 2007
    Messages : 476
    Points : 701
    Points
    701
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Belgitaes Voir le message
    Lorsque une soustraction de deux nombres A et B se présentent
    Que A > B et Que A < B
    etc, etc...
    en français, ça donnerait quoi?

  20. #20
    Membre du Club
    Inscrit en
    Décembre 2004
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 33
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par edfed Voir le message
    en français, ça donnerait quoi?
    Un ordinateur passe la plupart du temps à penser quel serait la méthode idéale pour réaliser son travail,
    la condition principale étant calculer et soustraire pour qu'il puisse donner des résultats logiques,

    Le complément à un
    est l'opération qui inverse la valeur de chacun des bits d'un nombre binaire.
    Il est la première étape du complément à deux.


    Dans la base du système numérique existent 2 signes, le 0 et le 1, pour représenter un nombre binaire.
    Tout nombre binaire a un inverse qui s'obtient en changeant les 0 pour des 1.
    Et bien si au nombre inverse on additionne 1, on obtient le complément à 2 de ce nombre.

    A quoi sert le complément à 2 d'un nombre binaire ?

    Les microprocesseurs, généralement, ne savent pas soustraire, seulement compter.
    Donc ils utilisent des instructions de soustraction utilisant le complément à 2
    pour convertir une soustraction en addition. De cette façon, si on peut calculer tout est résolu.

    operand1 operand2

    A > B = op1>op2 = 3B 15 Diference = 26

    A < B = op1<op2 = 15 3B Diference = DA

    Maintenant j'espère que malgré mon mauvais français, vous aurez mieux compris.

    Merci de votre compréhension pour mes fautes d'orthographe, je suis españole
    Images attachées Images attachées  

Discussions similaires

  1. Instruction catch et classes dérivées.
    Par emmr.rida dans le forum C++
    Réponses: 15
    Dernier message: 24/06/2009, 12h20
  2. Passer de la zone d'édition vers une instruction sql
    Par tripper.dim dans le forum C++Builder
    Réponses: 2
    Dernier message: 27/11/2002, 14h44
  3. Instruction pour créer un fichier text ???
    Par Soulsurfer dans le forum Langage
    Réponses: 2
    Dernier message: 06/08/2002, 11h17
  4. [Crystal Report][VB6] instruction PrintReport
    Par yyyeeeaaahhh dans le forum SDK
    Réponses: 4
    Dernier message: 29/07/2002, 14h58
  5. [TASM] Problème concernant l'instruction LGDT
    Par Ninkosen dans le forum Assembleur
    Réponses: 3
    Dernier message: 15/07/2002, 19h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo