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