RosettaCodeData/Task/Arithmetic-numbers/ARM-Assembly/arithmetic-numbers.arm

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"