407 lines
13 KiB
Plaintext
407 lines
13 KiB
Plaintext
/* 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"
|