zettacode.files/arithmetic.integer/arm_assembly.txt in zettacode-0.1.0 vs zettacode.files/arithmetic.integer/arm_assembly.txt in zettacode-0.1.1

- old
+ new

@@ -1,293 +1,293 @@ -{{ ||Rb P}} - =" b" +{{works with|as|Raspberry Pi}} +<syntaxhighlight lang="arm assembly"> -* ARM b Rb PI * -* . * -* C * -.qu STDOUT, 1 -.qu WRITE, 4 -.qu EXIT, 1 +/* ARM assembly Raspberry PI */ +/* program arith.s */ +/* Constantes */ +.equ STDOUT, 1 +.equ WRITE, 4 +.equ EXIT, 1 -*********************** -* Iz * -*********************** -. -zME: .cz " T ub c ! \" @ -zRuL: .cz "\" -zMRu: .cz "Ru " @ u -MVu: .f 12, 1, ' ' - .cz "\" -zMA: .cz " :" -zMSuc: .cz "uc :" -zMMuc: .cz "uc :" -zMD: .cz " :" -zMR: .cz " :" +/***********************/ +/* Initialized data */ +/***********************/ +.data +szMessError: .asciz " Two numbers in command line please ! \n" @ message +szRetourLigne: .asciz "\n" +szMessResult: .asciz "Resultat " @ message result +sMessValeur: .fill 12, 1, ' ' + .asciz "\n" +szMessAddition: .asciz "addition :" +szMessSoustraction: .asciz "soustraction :" +szMessMultiplication: .asciz "multiplication :" +szMessDivision: .asciz "division :" +szMessReste: .asciz "reste :" -*********************** -* N Iz * -*********************** -.b -Vu: . 4 @ 4 b +/***********************/ +/* No Initialized data */ +/***********************/ +.bss +iValeur: .skip 4 @ reserve 4 bytes in memory -. -.b -: - u {f,} @ 2 - f,,#8 @ f - ébu - 0,[f] @ cu ub f c - c 0,#3 - b - 0,[f,#8] @ f 1 ub - b cAD - 3,0 - 0,[f,#12] @ f 2 ub - b cAD - 4,0 - @ - 0,3,4 - 1,AMVu @ u 0 - b c10S @ c fuc 2 (0,1) - 0,AzMRu - b ffcM @ - 0,AzMA - b ffcM @ - 0,AMVu - b ffcM @ - @ uc - ub 0,3,4 - 1,=MVu - b c10S @ c fuc 2 (0,1) - 0,AzMRu - b ffcM @ - 0,AzMSuc - b ffcM @ - 0,AMVu - b ffcM @ +.text +.global main +main: + push {fp,lr} @ save des 2 registres + add fp,sp,#8 @ fp <- adresse début + ldr r0,[fp] @ recup number of parameter in command line + cmp r0,#3 + blt error + ldr r0,[fp,#8] @ adresse of 1er number + bl conversionAtoD + mov r3,r0 + ldr r0,[fp,#12] @ adresse of 2eme number + bl conversionAtoD + mov r4,r0 + @ addition + add r0,r3,r4 + ldr r1,iAdrsMessValeur @ result in r0 + bl conversion10S @ call function with 2 parameter (r0,r1) + ldr r0,iAdrszMessResult + bl affichageMess @ display message + ldr r0,iAdrszMessAddition + bl affichageMess @ display message + ldr r0,iAdrsMessValeur + bl affichageMess @ display message + @ soustraction + sub r0,r3,r4 + ldr r1,=sMessValeur + bl conversion10S @ call function with 2 parameter (r0,r1) + ldr r0,iAdrszMessResult + bl affichageMess @ display message + ldr r0,iAdrszMessSoustraction + bl affichageMess @ display message + ldr r0,iAdrsMessValeur + bl affichageMess @ display message - @ uc - u 0,3,4 - 1,=MVu - b c10S @ c fuc 2 (0,1) - 0,AzMRu - b ffcM @ - 0,AzMMuc - b ffcM @ - 0,AMVu - b ffcM @ + @ multiplication + mul r0,r3,r4 + ldr r1,=sMessValeur + bl conversion10S @ call function with 2 parameter (r0,r1) + ldr r0,iAdrszMessResult + bl affichageMess @ display message + ldr r0,iAdrszMessMultiplication + bl affichageMess @ display message + ldr r0,iAdrsMessValeur + bl affichageMess @ display message - @ - 0,3 - 1,4 - b - 0,2 @ qu - 1,=MVu - b c10S @ c fuc 2 (0,1) - 0,AzMRu - b ffcM @ - 0,AzMD - b ffcM @ - 0,AMVu - b ffcM @ + @ division + mov r0,r3 + mov r1,r4 + bl division + mov r0,r2 @ quotient + ldr r1,=sMessValeur + bl conversion10S @ call function with 2 parameter (r0,r1) + ldr r0,iAdrszMessResult + bl affichageMess @ display message + ldr r0,iAdrszMessDivision + bl affichageMess @ display message + ldr r0,iAdrsMessValeur + bl affichageMess @ display message - 0,3 @ - 1,=MVu - b c10S @ c fuc 2 (0,1) - 0,AzMRu - b ffcM @ - 0,AzMR - b ffcM @ - 0,AMVu - b ffcM @ + mov r0,r3 @ remainder + ldr r1,=sMessValeur + bl conversion10S @ call function with 2 parameter (r0,r1) + ldr r0,iAdrszMessResult + bl affichageMess @ display message + ldr r0,iAdrszMessReste + bl affichageMess @ display message + ldr r0,iAdrsMessValeur + bl affichageMess @ display message - 0, #0 @ u c + mov r0, #0 @ return code b 100f -: - 0,AzME - b ffcM @ c fuc 1 (0) - 0, #1 @ u c -100: * f * - 7, #EXIT @ qu - 0 @ f c -AMVu: . MVu -AzMRu: . zMRu -AzME: . zME -AzMA: . zMA -AzMSuc: . zMSuc -AzMMuc: . zMMuc -AzMD: . zMD -AzMR: . zMR -****************************************************************** -* ffc c ccu uu * -****************************************************************** -* 0 c u * -ffcM: - u {f,} * 2 * - u {0,1,2,7} * u * - 2,#0 * cu uu * -1: *ccu uu * - b 1,[0,2] * cu c bu + c * - c 1,#0 * 0 c f * - bq 1f - 2,2,#1 * ju 1 * +error: + ldr r0,iAdrszMessError + bl affichageMess @ call function with 1 parameter (r0) + mov r0, #1 @ return code +100: /* end of program */ + mov r7, #EXIT @ request to exit program + swi 0 @ perform the system call +iAdrsMessValeur: .int sMessValeur +iAdrszMessResult: .int szMessResult +iAdrszMessError: .int szMessError +iAdrszMessAddition: .int szMessAddition +iAdrszMessSoustraction: .int szMessSoustraction +iAdrszMessMultiplication: .int szMessMultiplication +iAdrszMessDivision: .int szMessDivision +iAdrszMessReste: .int szMessReste +/******************************************************************/ +/* affichage des messages avec calcul longueur */ +/******************************************************************/ +/* r0 contient l adresse du message */ +affichageMess: + push {fp,lr} /* save des 2 registres */ + push {r0,r1,r2,r7} /* save des autres registres */ + mov r2,#0 /* compteur longueur */ +1: /*calcul de la longueur */ + ldrb r1,[r0,r2] /* recup octet position debut + indice */ + cmp r1,#0 /* si 0 c est fini */ + beq 1f + add r2,r2,#1 /* sinon on ajoute 1 */ b 1b -1: * c c 2 c uu u * - 1,0 * u 1 * - 0,#STDOUT * c u éc u Lu * - 7, #WRITE * c '' * - #0 * * - {0,1,2,7} * u u * - {f,} * u 2 * - b * u cu * -*************************************************** -* c éc é * -*************************************************** -* 0 c * -* 1 c z c * -c10S: - u {f,} * 2 f u * - u {0-5} * u * - 2,1 * bu z c * - 5,#'+' * fu + * - c 0,#0 * b éf ? * - 5,#'-' * u - * - 0,0 * u * - 0,#1 - 4,#10 * uu z * -1: * bu buc c * - b 10 * * - 1,#48 * ju 48 u u c c * - b 1,[2,4] * c u b ébu z 5 + 4 * - ub 4,4,#1 * éc * - c 0,#0 - b 1b * buc qu ff zé * - b 5,[2,4] * c u à cu * - ub 4,4,#1 * éc * - b 100f * 4 0 f * - * fu c bu z c bc * - 3,#' ' * cc c * +1: /* donc ici r2 contient la longueur du message */ + mov r1,r0 /* adresse du message en r1 */ + mov r0,#STDOUT /* code pour écrire sur la sortie standard Linux */ + mov r7, #WRITE /* code de l appel systeme 'write' */ + swi #0 /* appel systeme */ + pop {r0,r1,r2,r7} /* restaur des autres registres */ + pop {fp,lr} /* restaur des 2 registres */ + bx lr /* retour procedure */ +/***************************************************/ +/* conversion registre en décimal signé */ +/***************************************************/ +/* r0 contient le registre */ +/* r1 contient l adresse de la zone de conversion */ +conversion10S: + push {fp,lr} /* save des 2 registres frame et retour */ + push {r0-r5} /* save autres registres */ + mov r2,r1 /* debut zone stockage */ + mov r5,#'+' /* par defaut le signe est + */ + cmp r0,#0 /* nombre négatif ? */ + movlt r5,#'-' /* oui le signe est - */ + mvnlt r0,r0 /* et inversion en valeur positive */ + addlt r0,#1 + mov r4,#10 /* longueur de la zone */ +1: /* debut de boucle de conversion */ + bl divisionpar10 /* division */ + add r1,#48 /* ajout de 48 au reste pour conversion ascii */ + strb r1,[r2,r4] /* stockage du byte en début de zone r5 + la position r4 */ + sub r4,r4,#1 /* position précedente */ + cmp r0,#0 + bne 1b /* boucle si quotient different de zéro */ + strb r5,[r2,r4] /* stockage du signe à la position courante */ + subs r4,r4,#1 /* position précedente */ + blt 100f /* si r4 < 0 fin */ + /* sinon il faut completer le debut de la zone avec des blancs */ + mov r3,#' ' /* caractere espace */ 2: - b 3,[2,4] * c u b * - ub 4,4,#1 * éc * - b 2b * buc 4 u u z * -100: * f fc * - {0-5} *u u * - {f,} * u 2 f u * - b + strb r3,[r2,r4] /* stockage du byte */ + subs r4,r4,#1 /* position précedente */ + bge 2b /* boucle si r4 plus grand ou egal a zero */ +100: /* fin standard de la fonction */ + pop {r0-r5} /*restaur des autres registres */ + pop {fp,lr} /* restaur des 2 registres frame et retour */ + bx lr -*************************************************** -* 10 é * -* T :.c-b-b-* -* :.c. * -*************************************************** -* 0 c * -* 0 u qu * -* 1 u * -10: - * 0 c u b b 10 * - u {2-4} * u * - 4,0 - 3, .L_c_ub_10 * 1 - c_ub * - u 1, 2, 3, 0 * 1 - L32B(1*0). 2 - U32B(1*0) * - 2, 2, ASR #2 * 2 - 2 2 * - 1, 0, LSR #31 * 1 - 0 31 * - 0, 2, 1 * 0 - 2 + 1 * - 2,0,0, #2 * 2 - 0 * 5 * - ub 1,4,2, #1 * 1 - 4 - (2 * 2) = 4 - (0 * 10) * - {2-4} - b * fuc * - . 4 -.L_c_ub_10: . 066666667 -****************************************************************** -* C u c b cé u * -****************************************************************** -* 0 c z é 0 u 0A * -cAD: - u {f,} * 2 * - u {1-7} * u * - 1,#0 - 2,#10 * fcu * - 3,#0 * cu * - 4,0 * 4 * - 6,#0 * f fu * - 0,#0 * à 0 * -1: * buc é bc u bu * - b 5,[4,3] * c 5 c ué u bu + * - c 5,#0 * f c - f u * - bq 100f - c 5,#00A * f c - f u * - bq 100f - c 5,#' ' * bc u ébu * - b 1f * cu * - 3,3,#1 * u buc ç u c * +/***************************************************/ +/* division par 10 signé */ +/* Thanks to http://thinkingeek.com/arm-assembler-raspberry-pi/* +/* and http://www.hackersdelight.org/ */ +/***************************************************/ +/* r0 contient le dividende */ +/* r0 retourne le quotient */ +/* r1 retourne le reste */ +divisionpar10: + /* r0 contains the argument to be divided by 10 */ + push {r2-r4} /* save autres registres */ + mov r4,r0 + ldr r3, .Ls_magic_number_10 /* r1 <- magic_number */ + smull r1, r2, r3, r0 /* r1 <- Lower32Bits(r1*r0). r2 <- Upper32Bits(r1*r0) */ + mov r2, r2, ASR #2 /* r2 <- r2 >> 2 */ + mov r1, r0, LSR #31 /* r1 <- r0 >> 31 */ + add r0, r2, r1 /* r0 <- r2 + r1 */ + add r2,r0,r0, lsl #2 /* r2 <- r0 * 5 */ + sub r1,r4,r2, lsl #1 /* r1 <- r4 - (r2 * 2) = r4 - (r0 * 10) */ + pop {r2-r4} + bx lr /* leave function */ + .align 4 +.Ls_magic_number_10: .word 0x66666667 +/******************************************************************/ +/* Conversion d une chaine en nombre stocké dans un registre */ +/******************************************************************/ +/* r0 contient l adresse de la zone terminée par 0 ou 0A */ +conversionAtoD: + push {fp,lr} /* save des 2 registres */ + push {r1-r7} /* save des autres registres */ + mov r1,#0 + mov r2,#10 /* facteur */ + mov r3,#0 /* compteur */ + mov r4,r0 /* save de l adresse dans r4 */ + mov r6,#0 /* signe positif par defaut */ + mov r0,#0 /* initialisation à 0 */ +1: /* boucle d élimination des blancs du debut */ + ldrb r5,[r4,r3] /* chargement dans r5 de l octet situé au debut + la position */ + cmp r5,#0 /* fin de chaine -> fin routine */ + beq 100f + cmp r5,#0x0A /* fin de chaine -> fin routine */ + beq 100f + cmp r5,#' ' /* blanc au début */ + bne 1f /* non on continue */ + add r3,r3,#1 /* oui on boucle en avançant d un octet */ b 1b 1: - c 5,#'-' * cc - * - q 6,#1 * j u 6 c 1 * - bq 3f * u c à u * -2: * bu buc cff * - c 5,#'0' * cc u cff * - b 3f - c 5,#'9' * cc u cff * - b 3f - * ccè u cff * - ub 5,#48 - 1,M *f é u * - c 0,1 - b 99f - u 0,2,0 * u fcu * - 0,5 * ju à 0 * + cmp r5,#'-' /* premier caracteres est - */ + moveq r6,#1 /* maj du registre r6 avec 1 */ + beq 3f /* puis on avance à la position suivante */ +2: /* debut de boucle de traitement des chiffres */ + cmp r5,#'0' /* caractere n est pas un chiffre */ + blt 3f + cmp r5,#'9' /* caractere n est pas un chiffre */ + bgt 3f + /* caractère est un chiffre */ + sub r5,#48 + ldr r1,iMaxi /*verifier le dépassement du registre */ + cmp r0,r1 + bgt 99f + mul r0,r2,r0 /* multiplier par facteur */ + add r0,r5 /* ajout à r0 */ 3: - 3,3,#1 * c à u * - b 5,[4,3] * c c * - c 5,#0 * f c - f u * - bq 4f - c 5,#10 * f c - f u * - bq 4f - b 2b * buc * + add r3,r3,#1 /* avance à la position suivante */ + ldrb r5,[r4,r3] /* chargement de l octet */ + cmp r5,#0 /* fin de chaine -> fin routine */ + beq 4f + cmp r5,#10 /* fin de chaine -> fin routine */ + beq 4f + b 2b /* boucler */ 4: - c 6,#1 * u 6 u * + cmp r6,#1 /* test du registre r6 pour le signe */ + bne 100f + mov r1,#-1 + mul r0,r1,r0 /* si negatif, on multiplie par -1 */ b 100f - 1,#-1 - u 0,1,0 * f, u -1 * - b 100f -99: * u é * - 1,=zMED - b ffcu - 0,#0 * c u u uju z * +99: /* erreur de dépassement */ + ldr r1,=szMessErrDep + bl afficheerreur + mov r0,#0 /* en cas d erreur on retourne toujours zero */ 100: - {1-7} * u u * - {f,} * u 2 * - b * u cu * -* c * -M: . 1073741824 -zMED: .cz "Nb : é cc 32 b. :\" -. 4 -*=============================================* -* é * -*============================================* -: - * 0 c N * - * 1 c D * - * 2 c Q * - * 3 c R * - u {4, } - 2, #0 * 2 ? 0 * - 3, #0 * 3 ? 0 * - 4, #32 * 4 ? 32 * + pop {r1-r7} /* restaur des autres registres */ + pop {fp,lr} /* restaur des 2 registres */ + bx lr /* retour procedure */ +/* constante programme */ +iMaxi: .int 1073741824 +szMessErrDep: .asciz "Nombre trop grand : dépassement de capacite de 32 bits. :\n" +.align 4 +/*=============================================*/ +/* division entiere non signée */ +/*============================================*/ +division: + /* r0 contains N */ + /* r1 contains D */ + /* r2 contains Q */ + /* r3 contains R */ + push {r4, lr} + mov r2, #0 /* r2 ? 0 */ + mov r3, #0 /* r3 ? 0 */ + mov r4, #32 /* r4 ? 32 */ b 2f 1: - 0, 0, LSL #1 * 0 ? 0 1 u c ( C f 31 b f 0 1) * - c 3, 3, 3 * 3 ? 3 + 3 + C. T qu 3 ? (3 1) + C * + movs r0, r0, LSL #1 /* r0 ? r0 << 1 updating cpsr (sets C if 31st bit of r0 was 1) */ + adc r3, r3, r3 /* r3 ? r3 + r3 + C. This is equivalent to r3 ? (r3 << 1) + C */ - c 3, 1 * cu 3 - 1 u c * - ub 3, 3, 1 * f 3 = 1 (C=1) 3 ? 3 - 1 * - c 2, 2, 2 * 2 ? 2 + 2 + C. T qu 2 ? (2 1) + C * + cmp r3, r1 /* compute r3 - r1 and update cpsr */ + subhs r3, r3, r1 /* if r3 >= r1 (C=1) then r3 ? r3 - r1 */ + adc r2, r2, r2 /* r2 ? r2 + r2 + C. This is equivalent to r2 ? (r2 << 1) + C */ 2: - ub 4, 4, #1 * 4 ? 4 - 1 * - b 1b * f 4 = 0 (N=0) bc .L1 * + subs r4, r4, #1 /* r4 ? r4 - 1 */ + bpl 1b /* if r4 >= 0 (N=0) then branch to .Lloop1 */ - {4, } - b + pop {r4, lr} + bx lr