Veuillez consulter cette page à partir de l'interface principale.
Tutorial: Checksum
yasep/tuto/tuto_checksum.en.html created 20130802 by Yann Guidon
 

How to compute checksums with the YASEP

Introduction

Checksums are a family of basic methods that compute a signature of a block or stream of data, with the aim to protect against accidental and simple errors or alterations of these data. The signature is computed before and after the data is transmitted or stored (along with the signature) to ensure the integrity.

See also Wikipedia.

Prerequisites and assumptions:

Scan a block of bytes

Checksums usually read consecutive bytes from data memory. The code needs a bit of pointer handling and basic looping techniques.

Commençons par affecter des registres à cette opération :

;  R1 : loop counter (how many bytes left to scan)
;  R2 : the byte read from the current location
;  A1 : addresse of the bytes to read (will be altered)
;  A2 : loop start address

Data memory words or half-words are read with a pair of A and D registers. However bytes must be extracted with the EZB and ESB opcodes. If you want to read the byte pointed by A1, and put it in R2, you must write the following instruction:

  EZB A1 D1 R2

The difference between EZB and ESB is that EZB fills the rest of the register with 0S while ESB extends the sign bits (this loads signed integers).

Once the byte is loaded, the pointer is incremented by adding 1 to the address register :

  add 1 A1

Loops are

  add -1 R3
  add -1 R3

Puis on remet A1 dans PC si R3 n'est pas égal à 0 (NZ : Not Zero)

  mov A1 PC NZ R3

Et enfin, on bloque le processeur pour arrêter le programme quand le rebouclage est terminé.

  HALT

 

Voici le programme complet :

; fbLFSR_1 : boucle 65536 fois
.name fbLFSR_1
.profile YASEP32

; Affectation des registres :
;   R3 : compteur
;   A1 : loop

mov 65536 R3

add 4 PC A1

;;;;; début de la boucle ;;;;;
  ; décrémente le compteur
  add -1 R3

  ; on remet A1 dans PC si R3 n'est pas égal à 0
  mov A1 PC NZ R3
;;;;;; fin de la boucle ;;;;;;

HALT

 

Changer la couleur du framebuffer

Maintenant, nous pouvons accéder au framebuffer, ce qui nécessite de gérer l'adresse des pixels ainsi que leur valeur (qui est fixe pour l'instant).

On commence par compléter l'affectation des registres :

;  R1 : couleur (R : Registre simple de stockage)
;  R3 : compteur
;  A1 : loop
;  A2 : écran (A : registre d'Adresse)
;       associé à D2 (D : registre de Donnée)

On pointe ensuite A2 sur le début du framebuffer :

  mov 20000h A2

Cette adresse peut changer arbitrairement, vérifier que cela correspond bien au champ "Adresse début" en haut à droite de la fenêtre du framebuffer.

On décide alors de la couleur des pixels :

Pour ça, on doit placer #00A0FF (le code HTML de la couleur) dans R1. On commence par inverser l'ordre des trois octets dans ce mot :

On passe manuellement de RVB à BVR car le YASEP est "Little Endian" et l'octet rouge est à la première position d'un pixel. La valeur de la couleur dans le registre finira donc par être 00 FF A0 00 (les deux premiers 0 ne sont pas exploités mais ils restent nécessaires pour remplir les 32 bits).

Le YASEP ne permet pas de charger 32 bits directement, il faut donc une séquence d'instructions qui chargent 16 bits chacune. On place d'abord A0 00 (dans les bits de poids faible, à droite) avec MOV puis on place (00)FF dans les bits de poids forts (à gauche) avec MOVH.

  mov   A000h R1
  movh  FFh   R1 ; #00A0FF : bleu ciel

Puis on écrit la couleur dans le framebuffer avec MOV et avance au pixel suivant (4 octets plus loin) avec ADD 4 A2 :

  mov R1 D2
  add 4 A2

 

Voici le programme complet :

; fbLFSR_2 : remplit l'écran avec une couleur
.name fbLFSR_2
.profile YASEP32

; Affectation des registres :
;   R1 : couleur (Registre simple de stockage)
;   R3 : compteur
;   A1 : loop
;   A2 : écran (registre d'Adresse)
       ; associé à D2 (registre de Donnée)

mov 65536 R3

; adresse du framebuffer:
mov 20000h A2

mov   A000h R1
movh  FFh   R1 ; #00A0FF : bleu ciel

add 4 PC A1

;;;;; début de la boucle ;;;;;
  ; écrit la couleur dans le framebuffer
  mov R1 D2
  add 4 A2

  ; décrémente le compteur
  add -1 R3

  ; on remet A1 dans PC si R3 n'est pas égal à 0
  mov A1 PC NZ R3
;;;;;; fin de la boucle ;;;;;;

HALT

 

Changer la couleur avec un LFSR

Nous allons maintenant remplir l'écran avec des pixels pseudo-aléatoires. Pour cela, on utilise un "Registre à décalage à rétroaction linéaire". La théorie mathématique est mieux expliquée sur la page Wikipedia anglaise et un article très détaillé est disponible chez UnixGarden. Le principe est réduit à un décalage et une opération XOR.

Toutes les subtilités mathématiques sont concentrées dans la valeur choisie pour le XOR, qu'on appelle "polynôme". Il existe des tables de valeurs valides, et comme on utilise 32 bits, on choisit une des valeurs les plus utilisées, celle du CRC32 standard : 0x04C11DB7

Pour que le générateur de nombres pseudo-aléatoires fonctionne correctement, en plus du choix d'un bon polynôme, il faut s'assurer que R1 n'est pas initialisé avec la valeur 0. La couleur "bleu ciel" convient par exemple et R1 est initialisé avec cette valeur.

Affectation des registres :

;   R1 : LFSR (couleur)
;   R2 : polynome
;   R3 : compteur
;   A1 : loop
;   A2 : écran (registre d'Adresse)
;        associé à D2 (registre de Donnée)

On initialise donc d'abord le polynôme du LFSR (R2) ...

  mov   1DB7h R2 ; LSB
  movh 04C1h R2 ; MSB

C'est une valeur qui ne tient pas dans 20 bits, il faut donc la "couper en deux" et la charger dans R1 avec une séquence de 2 instructions (MOV puis MOVH).

... Et on génère un bit pseudo-aléatoire :

  add R1 R1 ; décale le registre
  ; et met le bit de poids fort dans la retenue

Enfin, si la retenue est à 1, on XOR avec le polynome. Cela permet de générer le bit pseudo aléatoire en combinaison avec le décalage réalisé par le ADD précédent) :

  xor R2 R1 CARRY

 

Voici le programme complet :

; fbLFSR : remplit l'écran avec
; une couleur pseudo-aléatoire
.name fbLFSR
.profile YASEP32

; Affectation des registres :
;   R1 : LFSR (couleur)
;   R2 : polynome
;   R3 : compteur
;   A1 : loop
;   A2 : écran (registre d'Adresse)
       ; associé à D2 (registre de Donnée)

mov 65536 R3

; adresse du framebuffer:
mov 20000h A2

mov   A000h R1
movh  FFh   R1 ; #00A0FF : bleu ciel

; initialise le polynôme du LFSR:
mov  1DB7h R2 ; LSB
movh 04C1h R2 ; MSB

add 4 PC A1

;;;;; début de la boucle ;;;;;
  ; génère un bit pseudo-aléatoire :
  ADD R1 R1 ; décale le registre et
            ; met le bit de poids fort
            ; dans la retenue

  ; si la retenue est à 1, alors on xor
  xor R2 R1 CARRY

  ; écrit la couleur dans le framebuffer
  mov R1 D2
  add 4 A2

  ; décrémente le compteur
  add -1 R3

  ; on remet A1 dans PC si R3 n'est pas égal à 0
  mov A1 PC NZ R3
;;;;;; fin de la boucle ;;;;;;

HALT