
Basic Data Operation

This is a basic data operation. It represents a fundamental action on a basic data type.
You may see other such operations in the Basic Data Operations category, or:


Integer Operations
Arithmetic |
Comparison
Boolean Operations
Bitwise |
Logical
String Operations
Concatenation |
Interpolation |
Comparison |
Matching
Memory Operations
Pointers & references |
Addresses


Task

Get two integers from the user,   and then (for those two integers), display their:

   sum 
   difference 
   product 
   integer quotient
   remainder 
   exponentiation   (if the operator exists) 


Don't include error handling.

For quotient, indicate how it rounds   (e.g. towards zero, towards negative infinity, etc.).

For remainder, indicate whether its sign matches the sign of the first operand or of the second operand, if they are different.




 
 
/* 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	
 
 
 