How to resolve the algorithm Aliquot sequence classifications step by step in the ARM Assembly programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Aliquot sequence classifications step by step in the ARM Assembly programming language

Table of Contents

Problem Statement

An aliquot sequence of a positive integer K is defined recursively as the first member being K and subsequent members being the sum of the Proper divisors of the previous term.

Show all output on this page.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Aliquot sequence classifications step by step in the ARM Assembly programming language

Source code in the arm programming language

/* ARM assembly Raspberry PI  */
/* program aliquotSeq.s   */

 /* REMARK 1 : this program use routines in a include file 
   see task Include a file language arm assembly 
   for the routine affichageMess conversion10 
   see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"

.equ MAXINUM,      10
.equ MAXI,         16
.equ NBDIVISORS,   1000

/*******************************************/
/* Initialized data                        */
/*******************************************/
.data
szMessStartPgm:          .asciz "Program start \n"
szMessEndPgm:            .asciz "Program normal end.\n"
szMessErrorArea:         .asciz "\033[31mError : area divisors too small.\033[0m \n"
szMessError:             .asciz "\033[31mError  !!!\033[0m \n"
szMessErrGen:            .asciz "Error end program.\033[0m \n"

szCarriageReturn:        .asciz "\n"
szLibPerf:               .asciz "Perfect       \n"
szLibAmic:               .asciz "Amicable      \n"
szLibSoc:                .asciz "Sociable      \n"
szLibAspi:               .asciz "Aspiring      \n"
szLibCycl:               .asciz "Cyclic        \n"
szLibTerm:               .asciz "Terminating   \n"
szLibNoTerm:             .asciz "No terminating\n"

/* datas message display */
szMessResult:            .asciz " @ "
szMessResHead:            .asciz "Number @ :"

.align 4
tbNumber:                 .int 11,12,28,496,220,1184,12496,1264460,790,909,562,1064,1488
                          .equ NBNUMBER,  (. - tbNumber ) / 4

/*******************************************/
/* UnInitialized data                      */
/*******************************************/
.bss 
.align 4
sZoneConv:               .skip 24
tbZoneDecom:             .skip 4 * NBDIVISORS       // facteur 4 octets
tbNumberSucc:            .skip 4 * MAXI
/*******************************************/
/*  code section                           */
/*******************************************/
.text
.global main 
main:                               @ program start
    ldr r0,iAdrszMessStartPgm       @ display start message
    bl affichageMess

    mov r4,#1
1:
    mov r0,r4                       @  number
    bl aliquotClassif               @ aliquot classification
    cmp r0,#-1                      @ error ?
    beq 99f
    add r4,r4,#1
    cmp r4,#MAXINUM
    ble 1b
    
    ldr r5,iAdrtbNumber             @ number array
    mov r4,#0
2:
    ldr r0,[r5,r4,lsl #2]           @ load a number
    bl aliquotClassif               @ aliquot classification
    cmp r0,#-1                      @ error ?
    beq 99f
    add r4,r4,#1                    @ next number
    cmp r4,#NBNUMBER                @ maxi ?
    blt 2b                          @ no -> loop
    
    ldr r0,iAdrszMessEndPgm         @ display end message
    bl affichageMess
    b 100f
99:                                 @ display error message 
    ldr r0,iAdrszMessError
    bl affichageMess
100:                                @ standard end of the program
    mov r0, #0                      @ return code
    mov r7, #EXIT                   @ request to exit program
    svc 0                           @ perform system call
iAdrszMessStartPgm:        .int szMessStartPgm
iAdrszMessEndPgm:          .int szMessEndPgm
iAdrszMessError:           .int szMessError
iAdrszCarriageReturn:      .int szCarriageReturn
iAdrtbZoneDecom:           .int tbZoneDecom
iAdrszMessResult:          .int szMessResult
iAdrsZoneConv:             .int sZoneConv
iAdrtbNumber:              .int tbNumber
/******************************************************************/
/*     function aliquot classification                            */ 
/******************************************************************/
/* r0 contains number */
aliquotClassif:
    push {r3-r8,lr}              @ save  registers
    mov r5,r0                    @ save number
    ldr r1,iAdrsZoneConv
    bl conversion10              @ convert ascii string
    mov r2,#0
    strb r2,[r1,r0]
    ldr r0,iAdrszMessResHead
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc        @ put in head message
    bl affichageMess             @ and display
    mov r0,r5                    @ restaur number
    ldr r7,iAdrtbNumberSucc      @ number successif array
    mov r4,#0                    @ counter number successif
1:
    mov r6,r0                    @ previous number
    ldr r1,iAdrtbZoneDecom
    bl decompFact                @ create area of divisors
    cmp r0,#0                    @ error ?
    blt 99f
    sub r3,r1,r6                 @ sum 
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl conversion10              @ convert ascii string
    mov r2,#0
    strb r2,[r1,r0]
    ldr r0,iAdrszMessResult
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc        @ and put in message
    bl affichageMess
    cmp r3,#0                    @ sum = zero
    bne 11f
    ldr r0,iAdrszLibTerm         @ terminating
    bl affichageMess
    b 100f
11:
    cmp r5,r3                    @ compare number and sum
    bne 4f
    cmp r4,#0                    @ first loop ?
    bne 2f
    ldr r0,iAdrszLibPerf         @ perfect
    bl affichageMess
    b 100f
2:
    cmp r4,#1                    @ second loop ?
    bne 3f
    ldr r0,iAdrszLibAmic         @ amicable
    bl affichageMess
    b 100f
3:                               @ other loop
    ldr r0,iAdrszLibSoc          @ sociable
    bl affichageMess
    b 100f
    
4:
    cmp r6,r3                 @ compare sum and (sum - 1)
    bne 5f
    ldr r0,iAdrszLibAspi      @ aspirant
    bl affichageMess
    b 100f
5:
    cmp r3,#1                 @ if one ,no search in array
    beq 7f
    mov r2,#0                 @ search indice
6:                            @ search number in array
    ldr r8,[r7,r2,lsl #2]
    cmp r8,r3                 @ equal ?
    beq 8f                    @ yes -> cycling
    add r2,r2,#1              @ increment indice
    cmp r2,r4                 @ end ?
    blt 6b                    @ no -> loop
7:
    cmp r4,#MAXI
    blt 10f
    ldr r0,iAdrszLibNoTerm    @ no terminating
    bl affichageMess
    b 100f
8:                            @ cycling
    ldr r0,iAdrszLibCycl
    bl affichageMess
    b 100f 
    
10:
    str r3,[r7,r4,lsl #2]     @ store new sum in array
    add r4,r4,#1              @ increment counter
    mov r0,r3                 @ new number = new sum
    b 1b                      @ and loop
    
99:                           @ display error
    ldr r0,iAdrszMessError
    bl affichageMess
100:
    pop {r3-r8,lr}            @ restaur registers
    bx lr
iAdrszMessResHead: .int szMessResHead
iAdrszLibPerf:     .int szLibPerf
iAdrszLibAmic:     .int szLibAmic
iAdrszLibSoc:      .int szLibSoc
iAdrszLibCycl:     .int szLibCycl
iAdrszLibAspi:     .int szLibAspi
iAdrszLibNoTerm:   .int szLibNoTerm
iAdrszLibTerm:     .int szLibTerm
iAdrtbNumberSucc:  .int tbNumberSucc
/******************************************************************/
/*     factor decomposition                                               */ 
/******************************************************************/
/* r0 contains number */
/* r1 contains address of divisors area */
/* r0 return divisors items in array    */
/* r1 return the sum of divisors  */
decompFact:
    push {r3-r12,lr}              @ save  registers
    cmp r0,#1
    moveq r1,#1
    beq 100f
    mov r5,r1
    mov r8,r0                    @ save number
    bl isPrime                   @ prime ?
    cmp r0,#1
    beq 98f                      @ yes is prime
    mov r1,#1
    str r1,[r5]                  @ first factor
    mov r12,#1                   @ divisors sum
    mov r10,#1                   @ indice divisors table
    mov r9,#2                    @ first divisor
    mov r6,#0                    @ previous divisor
    mov r7,#0                    @ number of same divisors
    
    /*  division loop  */
2:
    mov r0,r8                    @ dividende
    mov r1,r9                    @ divisor
    bl division                  @ r2 quotient r3 remainder
    cmp r3,#0
    beq 3f                       @ if remainder  zero  ->  divisor
    
        /* not divisor -> increment next divisor */
    cmp r9,#2                    @ if divisor = 2 -> add 1 
    addeq r9,#1
    addne r9,#2                  @ else add 2
    b 2b
    
       /* divisor   compute the new factors of number */
3:
    mov r8,r2                    @ else quotient -> new dividende
    cmp r9,r6                    @ same divisor ?
    beq 4f                       @ yes
    
    mov r0,r5                    @ table address
    mov r1,r10                   @ number factors in table
    mov r2,r9                    @ divisor
    mov r3,r12                   @ somme 
    mov r4,#0
    bl computeFactors
    cmp r0,#-1
    beq 100f
    mov r10,r1
    mov r12,r0
    mov r6,r9                    @ new divisor
    b 7f
    
4:                               @ same divisor
    sub r7,r10,#1
5:                              @ search in table the first use of divisor
    ldr r3,[r5,r7,lsl #2 ]
    cmp r3,r9
    subne r7,#1
    bne 5b
                                 @ and compute new factors after factors 
    sub r4,r10,r7                @ start indice
    mov r0,r5
    mov r1,r10
    mov r2,r9                    @ divisor
    mov r3,r12
    bl computeFactors
    cmp r0,#-1
    beq 100f
    mov r12,r0
    mov r10,r1

    
    /* divisor -> test if new dividende is prime */
7: 
    cmp r8,#1                    @ dividende = 1 ? -> end
    beq 10f
    mov r0,r8                    @ new dividende is prime ?
    mov r1,#0
    bl isPrime                   @ the new dividende is prime ?
    cmp r0,#1
    bne 10f                      @ the new dividende is not prime

    cmp r8,r6                    @ else dividende is same divisor ?
    beq 8f                       @ yes
    
    mov r0,r5
    mov r1,r10
    mov r2,r8
    mov r3,r12
    mov r4,#0
    bl computeFactors
    cmp r0,#-1
    beq 100f
    mov r12,r0
    mov r10,r1
    mov r7,#0
    b 11f
8:
    sub r7,r10,#1
9:
    ldr r3,[r5,r7,lsl #2 ]
    cmp r3,r8
    subne r7,#1
    bne 9b
    
    mov r0,r5
    mov r1,r10
    sub r4,r10,r7
    mov r2,r8
    mov r3,r12
    bl computeFactors
    cmp r0,#-1
    beq 100f
    mov r12,r0
    mov r10,r1
    
    b 11f
    
10:
    cmp r9,r8                    @ current divisor  > new dividende ?
    ble 2b                       @ no -> loop
    
    /* end decomposition */ 
11:
    mov r0,r10                  @ return number of table items
    mov r1,r12                  @ return sum 
    mov r3,#0
    str r3,[r5,r10,lsl #2]      @ store zéro in last table item
    b 100f

    
98:                             @ prime number
    add r1,r8,#1
    mov r0,#0                   @ return code
    b 100f
99:
    ldr r0,iAdrszMessError
    bl   affichageMess
    mov r0,#-1                  @ error code
    b 100f
100:
    pop {r3-r12,pc}             @ restaur registers
/******************************************************************/
/*    compute all factors                                         */ 
/******************************************************************/

/*   r0 table factors address */
/*   r1 number factors in table */
/*   r2 new divisor */
/*   r3 sum  */
/*   r4 start indice */
/*   r0 return sum */
/*   r1 return number factors in table */
computeFactors:
    push {r2-r6,lr}              @ save registers 
    mov r6,r1                    @ number factors in table
1:
    ldr r5,[r0,r4,lsl #2 ]       @ load one factor
    mul r5,r2,r5                 @ multiply 
    str r5,[r0,r1,lsl #2]        @ and store in the table

    adds r3,r5
    movcs r0,#-1                 @ overflow
    bcs 100f
    add r1,r1,#1                 @ and increment counter
    add r4,r4,#1
    cmp r4,r6
    blt 1b
    mov r0,r3                    @ factors sum
100:                             @ fin standard de la fonction 
    pop {r2-r6,pc}               @ restaur des registres
/***************************************************/
/*   check if a number is prime              */
/***************************************************/
/* r0 contains the number            */
/* r0 return 1 if prime  0 else */
isPrime:
    push {r1-r6,lr}    @ save registers 
    cmp r0,#0
    beq 90f
    cmp r0,#17
    bhi 1f
    cmp r0,#3
    bls 80f            @ for 1,2,3 return prime
    cmp r0,#5
    beq 80f            @ for 5 return prime
    cmp r0,#7
    beq 80f            @ for 7 return prime
    cmp r0,#11
    beq 80f            @ for 11 return prime
    cmp r0,#13
    beq 80f            @ for 13 return prime
    cmp r0,#17
    beq 80f            @ for 17 return prime
1:
    tst r0,#1          @ even ?
    beq 90f            @ yes -> not prime
    mov r2,r0          @ save number
    sub r1,r0,#1       @ exposant n - 1
    mov r0,#3          @ base
    bl moduloPuR32     @ compute base power n - 1 modulo n
    cmp r0,#1
    bne 90f            @ if <> 1  -> not prime
 
    mov r0,#5
    bl moduloPuR32
    cmp r0,#1
    bne 90f
    
    mov r0,#7
    bl moduloPuR32
    cmp r0,#1
    bne 90f
    
    mov r0,#11
    bl moduloPuR32
    cmp r0,#1
    bne 90f
    
    mov r0,#13
    bl moduloPuR32
    cmp r0,#1
    bne 90f
    
    mov r0,#17
    bl moduloPuR32
    cmp r0,#1
    bne 90f
80:
    mov r0,#1        @ is prime
    b 100f
90:
    mov r0,#0        @ no prime
100:                 @ fin standard de la fonction 
    pop {r1-r6,pc}   @ restaur des registres
/********************************************************/
/*   Calcul modulo de b puissance e modulo m  */
/*    Exemple 4 puissance 13 modulo 497 = 445         */
/*                                             */
/********************************************************/
/* r0  nombre  */
/* r1 exposant */
/* r2 modulo   */
/* r0 return result  */
moduloPuR32:
    push {r1-r7,lr}    @ save registers  
    cmp r0,#0          @ verif <> zero 
    beq 100f
    cmp r2,#0          @ verif <> zero 
    beq 100f           @ TODO: v鲩fier les cas d erreur
1:
    mov r4,r2          @ save modulo
    mov r5,r1          @ save exposant 
    mov r6,r0          @ save base
    mov r3,#1          @ start result

    mov r1,#0          @ division de r0,r1 par r2
    bl division32R
    mov r6,r2          @ base <- remainder
2:
    tst r5,#1          @  exposant even or odd
    beq 3f
    umull r0,r1,r6,r3
    mov r2,r4
    bl division32R
    mov r3,r2          @ result <- remainder
3:
    umull r0,r1,r6,r6
    mov r2,r4
    bl division32R
    mov r6,r2          @ base <- remainder

    lsr r5,#1          @ left shift 1 bit
    cmp r5,#0          @ end ?
    bne 2b
    mov r0,r3
100:                   @ fin standard de la fonction
    pop {r1-r7,pc}     @ restaur des registres   

/***************************************************/
/*   division number 64 bits in 2 registers by number 32 bits */
/***************************************************/
/* r0 contains lower part dividende   */
/* r1 contains upper part dividende   */
/* r2 contains divisor   */
/* r0 return lower part quotient    */
/* r1 return upper part quotient    */
/* r2 return remainder               */
division32R:
    push {r3-r9,lr}    @ save registers
    mov r6,#0          @ init upper upper part remainder  !!
    mov r7,r1          @ init upper part remainder with upper part dividende
    mov r8,r0          @ init lower part remainder with lower part dividende
    mov r9,#0          @ upper part quotient 
    mov r4,#0          @ lower part quotient
    mov r5,#32         @ bits number
1:                     @ begin loop
    lsl r6,#1          @ shift upper upper part remainder
    lsls r7,#1         @ shift upper  part remainder
    orrcs r6,#1        
    lsls r8,#1         @ shift lower  part remainder
    orrcs r7,#1
    lsls r4,#1         @ shift lower part quotient
    lsl r9,#1          @ shift upper part quotient
    orrcs r9,#1
                       @ divisor sustract  upper  part remainder
    subs r7,r2
    sbcs  r6,#0        @ and substract carry
    bmi 2f             @ n駡tive ?
    
                       @ positive or equal
    orr r4,#1          @ 1 -> right bit quotient
    b 3f
2:                     @ negative 
    orr r4,#0          @ 0 -> right bit quotient
    adds r7,r2         @ and restaur remainder
    adc  r6,#0 
3:
    subs r5,#1         @ decrement bit size 
    bgt 1b             @ end ?
    mov r0,r4          @ lower part quotient
    mov r1,r9          @ upper part quotient
    mov r2,r7          @ remainder
100:                   @ function end
    pop {r3-r9,pc}     @ restaur registers

/***************************************************/
/*      ROUTINES INCLUDE                 */
/***************************************************/
.include "../affichage.inc"

  

You may also check:How to resolve the algorithm Flatten a list step by step in the Quackery programming language
You may also check:How to resolve the algorithm Man or boy test step by step in the Common Lisp programming language
You may also check:How to resolve the algorithm Repeat step by step in the F# programming language
You may also check:How to resolve the algorithm Binary search step by step in the COBOL programming language
You may also check:How to resolve the algorithm Mutex step by step in the Objeck programming language