web-dev-qa-db-fra.com

Comment déterminer quand le drapeau zéro, le drapeau de signe, le drapeau de débordement et le drapeau de transport sont définis?

Toute cette histoire de drapeau m'embrouille énormément. Les définitions sur le web semblent très simples. Je n'arrive pas à obtenir une très bonne explication applicable à tout cela.

Selon leurs définitions, - carry: indique un dépassement d'entier non signé - overflow: indique un dépassement d'entier signé - zéro: une opération a généré zéro - signe: l'opération a généré un nombre négatif

Alors, comment dans le monde les phrases suivantes sont-elles vraies? - Les instructions suivantes définissent le drapeau de signe: (La réponse ici est 252, pas un nombre négatif. Alors pourquoi le drapeau de signe est-il activé?)

mov al,0FEh
sub al,2
  • L’ajout de 7Fh et 05h dans un registre 8 bits définit l’indicateur de dépassement de capacité (la réponse est 132. Elle n’est pas supérieure à 255 alors pourquoi existe-t-il un dépassement?)

  • L’ajout de 0FFh et 05h dans un registre de 8 bits n’a pas pour effet de définir l’indicateur de dépassement de capacité (la réponse est 300, alors comment n’existe-t-il pas d’indicateur de dépassement? Il est supérieur à 256)

  • L'ajout de 5 à 0FBh dans un registre de 8 bits définit l'indicateur Zéro (la réponse ici est 256, pas 0. Je comprends que le 8 bits ne peut contenir que 255, mais d'où vient le «0»? Je ne comprends tout simplement pas .)

Est-ce que quelqu'un peut me faire savoir ce que je fais de mal ici et quelle est la bonne façon de l'aborder? Merci.

6
rose

La réponse ici est 252 pas un nombre négatif. Alors, pourquoi le drapeau est-il mis en place?

Comme unsigned il s'agit de 252, mais unsigned ne peut pas avoir de signe. L'indicateur de signe est uniquement associé au numéro traité comme signed . Peu importe comment vous le gérez, le processeur le traite toujours comme signé avec l'indicateur de signe. Donc, 252 est supérieur à 127, donc il est négatif en complément à 2 et le bit de signe est défini.

L’ajout de 7Fh et 05h dans un registre 8 bits définit l’indicateur de dépassement de capacité (la réponse est 132. Elle n’est pas supérieure à 255 alors pourquoi existe-t-il un dépassement?)

Comme vous l'avez dit, un débordement est défini lorsqu'un nombre signé nombre déborderait. Une variable signée de 8 bits peut aller de -128 à 127. Par conséquent, passer de 127 à 132 est un dépassement de capacité.

L’ajout de 0FFh et 05h dans un registre de 8 bits n’a pas pour effet de définir l’indicateur de dépassement de capacité (la réponse est 300, alors comment n’existe-t-il pas d’indicateur de dépassement? Il est supérieur à 256)

Encore une fois, le débordement est signé débordement. Cela provoque un unsigned overflow, ainsi le bit carry / sera défini.

L'ajout de 5 à 0FBh dans un registre 8 bits définit l'indicateur Zéro (la réponse ici est 256, pas 0. Je comprends que le 8 bits ne peut contenir que 255, mais d'où vient le «0»? Je ne comprends tout simplement pas .)

Comme vous l'avez dit, 8 bits peuvent aller jusqu'à 255. Après cela, il déborde et les 8 derniers bits sont 0. Le résultat est donc zéro et le bit zéro est défini. 

7
Sami Kuhmonen

Un autre excellent guide: Comprendre Carry vs. Overflow conditions/flags . Il contient de jolis exemples étape par étape avec des nombres à 4 bits qui vous permettent de garder le tout dans votre tête. Il explique également que le port non signé est ce que vous vérifiez lorsque vous interprétez les bits comme non signé, tandis que le dépassement de signature est ce que vous vérifiez lorsque vous interprétez les bits comme étant signés.


Basé sur le commentaire de OP:

Cela signifie-t-il que l'indicateur zéro est vraiment activé lorsque la valeur du bit le moins significatif est 0, et pas simplement "lorsqu'une opération produit 0"?

Ce qu'il faut retenir, c'est qu'il s'agit de l'arithmétique à largeur fixe entière. 0xFF + 1 dans un registre à 8 bits produit réellement un 0.

En termes mathématiques, il s’agit de arithmétique modulaire , avec un module de 28 pour une opération de 8 bits.

Donc, oui, ZF est défini en fonction de dst = (dst+src) % 0x100.

Il est conçu de cette façon parce que vous voulez généralement savoir si le registre est zéro, si vous comptez jusqu'à zéro avec inc sur un registre de départ négatif, ou si vous comptez jusqu'à zéro avec un registre de départ positif. .

Vous pouvez toujours vérifier CF==0 et ZF==1 pour détecter le cas où vous avez obtenu un zéro sans retenue. Si ZF n'était défini que lorsque dst et CF étaient tous les deux égaux à zéro, vous auriez souvent besoin d'une autre instruction pour tester simplement le registre de résultats.


Avoir CF et ZF indépendants signifie que les codes de condition non signés après cmp ou sub fonctionnent comme suit:

JA      Jump if above (CF=0 and ZF=0).
JAE     Jump if above or equal (CF=0).
JB      Jump if below (CF=1).
JBE     Jump if below or equal (CF=1 or ZF=1).

JC      Jump if carry (CF=1).

JE      Jump if equal (ZF=1).

Je pense que si ZF ne pouvait être réglé que s’il n’y avait pas de report, vous ne pourriez pas faire la différence entre Above et Above-or-Equal . C’est donc probablement la raison la plus concrète de la décision de conception de non prendre la décision que vous aviez choisie.

Voici l'une des conditions de comparaison signées:

JLE     Jump  if less or equal (ZF=1 or SF ≠ OF).

L'ensemble complet de conditions figure dans le manuel de référence insn set d'Intel (liens dans le wiki de balise x86 ), sous la liste d'instructions jcc (code de saut si condition).

1
Peter Cordes