Arithmetic/Integer: Difference between revisions
Content added Content deleted
(add assembly ARM raspberry) |
|||
Line 323: | Line 323: | ||
Quotient will round down in this version. |
Quotient will round down in this version. |
||
=={{header|ARM Assembly}}== |
|||
{{works with|as|Raspberry Pi}} |
|||
<lang ARM Assembly> |
|||
/* ARM assembly Raspberry PI */ |
|||
/* program arith.s */ |
|||
/* Constantes */ |
|||
.equ STDOUT, 1 |
|||
.equ WRITE, 4 |
|||
.equ EXIT, 1 |
|||
/***********************/ |
|||
/* 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 :" |
|||
/***********************/ |
|||
/* No Initialized data */ |
|||
/***********************/ |
|||
.bss |
|||
iValeur: .skip 4 @ reserve 4 bytes in memory |
|||
.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 |
|||
@ 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 |
|||
@ 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 |
|||
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 |
|||
mov r0, #0 @ return code |
|||
b 100f |
|||
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: /* 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: |
|||
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 |
|||
/***************************************************/ |
|||
/* 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: |
|||
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: |
|||
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: |
|||
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 |
|||
99: /* erreur de dépassement */ |
|||
ldr r1,=szMessErrDep |
|||
bl afficheerreur |
|||
mov r0,#0 /* en cas d'erreur on retourne toujours zero */ |
|||
100: |
|||
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: |
|||
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 */ |
|||
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: |
|||
subs r4, r4, #1 /* r4 ? r4 - 1 */ |
|||
bpl 1b /* if r4 >= 0 (N=0) then branch to .Lloop1 */ |
|||
pop {r4, lr} |
|||
bx lr |
|||
</lang> |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |