Assembleur résultat d'une multiplication sur 16 bits

de mémoire et tapé ici sans tester

volatile uint16_t resultat = 0;

void setup() {
  Serial.begin(115200); Serial.println();
  asm volatile (
    "ldi r18, 144 \n"
    "ldi r19, 3 \n"
    "mul r18, r19 \n"
    "sts (resultat), r0 \n"           // LSB
    "sts (resultat + 1), r1 \n"       // MSB
    "eor r1,r1 \n"                    // on remet r1 à 0
    :::"r19", "r19"
  );

  Serial.print("resultat = "); Serial.println(resultat);
}

void loop(void) { }

les points notables

  • je fais un clear (par un ou exclusif eor) de r1 à la fin car si ce registre est modifié il faut le remettre à 0.
  • je donne une clobber list qui dit quels sont les registres que j'ai modifié

ou si vous voulez utiliser des variables sur un octet pour la multiplication

volatile uint16_t resultat = 0;
volatile uint8_t a = 144;
volatile uint8_t b = 3;

void setup() {
  Serial.begin(115200); Serial.println();

  // asm volatile(“code” : output operand list : input operand list : clobber list);

  asm volatile (
    "mul %0, %1 \n"
    "sts (resultat), r0 \n"           // LSB
    "sts (resultat + 1), r1 \n"       // MSB
    "eor r1,r1 \n"                    // on remet r1 à 0
    : 
    : "a" (a), "a" (b)
    :
  );

  Serial.print("resultat = "); Serial.println(resultat);
}

void loop(void) { }

je précise dans la liste des opérandes en entrée que a et b doivent être mis dans dans un registre de la partie haute (celui que le compilateur choisira dans r16 à r23) et je peux faire référence à ces registres par %0 et %1

➜ dans ce cas je n'ai plus besoin de la clobber list puisque le compilateur sait quels sont les registres choisis et donc s'est chargé de les restaurer à leur valeur s'il en avait besoin

(ça fait quelques années (décennies) que je n'ai plus vraiment fait d'assembleur... le compilateur + optimiser est généralement bien meilleur que moi)