Informatique embarquée (IEM) Programmation sur ARM (2/2) 2008-2009 (v0.2) Daniel Rossier [email protected] Programmation sur ARM Modèle du programmeur Jeu d'instructions Langage d'assemblage Extensions du langage Traduction de structures C en assembleur Programmation sur ARM (2/2) - IEM/REDS 2 Extensions du langage Programmation sur ARM (2/2) - IEM/REDS 3 Pseudo-instructions (1/6) Les instructions sont des macros de l'assembleur constituées de une ou plusieurs instructions du processeur. adr adrl ldr Attention! Il existe également une instruction LDR nop Programmation sur ARM (2/2) - IEM/REDS 4 Pseudo-instructions (2/6) adr{condition} registre, expression La pseudo-instruction charge une adresse dans un registre. Le mnémonique contient une valeur relative au PC. La pseudo-instruction est traduite par une seule instruction add ou sub. Le déplacement doit être de ±1024 octets au maximum. Exemple: start: mov adr r0, #10 r4, start adr => sub r4,pc,#0xC Programmation sur ARM (2/2) - IEM/REDS 5 Pseudo-instructions (3/6) adrl{condition} registre, expression La pseudo-instruction charge une adresse dans un registre. Le mnémonique contient une valeur relative au PC. La pseudo-instruction est traduite par deux instructions. Le déplacement doit être de ±256 KB au maximum. Exemple: start: mov adrl r0,#10 r4,start+60000 @ => add @ => add @0xE8FE r4,pc,#0xE800 r4,r4,#0xFE Programmation sur ARM (2/2) - IEM/REDS 6 Pseudo-instructions (4/6) ldr {cond} register, =[expr|label-expr] La pseudo-instruction charge un registre avec… Si l'expression peut être représentée sur 8 bits, l'instruction est traduite par un mov. Si tel n'est pas le cas, l'instruction utilise une indirection mémoire dans un pool situé dans le code… …une constante de 32 bits, ou …une adresse …automatiquement après le code, ou …spécifié à l'aide de la directive .ltorg Attention! Ne pas confondre avec l'instruction ldr (sans =) Programmation sur ARM (2/2) - IEM/REDS 7 Pseudo-instructions (5/6) Exemples ldr r3, =0xff00 @ charge 0xff00 -> r3 @ => mov r3,#0xff00 (0xff * 28) ldr r1, =0xfff @ charge 0xfff -> r1 @ => ldr r1, [pc, offset vers Mm] @ … @ Mm: .word 0xfff offset ldr r1, =Place @ charge la const. Place -> r1 @ => ldr r1,[pc,offset vers Mm] @ … @ Mm: .word Place Programmation sur ARM (2/2) - IEM/REDS 8 Pseudo-instructions (6/6) nop (no operation) La pseudo-instruction est traduite par une instruction n'ayant aucun effet. mov r0, r0 nop ne peut s'exécuter conditionnellement. Les flags de l'ALU ne sont pas modifiés. Programmation sur ARM (2/2) - IEM/REDS 9 Directives d'assemblage (1/9) Les directives d'assemblage sont destinées au compilateur d’assemblage Identification des zones mémoire (sections) Déclaration de noms (symboles) constantes et variables Déclaration de données Contrôle de l'assemblage Déclaration de structures … Les directives commencent par un . (point) Programmation sur ARM (2/2) - IEM/REDS 10 Directives d'assemblage (2/9) - Sections Un programme (dans un fichier binaire ou en mémoire) est subdivisé en sections (cf cours SYX). Lors du chargement et durant l'exécution, les sections sont traitées différemment. Lors du chargement des sections en mémoire, les pages mémoire - si la pagination est activée - reçoivent des attributs différents en fonction des sections. Section .text Cette section est destinée à contenir les instructions et parfois des constantes. Les données de cette section sont inaltérables durant l’exécution. Programmation sur ARM (2/2) - IEM/REDS 11 Directives d'assemblage (3/9) - Sections Section .data Contient les variables initialisées (valeur d’initialisation indiquée lors de la déclaration) Les instructions d'initialisations sont produites lors de la compilation. Les données de cette section peuvent être altérer durant l’exécution. Programmation sur ARM (2/2) - IEM/REDS 12 Directives d'assemblage (4/9) - Sections Section .bss (Block Started by Symbol) Contient les variables globales non initialisées. Dans le fichier binaire, un symbole est attribué à chaque variable ainsi que la taille qui devra être alloué en mémoire. Le chargeur (loader) est responsable d'effectuer l'allocation (et l'initialisation à 0 éventuellement) de chaque variable, en fonction des informations trouvées dans le fichier binaire. Typiquement, l'OS ou le moniteur sont responsables d'allouer la mémoire lors du chargement du programme. La réservation de l'espace s'effectue avec la directive .space .bss aux_reg: .space 4 @ déclare une variable de 32 bits Programmation sur ARM (2/2) - IEM/REDS 13 Directives d'assemblage (5/9) - Sections Les directives .text, .data, .bss permettent de forcer ce qui suit dans les différentes sections respectives. Il peut y avoir d'autres types de section. Sections pour la mise au point (debug) Sections pour des données en lecture seule Sections pour les informations relatives au droit d'auteur etc. L’éditeur de liens (linker) concatène les bouts d’une même section apparaissant dans les fichiers liés. Programmation sur ARM (2/2) - IEM/REDS 14 Directives d'assemblage (6/9) L’éditeur de liens permet de spécifier l’adresse à laquelle commence une certaine section en mémoire. Il s'agit de l'offset par rapport au début de section. Pour choisir la position relative dans une section, on utilise la directive d’assemblage .org .text .org 0x18 @ text (adresse 0 p.ex. du fichier principal) handler: mov r5, #2F @ cette instruction se trouve à 0x18 Programmation sur ARM (2/2) - IEM/REDS 15 Directives d'assemblage (7/9) La directive .globl <label> exporte la visibilité du label au-delà du fichier. La directive .globl <label> informe le compilateur que le label se trouve dans un autre fichier. Utilisé par le linker typiquement La directive .end indique au compilateur d'assemblage la fin du fichier source. Ce qui se trouve au-delà de cette directive n'est pas compilé! .extern LP_status, Err_No_LP .global add32 add32: add ldr ldr cmp beq r0,r0,r1 r0, =LP_status r1,[r0] r1,#0 Err_No_LP .end Programmation sur ARM (2/2) - IEM/REDS 16 Directives d'assemblage (8/9) Le compilateur d’assemblage permet… …d’associer un nom à une constante numérique. …d’utiliser ce nom dans un fichier source, en lieu et place de la valeur de la constante. Déclaration de constante (semblable à #define en C) : .equiv <nom>, <expression> .equiv Nb_Roues, 4 .equiv LP_Data, LP_Base+8 Tout comme #define en C, déclarer une constante d’assemblage ne crée pas une vraie constante dans la mémoire de l’application !! Le pré-processeur effectue le remplacement systématique. Programmation sur ARM (2/2) - IEM/REDS 17 Directives d'assemblage (9/9) Quelques directives de mise en page: .title "titre" : titre mis en entête de chaque page .subtitle "soustitre" : sous-titre, remplace le précédent sous-titre .nolist / .list : stoppe et redémarre l’inclusion des lignes dans le listing .eject : saut de page .psize lines,columns : spécifie le format (nombre de lignes et de colonnes) d’une page Programmation sur ARM (2/2) - IEM/REDS 18 Expressions (1/3) Le compilateur peut calculer une valeur numérique à partir d’une expression composée de… …constantes numériques …opérateurs reconnus par le compilateur …noms (symboles) définis avant l’expression Noms (ou symboles) Etiquettes (label) Constantes d’assemblage Variables d’assemblage Programmation sur ARM (2/2) - IEM/REDS 19 Expressions (2/3) - Opérateurs Opérateurs en préfixe : - : négation (complément à 2) ~ : inversion bit à bit Opérateurs entre 2 opérandes (priorité 1): * : multiplication / : division (résultat tronqué) % : modulo (reste) << : décalage à gauche >> : décalage à droite Programmation sur ARM (2/2) - IEM/REDS 20 Expressions (3/3) - Opérateurs Opérateurs entre 2 opérandes (priorité 2): | : OU (inclusif) bit à bit & : ET bit à bit ^ : OU-exclusif bit à bit ! : OU-NON bit à bit Opérateurs entre 2 opérandes (priorité 3): + : addition - : soustraction Programmation sur ARM (2/2) - IEM/REDS 21 Variables et constante d’assemblage (1/2) Une variable d’assemblage est traité comme une constante d’assemblage qui peut changer de valeur à l'intérieur d'un même fichier source. Exemple .set Taille, 32 @depuis cette ligne: Taille = 32 … .set Taille, Taille*2 @depuis de cette ligne: Taille double Programmation sur ARM (2/2) - IEM/REDS 22 Variables et constante d’assemblage (2/2) Attention! Les constantes et les variables d’assemblage ne sont utilisées que durant la phase de compilation (par le préprocesseur), et non lors de l’exécution du programme. Programmation sur ARM (2/2) - IEM/REDS 23 Constantes de l'application (1/2) Les constantes de l'applications peuvent être placés soit dans la section .data soit dans la section .text (par défaut). Le compilateur "décidera" en fonction du langage et de l'environnement d'exécution (OS, moniteur, standalone, etc.) La directive .byte permet d'allouer un ou plusieurs bytes (8 bits) de mémoire et spécifie la valeur qu’ils doivent contenir. @ Constante occupant 4 bytes err_S: .byte 0x23, 'O', 0, 'K' .hword pour des mots de 16 bits (2 bytes) .word pour des mots de 32 bits (4 bytes) Programmation sur ARM (2/2) - IEM/REDS 24 Constantes de l'application (2/2) . asciz : pour des textes (entre " "), ajout automatique d’un 0 à la fin. .string : identique à .string Err_S: .string "Surchauffe" @ constante occupant 11 bytes, contenant @ le mot Surchauffe suivi d’un 0 .ascii : identique à .asciz, sans le 0 final Programmation sur ARM (2/2) - IEM/REDS 25 Caractères spéciaux dans un string Byte Signification \b backspace (retourner 1 caractère en arrière) \f formfeed (passer à la page suivante) \n carriage return (retour de chariot) \t horizontal tabulation \\ le caractère \ \" le caractère " \x <hex> le caractère ayant le code hexadécimal <hex> Programmation sur ARM (2/2) - IEM/REDS 26 Alignement Aligne la position courante (le compilateur y placera le prochain byte de code ou de donnée) sur une limite spécifiée. .align <expression> expression correspond au nombre de bit à 0 depuis la droite (nombre de zéros depuis la droite). Err_Code .byte .align 75 2 @ prochaine adresse se terminera par 00 @alignement de l’instruction qui suit @sur un mot de 32 bits Suite: mov r0,r1 Programmation sur ARM (2/2) - IEM/REDS 27 Alias de registre <alias> .req <reg> Associe un <alias> pour le registre <reg> L'alias simplifie l'utilisation des registres en le nommant avec un nom significatif. Améliore grandement la lisibilité du programme. Programmation sur ARM (2/2) - IEM/REDS 28 Macro-instructions (1/6) Une macro-instruction ou simplement macro représente un bloc d'instructions représenté par un nom symbolique. Le début du bloc commence par la directive .macro Le fin du bloc est déterminé par la directive .endm Une sortie prématurée de la macro est possible avec .exitm Une macro est… paramétrable (générique) plus rapide qu'un sous-programme, mais utilise plus de place mémoire. une macro peut en utiliser une autre. Programmation sur ARM (2/2) - IEM/REDS 29 Macro-instructions (2/6) Le pré-processeur du compilateur d'assemblage insère le corps de la macro… …à chaque endroit du fichier source où le nom de la macro apparaît. …en remplaçant les paramètres formels (ceux de la déclaration) par les paramètres réels utilisés lors de l’invocation. Programmation sur ARM (2/2) - IEM/REDS 30 Macro-instructions (3/6) Amélioration de la lisibilité du code source (plus "parlant" et plus compact). Permet un découpage hiérarchique des fonctions. Permet l'abstraction des particularités matérielles (nom de registre, adresse, etc.). Ré-utilisation du code Programmation sur ARM (2/2) - IEM/REDS 31 Macro-instructions (4/6) Exemple de déclaration et d'utilisation d’une macro-instruction: .macro macroABC Param1,Param2 ... @ code (corps de la macro) @ On se référera aux paramètres avec \ @ (exemple: \Param1) ldr r0, =\Param2 ... ldr \Param1, r7 ... .endm macroABC r0, #20 Programmation sur ARM (2/2) - IEM/REDS 32 Macro-instructions (5/6) - Exercice Ecrire une macro qui accepte trois paramètres (<reg>, <dest>, <cond>) et qui compare le registre <reg> avec la valeur 0 selon la condition <cond>. Si le résultat est vrai, alors sauter à l'adresse <dest>. Quel sera le code en assembleur résultant? Programmation sur ARM (2/2) - IEM/REDS 33 Macro-instructions (6/6) - Exercice Ecrire en assembleur ARM les macros suivantes: CALL : appel de sous-programme RET : retour au programme appelant PUSH : placement de données sur la pile POP : récupération de données depuis la pile Programmation sur ARM (2/2) - IEM/REDS 34 Inclusion de fichiers La directive .include permet l'insertion d'un fichier source dans le fichier en cours d'assemblage (comme un copier-coller). Exemples .include "macros.inc" .include "serial/pl12011.inc" @ Contient les macros de base @ Contient des macros spécifiques @ et des constantes Programmation sur ARM (2/2) - IEM/REDS 35 Appels de fonction (1/7) Le développement de code en assembleur nécessite absolument un découpage en fonction. Découpage hiérarchique Réutilisation Réduction de la taille du code Exemple: … bl SProg ... @ appel de sous-programme @ adresse de retour SProg: ... @ point d'entrée du sous-prog mov pc,lr @ retour Programmation sur ARM (2/2) - IEM/REDS 36 Appels de fonction (2/7) Un appel de sous-programme est un saut avec mémorisation de l'adresse de retour (dans le cas de ARM, l'adresse de retour est stocké dans le registre de lien). Instruction: bl format: r14 := pc - #4 (le PC est en avance de deux instructions) action sur le pc: bl{<cond>}<adresse saut> Action sur le registre de lien @ branch with link, ±32MB pc := pc ± offset(24 bits) L'offset est calculé lors de l'assemblage ou de l’édition de liens. Programmation sur ARM (2/2) - IEM/REDS 37 Appels de fonction (3/7) Dans un langage structuré, une fonction possède son propre contexte (variables locales, code, etc.). En assembleur, on ne dispose que de registres. Il faut donc préserver les registres entre les différentes contextes. Les registres qui seront altérés doivent être sauvegardés sur la pile au début de la fonction, puis restaurés à la fin de celle-ci. Programmation sur ARM (2/2) - IEM/REDS 38 Appels de fonction (4/7) - Passage paramètres Dans un langage structuré, le passage de paramètres est régi par des conventions de passage. Les conventions dépendent fortement des compilateurs. Le passage des paramètres peut se faire selon deux types de paramètres formels: Par valeur Par référence La valeur du paramètre n'est pas altéré au retour de la fonction. La valeur du paramètre peut être altéré au retour de l'appelant. Typiquement, le paramètre est une adresse. Les paramètres doivent être transmis à la fonction par registres par zone mémoire dédiée par la pile Programmation sur ARM (2/2) - IEM/REDS 39 Appels de fonction (5/7) - Passage paramètres Transmission des paramètres par registres Méthode efficace (taille du code, vitesse) . Requiert une convention stricte entre programme appelant et sous-programme. Convient pour un nombre restreint de paramètres. Manque de souplesse. Mise au point difficile. Programmation sur ARM (2/2) - IEM/REDS 40 Appels de fonction (6/7) - Passage paramètres Transmission des paramètres par zone mémoire dédiée La zone mémoire est commune à l'appelant et l'appelé. Adéquat lors de transfert volumineux de paramètres. Requiert une convention stricte entre programme appelant et sous-programme. Manque de souplesse. Moins efficace (plus lent à cause des transferts mémoire) que par registre. Programmation sur ARM (2/2) - IEM/REDS 41 Appels de fonction (7/7) - Passage paramètres Transmission des paramètres par la pile Permet le transfert de paramètres nombreux. Nécessite une convention, mais moins stricte que les deux autres méthodes. Adéquat pour des appels imbriqués (notamment pour les appels récursifs). Méthode employée par les compilateurs pour la plupart des processeurs. Moins efficace que par registre. La pile est une zone mémoire. Programmation sur ARM (2/2) - IEM/REDS 42 Gestion de la pile (1/3) La pile est une zone mémoire utilisée comme un LIFO. Deux actions classiques PUSH POP Mettre sur la pile Retirer de la pile Pile sur ARM stm{cond} <a_mode4S> rd!,<reglist> ldm{cond} <a_mode4L> rd!,<reglist> Habituellement: rd = sp (r13) Programmation sur ARM (2/2) - IEM/REDS 43 Gestion de la pile (2/3) A partir d'une adresse de base, une pile peut croître dans l'espace mémoire… …soit en montant (adresses croissantes) …soit en descendant (adresses décroissantes) Type "ascending" (A) Type "descending" (D) Le pointeur de pile peut pointer… …soit sur le sommet de la pile Case occupée → full (F) …soit sur la case suivante Case libre → empty (E) Programmation sur ARM (2/2) - IEM/REDS 44 Gestion de la pile (3/3) Dans la plupart des cas, la pile croît en descendant dans l'espace d'adressage. Le pointeur de pile sp pointe sur le sommet de la pile (case pleine). C'est l'approche adoptée dans les OS afin de gérer au mieux la gestion dynamique du tas (heap) et de la pile (stack) (cf cours SYX). Lorsque la pile est vide, le sp pointe en dessous de la pile. On utilisera donc les instructions stm{cond}fd sp!,<reglist> @ PUSH ldm{cond}fd sp!,<reglist> @ POP Programmation sur ARM (2/2) - IEM/REDS 45 Appels de fonctions et gestion de la pile (1/3) Lors d'un appel à un sous-programme, l'adresse de retour est stockée dans le registre lr (r14). Un appel imbriqué nécessite la sauvegarde du registre lr. Chaque nouvelle appelle de fonction empile les différentes adresses de retour. A la sortie d'une fonction, on restaure le lr du contexte précédant. On remonte ainsi le chemin d'invocation des fonctions. Programmation sur ARM (2/2) - IEM/REDS 46 Appels de fonctions et gestion de la pile (2/3) @ Programme principal … Main: ... bl pc → r15 program counter lr → r14 link register sp → r13 stack pointer SProg1 Sous-programme 1 (SP-branche : appelle un autre SProg1: stmfd sp!,{lr,r0-r2} bl SProg2 ... ldmfd sp!,{lr,r0-r2} mov pc,lr SP) : @ PUSH @ POP @ retour Sous-programme 2 (SP-feuille : n’appelle aucun SP) : SProg2: ... mov pc,lr @ retour Programmation sur ARM (2/2) - IEM/REDS 47 Appels de fonctions et gestion de la pile (3/3) Le retour de la fonction peut être optimisé… @ Programme principal … Main: ... bl SProg1 Sous-programme 1 (SP-branche : appelle un autre SP) : SProg1: stmfd sp!,{lr,r0-r2} @ PUSH bl SProg2 ... ldmfd sp!,{pc,r0-r2} @ POP Sous-programme 2 (SP-feuille : n’appelle aucun SP) : SProg2: ... mov pc,lr @ retour Programmation sur ARM (2/2) - IEM/REDS 48 Traduction de structures C en assembleur Programmation sur ARM (2/2) - IEM/REDS 49 Structure de contrôle if-else (1/2) En C: if (expression) instructions1; else instructions2; Traduction en pseudo-code assembleur: if not(expression) goto else; instructions1; goto suite; else: instructions2; suite: Programmation sur ARM (2/2) - IEM/REDS 50 Structure de contrôle if-else (2/2) - Exemple @if (a > b) cmp ble @ a = a-b; sub b @else @ b = b-a; else: sub Suite: r0,r1 else @a->r0, b->r1 r0,r0,r1 Suite r1,r1,r0 Programmation sur ARM (2/2) - IEM/REDS 51 Structure de contrôle while (1/2) En C: Traduction en pseudo-code assembleur: while(expression) instructions; debut_while: if not(expression) goto fin; instructions; goto debut_while; fin: Programmation sur ARM (2/2) - IEM/REDS 52 Structure de contrôle while (2/2)- Exemple Exemple: mise à zéro de la mémoire, mot par mot, entre data et data+taille ldr r0, =x @ while(x>=data){ ldr r1, =data mov r2, #0 InitData: cmp r0,r1 blo Suite @ mem[x]=0; str r2,[r0] @ x=x-4; sub r0,r0,#4 @} b InitData Suite: @ r0=x -> data+taille @ r1 = val lim boucle @ r2 = val a memoriser Programmation sur ARM (2/2) - IEM/REDS 53 Structure de contrôle do-while (1/2) En C: Traduction en pseudo-code assembleur: do debut: instructions; if expression goto debut; instructions; while(expression) Programmation sur ARM (2/2) - IEM/REDS 54 Structure de contrôle do-while (2/2) - Exemple ldr r0, =x @ r0=x -> fin de data @ do { ldr r1, =data mov r2, #0 InitData: @ mem[x]=0; str r2,[r0] @ x=x-4; sub r0,r0,#4 @ } while(x>=data) cmp r0,r1 bhs InitData @ r1 = val lim boucle @ r2 = val a memoriser Programmation sur ARM (2/2) - IEM/REDS 55 Structure de contrôle for (1/2) En C: Traduction en pseudo-code assembleur: for(init,cond,m_à_j) instructions; init(indice); debut: instructions; mise_à_jour(indice); if (cond) goto debut; Programmation sur ARM (2/2) - IEM/REDS 56 Structure de contrôle for (2/2) - Exemple val_lim = data+taille @for(x=data,x<=val_lim,x=x+4) { ldr r0, =data @ r0=x -> data ldr r1, =val_lim @ r1 = val lim boucle mov r2, #0 @ r2 = val a memoriser InitData: @ mem[x]=0; str r2, [r0] @} add r0, r0, #4 @ x=x+4 cmp r0, r1 bls InitData Programmation sur ARM (2/2) - IEM/REDS 57 Optimisation boucle for Optimisez la traduction en assembleur de l’exemple précédent de boucle for, en utilisant l’adressage postindexé. Programmation sur ARM (2/2) - IEM/REDS 58 Structure de contrôle switch (1/2) En C: Traduction en pseudo-code assembleur: switch(expression entière) { case constante1: instrs1; (optionnel) break; (optionnel) case constante2: instrs2; (optionnel) break; (optionnel) … default: instrs_def; calcule(expr); cas1: if expr <> const1 goto cas2; instrs1; goto fin; cas2: if expr <> const2 goto cas3; instrs2; goto fin; cas3: … instrs_def; fin: (optionnel) (optionnel) } Programmation sur ARM (2/2) - IEM/REDS 59 Structure de contrôle switch (2/2) - Exemple @switch (val) { s_prog1; @.case 1: cmp r0,#1 bleq SProg1 @..break; beq Fin s_prog2; @.case 2: cmp r0,#2 bleq SProg2 @..break; beq Fin s_prog6; @.case 6: cmp r0,#6 bleq SProg6 @..break; beq Fin s_prog_def; @.default: bl SProg_Def @} Fin: @ val est dans r0 Programmation sur ARM (2/2) - IEM/REDS 60 Calcul du PGCD (1/5) Algorithme PGCD (plus grand commun diviseur, Euclide) int pgcd(int a, int b){ while (a != b) do { if (a > b) a = a - b; else b = b - a; } return a; } Programmation sur ARM (2/2) - IEM/REDS 61 Calcul du PGCD (2/5) @int pgcd(int a, int b) { @.while (a != b) do { pgcd: cmp r0,r1 be fin @..if (a > b) blt pp @...a = a – b; pg: sub r0,r0,r1 b pgcd @..else @...b = b - a; pp: sub r1,r1,r0 @..} b pgcd fin: @.return a; @} mov pc,lr Programmation sur ARM (2/2) - IEM/REDS 62 Calcul du PGCD (3/5) Bilan taille mémoire / durée d'exécution ⇒ Taille mémoire sans retour : 7 instructions (28 bytes) Programmation sur ARM (2/2) - IEM/REDS 63 Calcul du PGCD (4/5) - Optimisation @int pgcd(int a, int b) { @.while (a != b) do { pgcd: cmp r0,r1 @..if (a > b) @...a = a – b; pg: subgt r0,r0,r1 @..else @...b = b - a; pp: sublt r1,r1,r0 bne pgcd @..} @.return a; @} mov pc,lr Programmation sur ARM (2/2) - IEM/REDS 64 Calcul du PGCD (5/5) Bilan taille mémoire / durée d'exécution après optimisation ⇒ Taille mémoire sans retour : 4 instructions (16 bytes) Programmation sur ARM (2/2) - IEM/REDS 65 Gestion pile - Exercice En ayant recours à la pile, modifiez le sous-programme pgcd de sorte qu'il réponde à l'API suivante: @----------------------------------------------------@ pgcd @----------------------------------------------------@Description: Calcul du PGCD de 2 nombres a et b @Entrees : a dans r0 et b dans r1 @Sorties : pgcd dans r2 @Modifie : r2 @----------------------------------------------------- Programmation sur ARM (2/2) - IEM/REDS 66 Références Cours NUM3 de l'ancienne orientation IT ARM System Developer's Guide Programmation sur ARM (2/2) - IEM/REDS 68