/* ARM assembly Raspberry PI */ /* program arithnumber.s */ /************************************/ /* Constantes */ /************************************/ /* for this file see task include a file in language ARM assembly*/ .include "../constantes.inc" .equ NBDIVISORS, 2000 //.include "../../ficmacros32.inc" @ use for developper debugging /*******************************************/ /* Initialized data */ /*******************************************/ .data szMessStartPgm: .asciz "Program 32 bits start. \n" szMessEndPgm: .asciz "Program normal end.\n" szMessErrorArea: .asciz "\033[31mError : area divisors too small.\n" szMessError: .asciz "\033[31mError !!!\n" szMessErrGen: .asciz "Error end program.\n" szMessResultFact: .asciz "@ " szCarriageReturn: .asciz "\n" szMessEntete: .asciz "The first 150 arithmetic numbers are:\n" szMessResult: .asciz " @ " szMessEntete1: .asciz "The 1000 aritmetic number :" szMessEntete2: .asciz "The 10000 aritmetic number :" szMessEntete3: .asciz "The 100000 aritmetic number :" szMessEntete4: .asciz "The 1000000 aritmetic number :" szMessComposite: .asciz "Composite number : " /*******************************************/ /* UnInitialized data */ /*******************************************/ .bss .align 4 sZoneConv: .skip 24 tbZoneDecom: .skip 4 * NBDIVISORS // facteur 4 octets /*******************************************/ /* code section */ /*******************************************/ .text .global main main: @ program start ldr r0,iAdrszMessStartPgm @ display start message bl affichageMess ldr r0,iAdrszMessEntete @ display result message bl affichageMess mov r2,#1 @ start number mov r3,#0 @ counter result mov r6,#0 @ counter result by line 1: mov r0,r2 @ number ldr r1,iAdrtbZoneDecom bl testNbArith @ test cmp r0,#1 @ ok ? bne 3f add r3,#1 mov r0,r2 @ number ldr r1,iAdrsZoneConv bl conversion10 @ convert ascii string ldr r0,iAdrszMessResult ldr r1,iAdrsZoneConv bl strInsertAtCharInc @ and put in message bl affichageMess add r6,r6,#1 cmp r6,#6 blt 3f mov r6,#0 ldr r0,iAdrszCarriageReturn bl affichageMess 3: add r2,r2,#1 cmp r3,#100 blt 1b ldr r0,iAdrszCarriageReturn bl affichageMess /* count arithmetic number */ mov r2,#1 mov r3,#0 ldr r5,iN10P4 ldr r6,iN10P5 ldr r7,iN10P6 mov r8,#0 @ counter composite 4: mov r0,r2 @ number ldr r1,iAdrtbZoneDecom bl testNbArith cmp r0,#1 bne 6f cmp r1,#1 bne 5f add r8,r8,#1 5: add r3,#1 6: cmp r3,#1000 beq 7f cmp r3,r5 @ 10000 beq 8f cmp r3,r6 @ 100000 beq 9f cmp r3,r7 @ 1000000 beq 10f b 11f 7: ldr r0,iAdrszMessEntete1 bl affichageMess mov r0,r2 mov r4,r1 @ save sum ldr r1,iAdrsZoneConv bl conversion10 @ convert ascii string mov r0,r1 bl affichageMess ldr r0,iAdrszMessComposite bl affichageMess mov r0,r8 ldr r1,iAdrsZoneConv bl conversion10 @ convert ascii string mov r0,r1 bl affichageMess ldr r0,iAdrszCarriageReturn bl affichageMess b 11f 8: ldr r0,iAdrszMessEntete2 bl affichageMess mov r0,r2 mov r4,r1 @ save sum ldr r1,iAdrsZoneConv bl conversion10 @ convert ascii string mov r0,r1 bl affichageMess ldr r0,iAdrszMessComposite bl affichageMess mov r0,r8 ldr r1,iAdrsZoneConv bl conversion10 @ convert ascii string mov r0,r1 bl affichageMess ldr r0,iAdrszCarriageReturn bl affichageMess b 11f 9: ldr r0,iAdrszMessEntete3 bl affichageMess mov r0,r2 mov r4,r1 @ save sum ldr r1,iAdrsZoneConv bl conversion10 @ convert ascii string mov r0,r1 bl affichageMess ldr r0,iAdrszMessComposite bl affichageMess mov r0,r8 ldr r1,iAdrsZoneConv bl conversion10 @ convert ascii string mov r0,r1 bl affichageMess ldr r0,iAdrszCarriageReturn bl affichageMess b 11f 10: ldr r0,iAdrszMessEntete4 bl affichageMess mov r0,r2 mov r4,r1 @ save sum ldr r1,iAdrsZoneConv bl conversion10 @ convert ascii string mov r0,r1 bl affichageMess ldr r0,iAdrszMessComposite bl affichageMess mov r0,r8 ldr r1,iAdrsZoneConv bl conversion10 @ convert ascii string mov r0,r1 bl affichageMess ldr r0,iAdrszCarriageReturn bl affichageMess b 12f 11: add r2,r2,#1 b 4b 12: 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 iAdrszMessEntete: .int szMessEntete iAdrszMessEntete1: .int szMessEntete1 iAdrszMessEntete2: .int szMessEntete2 iAdrszMessEntete3: .int szMessEntete3 iAdrszMessEntete4: .int szMessEntete4 iAdrszMessResult: .int szMessResult iAdrszMessComposite: .int szMessComposite iAdrsZoneConv: .int sZoneConv iN10P4: .int 10000 iN10P5: .int 100000 iN10P6: .int 1000000 /******************************************************************/ /* test if number is aritmetic number */ /******************************************************************/ /* r0 contains number */ /* r1 contains address of divisors area */ /* r0 return 1 if ok else return 0 */ /* r1 return 1 if composite */ testNbArith: push {r2-r11,lr} @ save registers cmp r0,#1 @ 1 is arithmetique moveq r0,#1 moveq r1,#0 beq 100f cmp r0,#2 @ 2 is not aritmetic moveq r0,#0 moveq r1,#0 beq 100f mov r5,r1 mov r8,r0 @ save number bl isPrime @ prime ? cmp r0,#1 moveq r0,#1 @ yes is prime and arithmetic moveq r1,#0 @ but not composite beq 100f @ end mov r1,#1 str r1,[r5] @ first factor mov r11,#1 @ divisors sum mov r4,#1 @ indice divisors table mov r1,#2 @ first divisor mov r6,#0 @ previous divisor mov r7,#0 @ number of same divisors 1: mov r0,r8 @ dividende bl division @ r1 divisor r2 quotient r3 remainder cmp r3,#0 bne 6f @ if remainder <> zero -> no divisor mov r8,r2 @ else quotient -> new dividende cmp r1,r6 @ same divisor ? beq 3f @ yes mov r7,r4 @ number factors in table mov r9,#0 @ indice 2: @ for each new prime factor compute all factors of number ldr r10,[r5,r9,lsl #2 ] @ load one factor mul r10,r1,r10 @ multiply str r10,[r5,r7,lsl #2] @ and store in the table add r11,r10 @ sum of factors add r7,r7,#1 @ and increment counter add r9,r9,#1 @ increment index cmp r9,r4 @ end array factors ? blt 2b mov r4,r7 mov r6,r1 @ new divisor b 7f 3: @ same divisor sub r9,r4,#1 mov r7,r4 4: @ for each prime factor compute all factors of number ldr r10,[r5,r9,lsl #2 ] @ this prime factor is in factor array ? cmp r10,r1 subne r9,#1 bne 4b sub r9,r4,r9 5: ldr r10,[r5,r9,lsl #2 ] mul r10,r1,r10 str r10,[r5,r7,lsl #2] @ and store in the table add r11,r10 add r7,r7,#1 @ and increment counter add r9,r9,#1 cmp r9,r4 blt 5b mov r4,r7 b 7f @ and loop /* not divisor -> increment next divisor */ 6: cmp r1,#2 @ if divisor = 2 -> add 1 addeq r1,#1 addne r1,#2 @ else add 2 b 1b @ and loop /* divisor -> test if new dividende is prime */ 7: mov r3,r1 @ save divisor cmp r8,#1 @ dividende = 1 ? -> end beq 13f mov r0,r8 @ new dividende is prime ? mov r1,#0 bl isPrime @ the new dividende is prime ? cmp r0,#1 bne 12f @ the new dividende is not prime cmp r8,r6 @ else new dividende prime is same divisor ? beq 9f @ yes @ no -> compute all factors mov r7,r4 @ number factors in table mov r9,#0 @ indice 8: ldr r10,[r5,r9,lsl #2 ] @ load one factor mul r10,r8,r10 @ multiply str r10,[r5,r7,lsl #2] @ and store in the table add r11,r10 add r7,r7,#1 @ and increment counter add r9,r9,#1 cmp r9,r4 blt 8b mov r4,r7 mov r7,#0 b 13f 9: sub r9,r4,#1 mov r7,r4 10: ldr r10,[r5,r9,lsl #2 ] cmp r10,r8 subne r9,#1 bne 10b sub r9,r4,r9 11: ldr r10,[r5,r9,lsl #2 ] mul r10,r8,r10 str r10,[r5,r7,lsl #2] @ and store in the table add r11,r10 add r7,r7,#1 @ and increment counter add r9,r9,#1 cmp r9,r4 blt 11b mov r4,r7 b 13f 12: mov r1,r3 @ current divisor = new divisor cmp r1,r8 @ current divisor > new dividende ? ble 1b @ no -> loop /* end decomposition */ 13: mov r1,r4 @ control if arithmetic mov r0,r11 @ compute average bl division mov r1,#1 cmp r3,#0 @ no remainder moveq r0,#1 @ average is integer beq 100f @ no -> end mov r0,#0 mov r1,#0 100: pop {r2-r11,pc} @ restaur registers //iAdrszMessNbPrem: .int szMessNbPrem /******************************************************************/ /* test if number is prime trial test */ /******************************************************************/ /* r0 contains the number */ /* r0 return 1 if prime else return 0 */ isPrime: push {r4,lr} @ save registers cmp r0,#1 @ <= 1 ? movls r0,#0 @ not prime bls 100f cmp r0,#3 @ 2 and 3 prime movls r0,#1 bls 100f tst r0,#1 @ even ? moveq r0,#0 @ not prime beq 100f mov r4,r0 @ save number mov r1,#3 @ first divisor 1: mov r0,r4 @ number bl division add r1,r1,#2 @ increment divisor cmp r3,#0 @ remainder = zero ? moveq r0,#0 @ not prime beq 100f cmp r1,r2 @ divisors<=quotient ? ble 1b @ loop mov r0,#1 @ return prime 100: pop {r4,pc} @ restaur registers /***************************************************/ /* ROUTINES INCLUDE */ /***************************************************/ /* for this file see task include a file in language ARM assembly*/ .include "../affichage.inc"