Comparaisons 8 bits en Z80

Il y a bien quelque chose avec le Z80 qui me ralenti à chaque fois, ce sont les comparaisons. L'égalité, c'est facile. Mais dès qu'il s'agit de comparer deux octets pour savoir si l'un est plus grand que l'autre, strictement ou pas, et encore pire, si ce sont des octets signés, j'y passe du temps... pour souvent me tromper.

Et donc, voici un petit tableau récapitulatif pour m'aider à m'y retrouver, et peut-être que ça pourra aussi vous aider.

Table des matières

Comparaisons non signées (8 bits)

Un octet non signé est positif et dans l'intervalle [0, 255]. Après cp b (qui calcule A−B sans stocker le résultat), on a : Z = 1 si A = B et C = 1 si A < B.

A = B

    cp b
    jr z,egal
    ; cas 1 : A ≠ B
    jr next
egal:
    ; cas 2 : A = B
next:

A ≠ B

Le même code que pour A = B, mais en privilégiant le cas A ≠ B.

    cp b
    jr nz,inegal
    ; cas 1 : A = B
    jr next
inegal:
    ; cas 2 : A ≠ B
next:

A < B et A ≥ B

Les deux cas sont identiques, c'est juste une question de sémantique.

    cp b
    jr c,inf_strict
    ; cas 1 : A < B (ou A ≥ B)
    jr next
inf_strict:
    ; cas 2 : A ≥ B (ou A < B)
next:

A ≤ B et A > B

Les deux cas sont identiques, c'est juste une question de sémantique.

    cp b
    jr z,inf_ou_egal
    jr c,inf_ou_egal
    ; cas 1 : A > B (ou A ≤ B)
    jr next
inf_ou_egal:
    ; cas 2 : A ≤ B (ou A > B)
next:

Comparaisons signées (8 bits)

En signé, les deux octets sont dans l'intervalle [−128, +127]. La condition A < B est plus complexe à évaluer, car il faut aussi prendre en compte le flag de débordement (overflow) qui peut se produire lors de la soustraction A−B.

Si on est assuré qu'aucun overflow ne se produit (si A et B sont tous deux dans un intervalle [−64, +63]), voir la section suivante.

En signé ou pas, l'égalité est identique à celle des non signés, elle n'est pas reproduite ici.

Note : jr ne supporte pas les conditions sur S et V, il faut donc utiliser jp pour ces cas.

A > B ou A ≤ B (signé)

    cp b
    jr z,inf_ou_egal    ; A et B égaux
    jp pe,ov_gt         ; Overflow, il faut inverser la condition
    jp p,sup_strict     ; S=0 et pas d'overflow, donc A > B (strict)
    jp inf_ou_egal      ; S=1 et pas d'overflow, donc A ≤ B
ov_gt:                  ; Cas de l'overflow
    jp m,sup_strict     ; S=1 et overflow, donc A > B
    jp inf_ou_egal      ; S=0 et overflow, donc A ≤ B
sup_strict:
    ; cas 1 : A > B (signé)
    jp next
inf_ou_egal:
    ; cas 2 : A ≤ B (signé)
next:

A < B ou A ≥ B (signé)

    cp b
    jp pe,ov_lt         ; Overflow, il faut inverser la condition
    jp m,inf_strict     ; S=1 et pas d'overflow, donc A < B
    jp sup_ou_egal      ; S=0 et pas d'overflow, donc A ≥ B
ov_lt:                  ; Cas de l'overflow
    jp p,inf_strict     ; S=0 et overflow, donc A < B
    jp sup_ou_egal      ; S=1 et overflow, donc A ≥ B
inf_strict:
    ; cas 1 : A < B (signé)
    jp next
sup_ou_egal:
    ; cas 2 : A ≥ B (signé)
next:

Comparaisons signées simplifiées (8 bits)

Lorsque A et B sont dans un intervalle tel qu'aucun overflow ne se produit lors de A−B (tous deux dans [−64, +63] ou toute opération garantie sans débordement) le code est simplifié en retirant les vérifications d'overflow.

A > B ou A ≤ B (signé, pas d'overflow)

    cp b
    jr z,inf_ou_egal    ; A = B
    jp p,sup_strict     ; S=0, donc A > B
    jp inf_ou_egal      ; S=1, donc A ≤ B
sup_strict:
    ; cas 1 : A > B (signé)
    jp next
inf_ou_egal:
    ; cas 2 : A ≤ B (signé)
next:

A < B ou A ≥ B (signé, pas d'overflow)

    cp b
    jp m,inf_strict     ; S=1, donc A < B
    jp sup_ou_egal      ; S=0, donc A ≥ B
inf_strict:
    ; cas 1 : A < B (signé)
    jp next
sup_ou_egal:
    ; cas 2 : A ≥ B (signé)
next:

Les drapeaux

L'état des drapeaux après cp b.

Flag Signification
Z 1 si A = B (A - B = 0)
C 1 si A < B (non signé) (emprunt lors de A−B)
S Bit 7 de A−B (signe du résultat 8 bits)
P/V 1 si overflow signé (voir conditions ci-dessous)

À propos de l'overflow signé : il se produit lorsque A et B ont des signes opposés et que le résultat de A−B a un signe différent de celui de A.

Entre autre, il n'y a pas d'overflow possible si A et B sont de même signe.

À propos de S et V :

S V Interprétation
0 0 A − B ≥ 0, pas de débordement, donc A ≥ B
1 0 A − B < 0, pas de débordement, donc A < B
0 1 Résultat positif mais a débordé, donc A < B
1 1 Résultat négatif mais a débordé, donc A > B

Instructions et drapeaux

La syntax des sauts ne fait pas toujours référence directe au nom des drapeaux, ce qui est confusant.

Instruction Description
jr z/nz Saut relatif sur Z
jr c/nc Saut relatif sur C
jp m/p Saut absolu sur S
jp pe/po Saut absolu sur P/V