Achilles numbers: Difference between revisions
Content added Content deleted
(add task to arm assembly raspberry pi) |
(add task to aarch64 assembly raspberry pi) |
||
Line 46: | Line 46: | ||
=={{header|AArch64 Assembly}}== |
|||
{{works with|as|Raspberry Pi 3B version Buster 64 bits <br> or android 64 bits with application Termux }} |
|||
<lang AArch64 Assembly> |
|||
/* ARM assembly AARCH64 Raspberry PI 3B */ |
|||
/* program achilleNumber.s */ |
|||
/************************************/ |
|||
/* Constantes */ |
|||
/************************************/ |
|||
.include "../includeConstantesARM64.inc" |
|||
.equ NBFACT, 33 |
|||
.equ MAXI, 50 |
|||
.equ MAXI1, 20 |
|||
.equ MAXI2, 1000000 |
|||
/*********************************/ |
|||
/* Initialized data */ |
|||
/*********************************/ |
|||
.data |
|||
szMessNumber: .asciz " @ " |
|||
szCarriageReturn: .asciz "\n" |
|||
szErrorGen: .asciz "Program error !!!\n" |
|||
szMessPrime: .asciz "This number is prime.\n" |
|||
szMessErrGen: .asciz "Error end program.\n" |
|||
szMessNbPrem: .asciz "This number is prime !!!.\n" |
|||
szMessOverflow: .asciz "Overflow function isPrime.\n" |
|||
szMessError: .asciz "\033[31mError !!!\n" |
|||
szMessTitAchille: .asciz "First 50 Achilles Numbers:\n" |
|||
szMessTitStrong: .asciz "First 20 Strong Achilles Numbers:\n" |
|||
szMessDigitsCounter: .asciz "Numbers with @ digits : @ \n" |
|||
/*********************************/ |
|||
/* UnInitialized data */ |
|||
/*********************************/ |
|||
.bss |
|||
sZoneConv: .skip 24 |
|||
tbZoneDecom: .skip 16 * NBFACT // factor 8 bytes, number of each factor 8 bytes |
|||
/*********************************/ |
|||
/* code section */ |
|||
/*********************************/ |
|||
.text |
|||
.global main |
|||
main: // entry of program |
|||
ldr x0,qAdrszMessTitAchille |
|||
bl affichageMess |
|||
mov x4,#1 // start number |
|||
mov x5,#0 // total counter |
|||
mov x6,#0 // line display counter |
|||
1: |
|||
mov x0,x4 |
|||
bl controlAchille |
|||
cmp x0,#0 // achille number ? |
|||
beq 2f // no |
|||
mov x0,x4 |
|||
ldr x1,qAdrsZoneConv |
|||
bl conversion10 // call décimal conversion |
|||
ldr x0,qAdrszMessNumber |
|||
ldr x1,qAdrsZoneConv // insert conversion in message |
|||
bl strInsertAtCharInc |
|||
bl affichageMess // display message |
|||
add x5,x5,#1 // increment counter |
|||
add x6,x6,#1 // increment indice line display |
|||
cmp x6,#10 // if = 10 new line |
|||
bne 2f |
|||
mov x6,#0 |
|||
ldr x0,qAdrszCarriageReturn |
|||
bl affichageMess |
|||
2: |
|||
add x4,x4,#1 // increment number |
|||
cmp x5,#MAXI |
|||
blt 1b // and loop |
|||
ldr x0,qAdrszMessTitStrong |
|||
bl affichageMess |
|||
mov x4,#1 // start number |
|||
mov x5,#0 // total counter |
|||
mov x6,#0 |
|||
3: |
|||
mov x0,x4 |
|||
bl controlAchille |
|||
cmp x0,#0 |
|||
beq 4f |
|||
mov x0,x4 |
|||
bl computeTotient |
|||
bl controlAchille |
|||
cmp x0,#0 |
|||
beq 4f |
|||
mov x0,x4 |
|||
ldr x1,qAdrsZoneConv |
|||
bl conversion10 // call décimal conversion |
|||
ldr x0,qAdrszMessNumber |
|||
ldr x1,qAdrsZoneConv // insert conversion in message |
|||
bl strInsertAtCharInc |
|||
bl affichageMess // display message |
|||
add x5,x5,#1 |
|||
add x6,x6,#1 |
|||
cmp x6,#10 |
|||
bne 4f |
|||
mov x6,#0 |
|||
ldr x0,qAdrszCarriageReturn |
|||
bl affichageMess |
|||
4: |
|||
add x4,x4,#1 |
|||
cmp x5,#MAXI1 |
|||
blt 3b |
|||
ldr x3,icstMaxi2 |
|||
mov x4,#1 // start number |
|||
mov x6,#0 // total counter 2 digits |
|||
mov x7,#0 // total counter 3 digits |
|||
mov x8,#0 // total counter 4 digits |
|||
mov x9,#0 // total counter 5 digits |
|||
mov x10,#0 // total counter 6 digits |
|||
5: |
|||
mov x0,x4 |
|||
bl controlAchille |
|||
cmp x0,#0 |
|||
beq 10f |
|||
mov x0,x4 |
|||
ldr x1,qAdrsZoneConv |
|||
bl conversion10 // call décimal conversion x0 return digit number |
|||
cmp x0,#6 |
|||
bne 6f |
|||
add x10,x10,#1 |
|||
beq 10f |
|||
6: |
|||
cmp x0,#5 |
|||
bne 7f |
|||
add x9,x9,#1 |
|||
b 10f |
|||
7: |
|||
cmp x0,#4 |
|||
bne 8f |
|||
add x8,x8,#1 |
|||
b 10f |
|||
8: |
|||
cmp x0,#3 |
|||
bne 9f |
|||
add x7,x7,#1 |
|||
b 10f |
|||
9: |
|||
cmp x0,#2 |
|||
bne 10f |
|||
add x6,x6,#1 |
|||
10: |
|||
add x4,x4,#1 |
|||
cmp x4,x3 |
|||
blt 5b |
|||
mov x0,#2 |
|||
mov x1,x6 |
|||
bl displayCounter |
|||
mov x0,#3 |
|||
mov x1,x7 |
|||
bl displayCounter |
|||
mov x0,#4 |
|||
mov x1,x8 |
|||
bl displayCounter |
|||
mov x0,#5 |
|||
mov x1,x9 |
|||
bl displayCounter |
|||
mov x0,#6 |
|||
mov x1,x10 |
|||
bl displayCounter |
|||
b 100f |
|||
98: |
|||
ldr x0,qAdrszErrorGen |
|||
bl affichageMess |
|||
100: // standard end of the program |
|||
mov x0, #0 // return code |
|||
mov x8,EXIT |
|||
svc #0 // perform the system call |
|||
qAdrszCarriageReturn: .quad szCarriageReturn |
|||
qAdrszErrorGen: .quad szErrorGen |
|||
qAdrsZoneConv: .quad sZoneConv |
|||
qAdrtbZoneDecom: .quad tbZoneDecom |
|||
qAdrszMessNumber: .quad szMessNumber |
|||
qAdrszMessTitAchille: .quad szMessTitAchille |
|||
qAdrszMessTitStrong: .quad szMessTitStrong |
|||
icstMaxi2: .quad MAXI2 |
|||
/******************************************************************/ |
|||
/* display digit counter */ |
|||
/******************************************************************/ |
|||
/* x0 contains limit */ |
|||
/* x1 contains counter */ |
|||
displayCounter: |
|||
stp x1,lr,[sp,-16]! // save registers |
|||
stp x2,x3,[sp,-16]! // save registers |
|||
mov x2,x1 |
|||
ldr x1,qAdrsZoneConv |
|||
bl conversion10 // call décimal conversion |
|||
ldr x0,qAdrszMessDigitsCounter |
|||
ldr x1,qAdrsZoneConv // insert conversion in message |
|||
bl strInsertAtCharInc |
|||
mov x3,x0 |
|||
mov x0,x2 |
|||
ldr x1,qAdrsZoneConv |
|||
bl conversion10 // call décimal conversion |
|||
mov x0,x3 |
|||
ldr x1,qAdrsZoneConv // insert conversion in message |
|||
bl strInsertAtCharInc |
|||
bl affichageMess // display message |
|||
100: |
|||
ldp x2,x3,[sp],16 // restaur registers |
|||
ldp x1,lr,[sp],16 // restaur registers |
|||
ret |
|||
qAdrszMessDigitsCounter: .quad szMessDigitsCounter |
|||
/******************************************************************/ |
|||
/* control if number is Achille number */ |
|||
/******************************************************************/ |
|||
/* x0 contains number */ |
|||
/* x0 return 0 if not else return 1 */ |
|||
controlAchille: |
|||
stp x1,lr,[sp,-16]! // save registers |
|||
stp x2,x3,[sp,-16]! // save registers |
|||
stp x4,x5,[sp,-16]! // save registers |
|||
mov x4,x0 |
|||
ldr x1,qAdrtbZoneDecom |
|||
bl decompFact // factor decomposition |
|||
cmp x0,#-1 |
|||
beq 99f // error ? |
|||
cmp x0,#1 // one only factor or prime ? |
|||
ble 98f |
|||
mov x1,x0 |
|||
ldr x0,qAdrtbZoneDecom |
|||
mov x2,x4 |
|||
bl controlDivisor |
|||
b 100f |
|||
98: |
|||
mov x0,#0 |
|||
b 100f |
|||
99: |
|||
ldr x0,qAdrszErrorGen |
|||
bl affichageMess |
|||
100: |
|||
ldp x4,x5,[sp],16 // restaur registers |
|||
ldp x2,x3,[sp],16 // restaur registers |
|||
ldp x1,lr,[sp],16 // restaur registers |
|||
ret |
|||
/******************************************************************/ |
|||
/* control divisors function */ |
|||
/******************************************************************/ |
|||
/* x0 contains address of divisors area */ |
|||
/* x1 contains the number of area items */ |
|||
/* x2 contains number */ |
|||
controlDivisor: |
|||
stp x1,lr,[sp,-16]! // save registers |
|||
stp x2,x3,[sp,-16]! // save registers |
|||
stp x4,x5,[sp,-16]! // save registers |
|||
stp x6,x7,[sp,-16]! // save registers |
|||
stp x8,x9,[sp,-16]! // save registers |
|||
stp x10,x11,[sp,-16]! // save registers |
|||
mov x6,x1 // factors number |
|||
mov x8,x2 // save number |
|||
mov x9,#0 // indice |
|||
mov x4,x0 // save area address |
|||
add x5,x4,x9,lsl #4 // compute address first factor |
|||
ldr x7,[x5,#8] // load first exposant of factor |
|||
add x2,x9,#1 |
|||
1: |
|||
add x5,x4,x2,lsl #4 // compute address next factor |
|||
ldr x3,[x5,#8] // load exposant of factor |
|||
cmp x3,x7 // factor exposant <> ? |
|||
bne 2f // yes -> end verif |
|||
add x2,x2,#1 // increment indice |
|||
cmp x2,x6 // factor maxi ? |
|||
blt 1b // no -> loop |
|||
mov x0,#0 |
|||
b 100f // all exposants are equals |
|||
2: |
|||
mov x10,x2 // save indice |
|||
21: |
|||
bge 22f |
|||
mov x2,x7 // if x3 < x7 -> inversion |
|||
mov x7,x3 |
|||
mov x3,x2 // x7 is the smaller exposant |
|||
22: |
|||
mov x0,x3 |
|||
mov x1,x7 // x7 < x3 |
|||
bl calPGCDmod |
|||
cmp x0,#1 |
|||
beq 24f // no commun multiple -> ne peux donc pas etre une puissance |
|||
23: |
|||
add x10,x10,#1 // increment indice |
|||
cmp x10,x6 // factor maxi ? |
|||
bge 99f // yes -> all exposants are multiples to smaller |
|||
add x5,x4,x10,lsl #4 |
|||
ldr x3,[x5,#8] // load exposant of next factor |
|||
cmp x3,x7 |
|||
beq 23b // for next |
|||
b 21b // for compare the 2 exposants |
|||
24: |
|||
mov x9,#0 // indice |
|||
3: |
|||
add x5,x4,x9,lsl #4 |
|||
ldr x7,[x5] // load factor |
|||
mul x1,x7,x7 // factor square |
|||
udiv x2,x8,x1 |
|||
msub x3,x1,x2,x8 // compute remainder |
|||
cmp x3,#0 // remainder null ? |
|||
bne 99f |
|||
add x9,x9,#1 // other factor |
|||
cmp x9,x6 // factors maxi ? |
|||
blt 3b |
|||
mov x0,#1 // achille number ok |
|||
b 100f |
|||
99: // achille not ok |
|||
mov x0,0 |
|||
100: |
|||
ldp x10,x11,[sp],16 // restaur registers |
|||
ldp x8,x9,[sp],16 // restaur registers |
|||
ldp x6,x7,[sp],16 // restaur registers |
|||
ldp x4,x5,[sp],16 // restaur registers |
|||
ldp x2,x3,[sp],16 // restaur registers |
|||
ldp x1,lr,[sp],16 // restaur registers |
|||
ret |
|||
/***************************************************/ |
|||
/* Compute pgcd modulo use */ |
|||
/***************************************************/ |
|||
/* x0 contains first number */ |
|||
/* x1 contains second number */ |
|||
/* x0 return PGCD */ |
|||
/* if error carry set to 1 */ |
|||
calPGCDmod: |
|||
stp x1,lr,[sp,-16]! // save registres |
|||
stp x2,x3,[sp,-16]! // save registres |
|||
cbz x0,99f // if = 0 error |
|||
cbz x1,99f |
|||
cmp x0,0 |
|||
bgt 1f |
|||
neg x0,x0 // if negative inversion number 1 |
|||
1: |
|||
cmp x1,0 |
|||
bgt 2f |
|||
neg x1,x1 // if negative inversion number 2 |
|||
2: |
|||
cmp x0,x1 // compare two numbers |
|||
bgt 3f |
|||
mov x2,x0 // inversion |
|||
mov x0,x1 |
|||
mov x1,x2 |
|||
3: |
|||
udiv x2,x0,x1 // division |
|||
msub x0,x2,x1,x0 // compute remainder |
|||
cmp x0,0 |
|||
bgt 2b // loop |
|||
mov x0,x1 |
|||
cmn x0,0 // clear carry |
|||
b 100f |
|||
99: // error |
|||
mov x0,0 |
|||
cmp x0,0 // set carry |
|||
100: |
|||
ldp x2,x3,[sp],16 // restaur des 2 registres |
|||
ldp x1,lr,[sp],16 // restaur des 2 registres |
|||
ret // retour adresse lr x30 |
|||
/******************************************************************/ |
|||
/* compute totient of number */ |
|||
/******************************************************************/ |
|||
/* x0 contains number */ |
|||
computeTotient: |
|||
stp x1,lr,[sp,-16]! // save registers |
|||
stp x2,x3,[sp,-16]! // save registers |
|||
stp x4,x5,[sp,-16]! // save registers |
|||
mov x4,x0 // totient |
|||
mov x5,x0 // save number |
|||
mov x1,#0 // for first divisor |
|||
1: // begin loop |
|||
mul x3,x1,x1 // compute square |
|||
cmp x3,x5 // compare number |
|||
bgt 4f // end |
|||
add x1,x1,#2 // next divisor |
|||
udiv x2,x5,x1 |
|||
msub x3,x1,x2,x5 // compute remainder |
|||
cmp x3,#0 // remainder null ? |
|||
bne 3f |
|||
2: // begin loop 2 |
|||
udiv x2,x5,x1 |
|||
msub x3,x1,x2,x5 // compute remainder |
|||
cmp x3,#0 |
|||
csel x5,x2,x5,eq // new value = quotient |
|||
beq 2b |
|||
udiv x2,x4,x1 // divide totient |
|||
sub x4,x4,x2 // compute new totient |
|||
3: |
|||
cmp x1,#2 // first divisor ? |
|||
mov x0,1 |
|||
csel x1,x0,x1,eq // divisor = 1 |
|||
b 1b // and loop |
|||
4: |
|||
cmp x5,#1 // final value > 1 |
|||
ble 5f |
|||
mov x0,x4 // totient |
|||
mov x1,x5 // divide by value |
|||
udiv x2,x4,x5 // totient divide by value |
|||
sub x4,x4,x2 // compute new totient |
|||
5: |
|||
mov x0,x4 |
|||
100: |
|||
ldp x4,x5,[sp],16 // restaur registers |
|||
ldp x2,x3,[sp],16 // restaur registers |
|||
ldp x1,lr,[sp],16 // restaur registers |
|||
ret |
|||
/******************************************************************/ |
|||
/* factor decomposition */ |
|||
/******************************************************************/ |
|||
/* x0 contains number */ |
|||
/* x1 contains address of divisors area */ |
|||
/* x0 return divisors items in table */ |
|||
decompFact: |
|||
stp x1,lr,[sp,-16]! // save registers |
|||
stp x2,x3,[sp,-16]! // save registers |
|||
stp x4,x5,[sp,-16]! // save registers |
|||
stp x6,x7,[sp,-16]! // save registers |
|||
stp x8,x9,[sp,-16]! // save registers |
|||
mov x5,x1 |
|||
mov x8,x0 // save number |
|||
bl isPrime // prime ? |
|||
cmp x0,#1 |
|||
beq 98f // yes is prime |
|||
mov x4,#0 // raz indice |
|||
mov x1,#2 // first divisor |
|||
mov x6,#0 // previous divisor |
|||
mov x7,#0 // number of same divisors |
|||
2: |
|||
udiv x2,x8,x1 // divide number or other result |
|||
msub x3,x2,x1,x8 // compute remainder |
|||
cmp x3,#0 |
|||
bne 5f // if remainder <> zero -> no divisor |
|||
mov x8,x2 // else quotient -> new dividende |
|||
cmp x1,x6 // same divisor ? |
|||
beq 4f // yes |
|||
cmp x6,#0 // no but is the first divisor ? |
|||
beq 3f // yes |
|||
str x6,[x5,x4,lsl #3] // else store in the table |
|||
add x4,x4,#1 // and increment counter |
|||
str x7,[x5,x4,lsl #3] // store counter |
|||
add x4,x4,#1 // next item |
|||
mov x7,#0 // and raz counter |
|||
3: |
|||
mov x6,x1 // new divisor |
|||
4: |
|||
add x7,x7,#1 // increment counter |
|||
b 7f // and loop |
|||
/* not divisor -> increment next divisor */ |
|||
5: |
|||
cmp x1,#2 // if divisor = 2 -> add 1 |
|||
mov x0,#1 |
|||
mov x3,#2 // else add 2 |
|||
csel x3,x0,x3,eq |
|||
add x1,x1,x3 |
|||
b 2b |
|||
/* divisor -> test if new dividende is prime */ |
|||
7: |
|||
mov x3,x1 // save divisor |
|||
cmp x8,#1 // dividende = 1 ? -> end |
|||
beq 10f |
|||
mov x0,x8 // new dividende is prime ? |
|||
mov x1,#0 |
|||
bl isPrime // the new dividende is prime ? |
|||
cmp x0,#1 |
|||
bne 10f // the new dividende is not prime |
|||
cmp x8,x6 // else dividende is same divisor ? |
|||
beq 9f // yes |
|||
cmp x6,#0 // no but is the first divisor ? |
|||
beq 8f // yes it is a first |
|||
str x6,[x5,x4,lsl #3] // else store in table |
|||
add x4,x4,#1 // and increment counter |
|||
str x7,[x5,x4,lsl #3] // and store counter |
|||
add x4,x4,#1 // next item |
|||
8: |
|||
mov x6,x8 // new dividende -> divisor prec |
|||
mov x7,#0 // and raz counter |
|||
9: |
|||
add x7,x7,#1 // increment counter |
|||
b 11f |
|||
10: |
|||
mov x1,x3 // current divisor = new divisor |
|||
cmp x1,x8 // current divisor > new dividende ? |
|||
ble 2b // no -> loop |
|||
/* end decomposition */ |
|||
11: |
|||
str x6,[x5,x4,lsl #3] // store last divisor |
|||
add x4,x4,#1 |
|||
str x7,[x5,x4,lsl #3] // and store last number of same divisors |
|||
add x4,x4,#1 |
|||
lsr x0,x4,#1 // return number of table items |
|||
mov x3,#0 |
|||
str x3,[x5,x4,lsl #3] // store zéro in last table item |
|||
add x4,x4,#1 |
|||
str x3,[x5,x4,lsl #3] // and zero in counter same divisor |
|||
b 100f |
|||
98: |
|||
//ldr x0,qAdrszMessPrime |
|||
//bl affichageMess |
|||
mov x0,#0 // return code 0 = number is prime |
|||
b 100f |
|||
99: |
|||
ldr x0,qAdrszMessErrGen |
|||
bl affichageMess |
|||
mov x0,#-1 // error code |
|||
b 100f |
|||
100: |
|||
ldp x8,x9,[sp],16 // restaur registers |
|||
ldp x6,x7,[sp],16 // restaur registers |
|||
ldp x4,x5,[sp],16 // restaur registers |
|||
ldp x2,x3,[sp],16 // restaur registers |
|||
ldp x1,lr,[sp],16 // restaur registers |
|||
ret |
|||
qAdrszMessErrGen: .quad szMessErrGen |
|||
/***************************************************/ |
|||
/* Verification si un nombre est premier */ |
|||
/***************************************************/ |
|||
/* x0 contient le nombre à verifier */ |
|||
/* x0 retourne 1 si premier 0 sinon */ |
|||
isPrime: |
|||
stp x1,lr,[sp,-16]! // save registres |
|||
stp x2,x3,[sp,-16]! // save registres |
|||
mov x2,x0 |
|||
sub x1,x0,#1 |
|||
cmp x2,0 |
|||
beq 99f // retourne zéro |
|||
cmp x2,2 // pour 1 et 2 retourne 1 |
|||
ble 2f |
|||
mov x0,#2 |
|||
bl moduloPur64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
cmp x2,3 |
|||
beq 2f |
|||
mov x0,#3 |
|||
bl moduloPur64 |
|||
blt 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f |
|||
cmp x2,5 |
|||
beq 2f |
|||
mov x0,#5 |
|||
bl moduloPur64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
cmp x2,7 |
|||
beq 2f |
|||
mov x0,#7 |
|||
bl moduloPur64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
cmp x2,11 |
|||
beq 2f |
|||
mov x0,#11 |
|||
bl moduloPur64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
cmp x2,13 |
|||
beq 2f |
|||
mov x0,#13 |
|||
bl moduloPur64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
cmp x2,17 |
|||
beq 2f |
|||
mov x0,#17 |
|||
bl moduloPur64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
2: |
|||
cmn x0,0 // carry à zero pas d'erreur |
|||
mov x0,1 // premier |
|||
b 100f |
|||
99: |
|||
cmn x0,0 // carry à zero pas d'erreur |
|||
mov x0,#0 // Pas premier |
|||
100: |
|||
ldp x2,x3,[sp],16 // restaur des 2 registres |
|||
ldp x1,lr,[sp],16 // restaur des 2 registres |
|||
ret // retour adresse lr x30 |
|||
/**************************************************************/ |
|||
/********************************************************/ |
|||
/* Calcul modulo de b puissance e modulo m */ |
|||
/* Exemple 4 puissance 13 modulo 497 = 445 */ |
|||
/********************************************************/ |
|||
/* x0 nombre */ |
|||
/* x1 exposant */ |
|||
/* x2 modulo */ |
|||
moduloPur64: |
|||
stp x1,lr,[sp,-16]! // save registres |
|||
stp x3,x4,[sp,-16]! // save registres |
|||
stp x5,x6,[sp,-16]! // save registres |
|||
stp x7,x8,[sp,-16]! // save registres |
|||
stp x9,x10,[sp,-16]! // save registres |
|||
cbz x0,100f |
|||
cbz x1,100f |
|||
mov x8,x0 |
|||
mov x7,x1 |
|||
mov x6,1 // resultat |
|||
udiv x4,x8,x2 |
|||
msub x9,x4,x2,x8 // contient le reste |
|||
1: |
|||
tst x7,1 |
|||
beq 2f |
|||
mul x4,x9,x6 |
|||
umulh x5,x9,x6 |
|||
//cbnz x5,99f |
|||
mov x6,x4 |
|||
mov x0,x6 |
|||
mov x1,x5 |
|||
bl divisionReg128U |
|||
cbnz x1,99f // overflow |
|||
mov x6,x3 |
|||
2: |
|||
mul x8,x9,x9 |
|||
umulh x5,x9,x9 |
|||
mov x0,x8 |
|||
mov x1,x5 |
|||
bl divisionReg128U |
|||
cbnz x1,99f // overflow |
|||
mov x9,x3 |
|||
lsr x7,x7,1 |
|||
cbnz x7,1b |
|||
mov x0,x6 // result |
|||
cmn x0,0 // carry à zero pas d'erreur |
|||
b 100f |
|||
99: |
|||
ldr x0,qAdrszMessOverflow |
|||
bl affichageMess |
|||
cmp x0,0 // carry à un car erreur |
|||
mov x0,-1 // code erreur |
|||
100: |
|||
ldp x9,x10,[sp],16 // restaur des 2 registres |
|||
ldp x7,x8,[sp],16 // restaur des 2 registres |
|||
ldp x5,x6,[sp],16 // restaur des 2 registres |
|||
ldp x3,x4,[sp],16 // restaur des 2 registres |
|||
ldp x1,lr,[sp],16 // restaur des 2 registres |
|||
ret // retour adresse lr x30 |
|||
qAdrszMessOverflow: .quad szMessOverflow |
|||
/***************************************************/ |
|||
/* division d un nombre de 128 bits par un nombre de 64 bits */ |
|||
/***************************************************/ |
|||
/* x0 contient partie basse dividende */ |
|||
/* x1 contient partie haute dividente */ |
|||
/* x2 contient le diviseur */ |
|||
/* x0 retourne partie basse quotient */ |
|||
/* x1 retourne partie haute quotient */ |
|||
/* x3 retourne le reste */ |
|||
divisionReg128U: |
|||
stp x6,lr,[sp,-16]! // save registres |
|||
stp x4,x5,[sp,-16]! // save registres |
|||
mov x5,#0 // raz du reste R |
|||
mov x3,#128 // compteur de boucle |
|||
mov x4,#0 // dernier bit |
|||
1: |
|||
lsl x5,x5,#1 // on decale le reste de 1 |
|||
tst x1,1<<63 // test du bit le plus à gauche |
|||
lsl x1,x1,#1 // on decale la partie haute du quotient de 1 |
|||
beq 2f |
|||
orr x5,x5,#1 // et on le pousse dans le reste R |
|||
2: |
|||
tst x0,1<<63 |
|||
lsl x0,x0,#1 // puis on decale la partie basse |
|||
beq 3f |
|||
orr x1,x1,#1 // et on pousse le bit de gauche dans la partie haute |
|||
3: |
|||
orr x0,x0,x4 // position du dernier bit du quotient |
|||
mov x4,#0 // raz du bit |
|||
cmp x5,x2 |
|||
blt 4f |
|||
sub x5,x5,x2 // on enleve le diviseur du reste |
|||
mov x4,#1 // dernier bit à 1 |
|||
4: |
|||
// et boucle |
|||
subs x3,x3,#1 |
|||
bgt 1b |
|||
lsl x1,x1,#1 // on decale le quotient de 1 |
|||
tst x0,1<<63 |
|||
lsl x0,x0,#1 // puis on decale la partie basse |
|||
beq 5f |
|||
orr x1,x1,#1 |
|||
5: |
|||
orr x0,x0,x4 // position du dernier bit du quotient |
|||
mov x3,x5 |
|||
100: |
|||
ldp x4,x5,[sp],16 // restaur des 2 registres |
|||
ldp x6,lr,[sp],16 // restaur des 2 registres |
|||
ret // retour adresse lr x30 |
|||
/***************************************************/ |
|||
/* ROUTINES INCLUDE */ |
|||
/***************************************************/ |
|||
.include "../includeARM64.inc" |
|||
</lang> |
|||
<pre> |
|||
First 50 Achilles Numbers: |
|||
72 108 200 288 392 432 500 648 675 800 |
|||
864 968 972 1125 1152 1323 1352 1372 1568 1800 |
|||
1944 2000 2312 2592 2700 2888 3087 3200 3267 3456 |
|||
3528 3872 3888 4000 4232 4500 4563 4608 5000 5292 |
|||
5324 5400 5408 5488 6075 6125 6272 6728 6912 7200 |
|||
First 20 Strong Achilles Numbers: |
|||
500 864 1944 2000 2592 3456 5000 10125 10368 12348 |
|||
12500 16875 19652 19773 30375 31104 32000 33275 37044 40500 |
|||
Numbers with 2 digits : 1 |
|||
Numbers with 3 digits : 12 |
|||
Numbers with 4 digits : 47 |
|||
Numbers with 5 digits : 192 |
|||
Numbers with 6 digits : 664 |
|||
</pre> |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |