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)