Zumkeller numbers: Difference between revisions

add new version to arm assembly raspberry pi
m (→‎{{header|Standard ML}}: improvement for 3d part)
(add new version to arm assembly raspberry pi)
Line 552:
{{works with|as|Raspberry Pi}}
<lang ARM Assembly>
 
/* ARM assembly Raspberry PI */
/* program zumkellerzumkeller4.s */
/* new version 10/2020 */
 
/* 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 NBDIVISORS, 1000
/* REMARK 2 : this program is not optimized.
Not search First 40 odd Zumkeller numbers not divisible by 5 */
/*******************************************/
/* Constantes */
/*******************************************/
.equ STDOUT, 1 @ Linux output console
.equ EXIT, 1 @ Linux syscall
.equ WRITE, 4 @ Linux syscall
 
.equ NBDIVISORS, 100
 
/*******************************************/
/* Structures */
/********************************************/
/* structurea area divisors */
.struct 0
div_ident: // ident
.struct div_ident + 4
div_flag: // value 0, 1 or 2
.struct div_flag + 4
div_fin:
/*******************************************/
/* Initialized data */
Line 590 ⟶ 576:
szMessErrorArea: .asciz "\033[31mError : area divisors too small.\n"
szMessError: .asciz "\033[31mError !!!\n"
szMessErrGen: .asciz "Error end program.\n"
szMessNbPrem: .asciz "This number is prime !!!.\n"
szMessResultFact: .asciz "@ "
 
szCarriageReturn: .asciz "\n"
Line 603 ⟶ 592:
.asciz ""
 
szMessEntete1: .asciz "The first 40 odd Zumkeller numbers are:\n"
szMessEntete2: .asciz "First 40 odd Zumkeller numbers not divisible by 5:\n"
/*******************************************/
/* UnInitialized data */
Line 609 ⟶ 599:
.bss
.align 4
tbDivisorssZoneConv: .skip div_fin * NBDIVISORS // area divisors24
tbZoneDecom: .skip 8 * NBDIVISORS // facteur 4 octets, nombre 4
/*******************************************/
/* code section */
Line 619 ⟶ 610:
bl affichageMess
 
ldr r0,iAdrszMessEntete @ display result message
bl affichageMess
mov r2,#1 @ counter number
mov r3,#0 @ counter zumkeller number
mov r4,#0 @ counter for line display
1:
mov r0,r2 @ number
mov r1,#0 @ display flag
bl testZumkeller
cmp r0,#1 @ zumkeller ?
bne 3f @ no
mov r0,r2
ldr r1,iAdrsNumber @ and convert ascii string
Line 638 ⟶ 628:
cmp r4,#20
blt 2f
add r1,r1,#3 @ carriage return at end of display line
mov r0,#'\n'
strb r0,[r1]
mov r0,#0
strb r0,[r1,#1] @ end of display line
ldr r0,iAdrsNumber @ display result message
bl affichageMess
mov r4,#0
2:
add r3,r3,#1 @ increment counter
3:
add r2,r2,#1 @ increment number
cmp r3,#220 @ end ?
blt 1b
 
Line 661 ⟶ 651:
4:
mov r0,r2 @ number
mov r1,#0 @ display flag
bl testZumkeller
cmp r0,#1
Line 687 ⟶ 676:
cmp r3,#40
blt 4b
/* odd zumkeller numbers not multiple5 */
 
61:
ldr r0,iAdrszMessEntete2
bl affichageMess
mov r3,#0
mov r4,#0
7:
lsr r8,r2,#3 @ divide counter by 5
add r8,r8,r2,lsr #4
add r8,r8,r8,lsr #4
add r8,r8,r8,lsr #8
add r8,r8,r8,lsr #16
add r9,r8,r8,lsl #2 @ multiply result by 5
sub r9,r2,r9
mov r6,#13
mul r9,r6,r9
lsr r9,#6
add r9,r8 @ it is a quotient
add r9,r9,r9,lsl #2 @ multiply by 5
sub r9,r2,r9 @ compute remainder
cmp r9,#0 @ remainder = zero ?
beq 9f
mov r0,r2 @ number
bl testZumkeller
cmp r0,#1
bne 9f
mov r0,r2
ldr r1,iAdrsNumber @ and convert ascii string
lsl r5,r4,#3
add r1,r5
bl conversion10
add r4,r4,#1
cmp r4,#8
blt 8f
add r1,r1,#8
mov r0,#'\n'
strb r0,[r1]
mov r0,#0
strb r0,[r1,#1]
ldr r0,iAdrsNumber @ display result message
bl affichageMess
mov r4,#0
8:
add r3,r3,#1
9:
add r2,r2,#2
cmp r3,#40
blt 7b
 
ldr r0,iAdrszMessEndPgm @ display end message
Line 705 ⟶ 741:
iAdrszMessResult: .int szMessResult
iAdrsValue: .int sValue
iAdrtbZoneDecom: .int tbZoneDecom
iAdrszMessEntete: .int szMessEntete
iAdrszMessEntete1: .int szMessEntete1
iAdrszMessEntete2: .int szMessEntete2
iAdrsNumber: .int sNumber
 
Line 713 ⟶ 751:
/******************************************************************/
/* r0 contains the number */
/* r1 contains display flag (<>0: display, 0: no display )
/* r0 return 1 if Zumkeller number else return 0 */
testZumkeller:
push {r1-r8r6,lr} @ save registers
mov r8r6,r0 @ save number
ldr r1,iAdrtbZoneDecom
mov r7,r1 @ save flag
bl decompFact @ create area of divisors
ldr r1,iAdrtbDivisors
blcmp divisorsr0,#1 @ create area of@ no divisors
movle r0,#0
cmp r0,#0 @ 0 divisors or error ?
movle r0,#-1
ble 100f
movtst r5r2,r0#1 @ numberodd ofsum dividers?
mov r6,r1 @ number of odd dividers
cmp r7,#1 @ display divisors ?
bne 1f
ldr r0,iAdrszMessListDivi @ yes
bl affichageMess
mov r0,r5
mov r1,#0
ldr r2,iAdrtbDivisors
bl printHeap
1:
tst r6,#1 @ number of odd divisors is odd ?
movne r0,#0 @ yes -> end
bne 100f
mov r0,r5
mov r1,#0
ldr r2,iAdrtbDivisors
bl sumDivisors @ compute divisors sum
tst r0,#1 @ sum is odd ?
movne r0,#0
bne 100f @ yes -> end
lsrtst r6,r0r1,#1 @ computenumber of odd divisors is sumodd /2?
movne r0,#0
mov r0,r6 @ r0 contains sum / 2
movbne 100f r1,#1 @ firstyes -> heapend
movlsl r3r5,r6,r5#1 @ @abondant number divisors
cmp r5,r2
mov r4,#0 @ N° element to start
movgt r0,#0
bl searchHeap
bgt 100f @ no -> end
cmp r0,#-2
mov r3,r0
beq 100f @ end
mov r4,r2 @ save sum
cmp r0,#-1
ldr r0,iAdrtbZoneDecom
beq 100f @ end
mov r1,#0
 
mov r2,r3
cmp r7,#1 @ print flag ?
bl shellSort @ sort table
bne 2f
ldr r0,iAdrszMessListDiviHeap
mov r1,r3 @ factors number
bl affichageMess
ldr r0,iAdrtbZoneDecom
mov r0,r5 @ yes print divisors of first heap
lsr r2,r4,#1 @ sum / 2
ldr r2,iAdrtbDivisors
bl computePartIter @
mov r1,#1
bl printHeap
2:
mov r0,#1 @ ok
 
100:
pop {r1-r8r6,lr} @ restaur registers
bx lr @ return
 
iAdrtbDivisors: .int tbDivisors
iAdrszMessListDiviHeap: .int szMessListDiviHeap
/******************************************************************/
/* search sumfactors divisors =to sum / 2 = entry value */
/******************************************************************/
/* r0 contains sumaddress toof searchdivisors area */
/* r1 contains elements flag (1 or 2)number */
/* r2 contains addressdivisors ofsum divisors/ 2 area */
/* r3r0 containsreturn elements1 numberif ok 0 else */
computePartIter:
/* r4 contains N° element to start */
push {r1-r7,fp,lr} @ save registers
/* r0 return -2 end search */
lsl r7,r1,#3 @ compute size of temp table
/* r0 return -1 no heap */
sub sp,r7 @ and reserve on stack
/* r0 return 0 Ok */
mov fp,sp @ frame pointer = stack address = begin table
/* recursive routine */
mov r5,#0 @ stack indice
searchHeap:
sub r3,r1,#1
push {r1-r8,lr} @ save registers
1:
cmpldr r4,[r0,r3,lsl #2] @ indice = elementsload numberfactor
moveqcmp r0r4,#-2r2 @ yes ->@ compare endvalue
beqbgt 100f2f
lslbeq 90f r6,r4,#3 @ computeequal -> elementend addressok
cmp r3,#0 @ first item ?
add r6,r2
beq 3f
ldr r7,[r6,#div_flag] @ flag equal ?
sub r3,#1 @ push indice item in temp table
cmp r7,#0
bneadd 6fr6,fp,r5,lsl #3
ldrstr r5r3,[r6,#div_ident]
cmpstr r5r2,r0 [r6,#4] @ elementpush valuesum =in remainingtemp amounttable
add r5,#1
beq 7f @ yes
bgtsub 6fr2,r4 @ substract divisors from @ too large sum
@ too less
mov r8,r0 @ save sum
sub r0,r0,r5 @ new sum to find
add r4,r4,#1 @ next divisors
bl searchHeap @ other search
cmp r0,#0 @ find -> ok
beq 5f
mov r0,r8 @ sum begin
sub r4,r4,#1 @ prev divisors
bl razFlags @ zero in all flags > current element
4:
add r4,r4,#1 @ last divisors
b 1b
2:
sub r3,#1 @ other divisors
cmp r3,#0 @ first item ?
bge 1b
3: @ first item
cmp r5,#0 @ stack empty ?
moveq r0,#0 @ no sum factors equal to value
beq 100f @ end
sub r5,#1 @ else pop stack
add r6,fp,r5,lsl #3 @ and restaur
ldr r3,[r6] @ indice
ldr r2,[r6,#4] @ and value
b 1b @ and loop
90:
mov r0,#1 @ it is ok
100:
add sp,r7 @ stack alignement
pop {r1-r7,fp,lr} @ restaur registers
bx lr @ return
 
/******************************************************************/
/* factor decomposition */
/******************************************************************/
/* r0 contains number */
/* r1 contains address of divisors area */
/* r0 return divisors items in table */
/* r1 return the number of odd divisors */
/* r2 return the sum of divisors */
decompFact:
push {r3-r8,lr} @ save registers
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 r11,#1 @ number odd divisors
mov r4,#1 @ indice divisors table
mov r1,#2 @ first divisor
mov r6,#0 @ previous divisor
mov r7,#0 @ number of same divisors
2:
mov r0,r8 @ dividende
bl division @ r1 divisor r2 quotient r3 remainder
cmp r3,#0
bne 5f @ if remainder <> zero -> no divisor
mov r8,r2 @ else quotient -> new dividende
cmp r1,r6 @ same divisor ?
beq 4f @ yes
mov r7,r4 @ number factors in table
mov r9,#0 @ indice
21:
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
tst r10,#1 @ divisor odd ?
addne r11,#1
add r12,r10
add r7,r7,#1 @ and increment counter
add r9,r9,#1
cmp r9,r4
blt 21b
mov r4,r7
mov r6,r1 @ new divisor
b 7f
4: @ same divisor
sub r9,r4,#1
mov r7,r4
41:
ldr r10,[r5,r9,lsl #2 ]
cmp r10,r1
subne r9,#1
bne 41b
sub r9,r4,r9
42:
ldr r10,[r5,r9,lsl #2 ]
mul r10,r1,r10
str r10,[r5,r7,lsl #2] @ and store in the table
tst r10,#1 @ divsor odd ?
addne r11,#1
add r12,r10
add r7,r7,#1 @ and increment counter
add r9,r9,#1
cmp r9,r4
blt 42b
mov r4,r7
b 7f @ and loop
/* not divisor -> increment next divisor */
5:
strcmp r1,[r6,#div_flag]2 @ flagif divisor = 2 -> areaadd element1 flag
addeq r1,#1
addne r1,#2 @ else add 2
b 2b
/* divisor -> test if new dividende is prime */
7:
mov r3,r1 @ save divisor
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 9f @ yes
mov r7,r4 @ number factors in table
mov r9,#0 @ indice
71:
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
tst r10,#1 @ divsor odd ?
addne r11,#1
add r12,r10
add r7,r7,#1 @ and increment counter
add r9,r9,#1
cmp r9,r4
blt 71b
mov r4,r7
mov r7,#0
b 11f
9:
sub r9,r4,#1
mov r7,r4
91:
ldr r10,[r5,r9,lsl #2 ]
cmp r10,r8
subne r9,#1
bne 91b
sub r9,r4,r9
92:
ldr r10,[r5,r9,lsl #2 ]
mul r10,r8,r10
str r10,[r5,r7,lsl #2] @ and store in the table
tst r10,#1 @ divisor odd ?
addne r11,#1
add r12,r10
add r7,r7,#1 @ and increment counter
add r9,r9,#1
cmp r9,r4
blt 92b
mov r4,r7
b 11f
10:
mov r1,r3 @ current divisor = new divisor
cmp r1,r8 @ current divisor > new dividende ?
ble 2b @ no -> loop
/* end decomposition */
11:
mov r0,r4 @ return number of table items
mov r2,r12 @ return sum
mov r1,r11 @ return number of odd divisor
mov r3,#0
str r3,[r5,r4,lsl #2] @ store zéro in last table item
b 100f
 
6:
add r4,r4,#1 @ last divisors
98:
b 1b
//ldr r0,iAdrszMessNbPrem
7:
//bl affichageMess
str r1,[r6,#div_flag] @ flag -> area element flag
mov r0,#01 @ searchreturn okcode
b 100f
99:
ldr r0,iAdrszMessError
bl affichageMess
mov r0,#-1 @ error code
b 100f
8:
mov r0,#-1 @ end search
100:
pop {r1r3-r8,lr} @ restaur registers
bx lr @ return
iAdrszMessNbPrem: .int szMessNbPrem
/******************************************************************/
/***************************************************/
/* raz flags */
/* check if a number is prime */
/******************************************************************/
/***************************************************/
/* r0 contains sum to search */
/* r1r0 contains the number flag (1 or 2) */
/* r2r0 containsreturn address1 ofif divisorsprime area 0 else */
@2147483647
/* r3 contains elements number */
@4294967297
/* r4 contains N° element to start */
@131071
/* r5 contains sum en cours */
isPrime:
razFlags:
push {r0r1-r6,lr} @ save registers
movcmp 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:
cmptst r4r0,r3 #1 @ indice > nb elementseven ?
bge 100f beq 90f @ yes -> endnot prime
mov r2,r0 @ save number
lsl r5,r4,#2
addsub r5r1,r5r0,r2#1 @ exposant n - @ compute address element1
ldrmov r6,[r5r0,#div_flag]3 @ load flag @ base
cmpbl r1,r6moduloPuR32 @ compute base power n - 1 modulo @ equal ?n
cmp r0,#1
streq r0,[r5,#div_flag] @ yes -> store 0
addbne r4,r4,#190f @ if <> 1 @ increment-> not indiceprime
b 1b @ and loop
mov r0,#5
100:
bl moduloPuR32
pop {r0-r6,lr} @ restaur registers
cmp r0,#1
bx lr @ return
bne 90f
/******************************************************************/
/* compute sum of divisors */
mov r0,#7
/******************************************************************/
bl moduloPuR32
/* r0 contains elements number */
cmp r0,#1
/* r1 contains flag (0 1 or 2)
bne 90f
/* r2 contains address of divisors area
/* r0 return divisors sum */
mov r0,#11
sumDivisors:
bl moduloPuR32
push {r1-r6,lr} @ save registers
cmp r0,#1
mov r3,#0 @ indice
bne 90f
mov r6,#0 @ sum
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,lr} @ restaur des registres
bx lr @ retour de la fonction en utilisant lr
/********************************************************/
/* 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érifier les cas d erreur
1:
lslmov r4,r3,#3 r2 @ N° element *save 8modulo
mov r5,r1 @ save exposant
add r4,r2
ldrmov r5r6,[r4,#div_flag]r0 @ compare flag @ save base
mov r3,#1 @ start result
cmp r5,r1
 
bne 2f
ldrmov r5,[r4r1,#div_ident]0 @ loaddivision de r0,r1 par valuer2
bl division32R
add r6,r6,r5 @ and add
mov r6,r2 @ base <- remainder
2:
tst r5,#1 @ exposant even or odd
add r3,r3,#1
cmpbeq r3,r03f
bltumull 1br0,r1,r6,r3
mov r0r2,r6 @ return sumr4
bl division32R
100:
popmov {r1-r6r3,lr}r2 @ result <- @ restaur registersremainder
3:
bx lr @ return
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,lr} @ restaur des registres
bx lr @ retour de la fonction en utilisant lr
 
/***************************************************/
/* 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égative ?
@ 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,lr} @ restaur registers
bx lr
/***************************************************/
/* shell Sort */
/***************************************************/
 
/* r0 contains the address of table */
/* r1 contains the first element but not use !! */
/* this routine use first element at index zero !!! */
/* r2 contains the number of element */
shellSort:
push {r0-r7,lr} @save registers
sub r2,#1 @ index last item
mov r1,r2 @ init gap = last item
1: @ start loop 1
lsrs r1,#1 @ gap = gap / 2
beq 100f @ if gap = 0 -> end
mov r3,r1 @ init loop indice 1
2: @ start loop 2
ldr r4,[r0,r3,lsl #2] @ load first value
mov r5,r3 @ init loop indice 2
3: @ start loop 3
cmp r5,r1 @ indice < gap
blt 4f @ yes -> end loop 2
sub r6,r5,r1 @ index = indice - gap
ldr r7,[r0,r6,lsl #2] @ load second value
cmp r4,r7 @ compare values
strlt r7,[r0,r5,lsl #2] @ store if <
sublt r5,r1 @ indice = indice - gap
blt 3b @ and loop
4: @ end loop 3
str r4,[r0,r5,lsl #2] @ store value 1 at indice 2
add r3,#1 @ increment indice 1
cmp r3,r2 @ end ?
ble 2b @ no -> loop 2
b 1b @ yes loop for new gap
100: @ end function
pop {r0-r7,lr} @ restaur registers
bx lr @ return
/******************************************************************/
/* printdisplay heapdivisors function */
/******************************************************************/
/* r0 contains elementsaddress numberof divisors area */
/* r1 contains the flagnumber (0of area 1items or 2) */
displayDivisors:
/* r2 contains address of divisors area */
push {r2-r8,lr} @ save registers
printHeap:
cmp r1,#0
push {r0-r8,lr} @ save registers
movbeq r7,r0100f
mov r8r2,r1
mov r3,#0 @ indice
mov r4,r0
1:
lsladd r5,r4,r3,lsl #3 @ N° element * 82
ldr r0,[r5] @ load factor
add r4,r2
 
ldr r5,[r4,#div_flag]
cmpldr r5r1,r8iAdrsZoneConv
bl conversion10 @ call décimal conversion
bne 2f
ldr r0,[r4,#div_ident]iAdrszMessResultFact
ldr r1,iAdrsValue iAdrsZoneConv @ andinsert convertconversion asciiin stringmessage
bl conversion10strInsertAtCharInc
ldrbl affichageMess r0,iAdrszMessResult @ display result message
add r3,#1 @ other ithem
bl affichageMess
cmp r3,r2 @ items maxi ?
2:
add r3,r3,#1
cmp r3,r7
blt 1b
ldr r0,iAdrszCarriageReturn
bl affichageMess
b 100f
100:
pop {r0-r8,lr} @ restaur registers
bx lr @ return
/******************************************************************/
/* divisors function */
/******************************************************************/
/* r0 contains the number */
/* r1 contains address of divisors area
/* r0 return divisors number */
/* r1 return counter odd divisors */
divisors:
push {r2-r11,lr} @ save registers
cmp r0,#1 @ = 1 ?
movle r0,#0
ble 100f
mov r7,r0
mov r8,r1
mov r11,#1 @ counter odd divisors
mov r0,#1 @ first divisor = 1
str r0,[r8,#div_ident]
mov r0,#0
str r0,[r8,#div_flag]
tst r7,#1 @ number is odd ?
addne r11,#1
mov r0,r7 @ last divisor = N
add r10,r8,#8 @ store at next element
str r0,[r10,#div_ident]
mov r0,#0
str r0,[r10,#div_flag]
 
mov r6,#2 @ first divisor
mov r5,#2 @ Counter divisors
2: @ begin loop
mov r0,r7 @ dividende = number
mov r1,r6 @ divisor
bl division
cmp r3,#0 @ remainder = 0 ?
bne 3f
cmp r2,r6
blt 4f @ quot<divisor end
lsl r10,r5,#3 @ N° element * 8
add r10,r10,r8 @ and add at area begin address
str r2,[r10,#div_ident]
mov r0,#0
str r0,[r10,#div_flag]
add r5,r5,#1 @ increment counter
cmp r5,#NBDIVISORS @ area maxi ?
bge 99f
tst r2,#1
addne r11,#1 @ count odd divisors
cmp r2,r6 @ quotient = divisor ?
ble 4f
lsl r10,r5,#3 @ N° element * 8
add r10,r10,r8 @ and add at area begin address
str r6,[r10,#div_ident]
mov r0,#0
str r0,[r10,#div_flag]
add r5,r5,#1 @ increment counter
cmp r5,#NBDIVISORS @ area maxi ?
bge 99f
tst r6,#1
addne r11,#1 @ count odd divisors
3:
cmp r2,r6
ble 4f
add r6,r6,#1 @ increment divisor
b 2b @ and loop
 
4:
mov r0,r5 @ return divisors number
mov r1,r11 @ retourn count odd divisors
b 100f
99: @ error
ldr r0,iAdrszMessErrorArea
bl affichageMess
mov r0,#-1
100:
pop {r2-r11r8,lr} @ restaur registers
bx lr @ return
iAdrszMessResultFact: .int szMessResultFact
iAdrszMessListDivi: .int szMessListDivi
iAdrszMessErrorAreaiAdrsZoneConv: .int szMessErrorAreasZoneConv
/***************************************************/
/* ROUTINES INCLUDE */
Line 993 ⟶ 1,230:
.include "../affichage.inc"
</lang>
{{Output}}
<pre>
Program start
Line 1,014 ⟶ 1,250:
11655 12285 12705 12915 13545 14175 14805 15015
15435 16065 16695 17325 17955 18585 19215 19305
First 40 odd Zumkeller numbers not divisible by 5:
81081 153153 171171 189189 207207 223839 243243 261261
279279 297297 351351 459459 513513 567567 621621 671517
729729 742203 783783 793611 812889 837837 891891 908523
960687 999999 1024947 1054053 1072071 1073709 1095633 1108107
1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Program normal end.