Bonjour

Pour faire des additions avec plus de 20 chiffres significatifs sans être pénalisé par des lenteurs je souhaite faire en Asm une fonction à laquelle je donne en entrée deux chaînes-numériques de longueur non limitée et qui renvoie le résultat de l’addition sous forme d’une autre chaîne dont les caractères numériques sont obtenus comme on apprend à l’école dans le style « 8 + 9 = JePose 7 et JeRetiens 1 ». A cet effet les chaînes envoyées en entrée sont des chaînes calibrées de même longueur et commençant par au moins un ‘0’ (ou davantage s’il faut ajuster l’une à l’autre).

Bien que je sois nul en Asm j’ai réussi à bidouiller une fonction qui réalise ce résultat très très maladroitement avec un fonction que j’aimerais donc optimiser sous plusieurs aspects :
- extension aux calculs sur des chaines-numériques du type String ou Pchar (au lieu des ShortString’s)
- soulagement des calculs par des précalculs résumés dans les deux tableaux suivants :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
type   TTabPoseRetiens = array['0'..'9','0'..'9'] of Char;
 
const  AdditionJePose : TTabPR = 
(('0','1','2','3','4','5','6','7','8','9'),
('1','2','3','4','5','6','7','8','9','0'),
('2','3','4','5','6','7','8','9','0','1'),
('3','4','5','6','7','8','9','0','1','2'),
('4','5','6','7','8','9','0','1','2','3'),
('5','6','7','8','9','0','1','2','3','4'),
('6','7','8','9','0','1','2','3','4','5'),
('7','8','9','0','1','2','3','4','5','6'),
('8','9','0','1','2','3','4','5','6','7'),
('9','0','1','2','3','4','5','6','7','8'))
 
const AdditionJeRetiens : TTabPR =
(('0','0','0','0','0','0','0','0','0','0'),
('0','0','0','0','0','0','0','0','0','1'),
('0','0','0','0','0','0','0','0','1','1'),
('0','0','0','0','0','0','0','1','1','1'),
('0','0','0','0','0','0','1','1','1','1'),
('0','0','0','0','0','1','1','1','1','1'),
('0','0','0','0','1','1','1','1','1','1'),
('0','0','0','1','1','1','1','1','1','1'),
('0','0','1','1','1','1','1','1','1','1'),
('0','1','1','1','1','1','1','1','1','1'))
La fonction Asm à optimiser :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 
function  AdditionAsm(str1,str2 : shortString; Len : Integer) : shortString;
//        str1 et str2 en entrée : de même longueur avec mini un 0 au début
//        str1     = '09123457891235469785743258714586027895'
//        str2     = '01234568524563759158521739582461397461'
//        Resultat = '10358026415799228944264998297047425356'
var       Pose,Retiens : byte; Res : shortString;
begin     Retiens:=0; Res:=StringOfChar(' ',Len);
  asm     PUSHFD
          PUSHAD
 
          PUSH  ESI
          PUSH  EDX
          PUSH  EDI
          PUSH  ECX
 
          LEA   ESI, str1  // source
          LEA   EDX, str2  // 2ème source
          LEA   EDI, res   // destination
 
          STD   // incrémenter de la fin vers le début
          ADD   ESI, Len  // Initialisation à l'offset de
          ADD   EDI, Len  // début des chaînes + Len
          ADD   EDX, Len  // idem
          MOV   ECX, Len
 
@Boucle:
          LODSB                    // Calcul de Pose:="s1[i] + s2[i] + retenue"
          MOV   Pose,AL            // caractère de str1
          MOV   AH,Retiens
          ADD   Pose,Ah
          MOV   AH, Byte ptr[EDX]  // caractère de str2
          ADD   Pose,AH
          SUB   Pose,96
          CMP   Pose,10
          JB   @Inf
          SUB   Pose,10
          MOV   AL,Pose
          MOV   Retiens,1          //retenue = 1
          JMP  @Suite
 
@Inf:     MOV   AL,Pose
          MOV   Retiens,0          //retenue = 0
 
@Suite:   ADD   AL,48
          DEC   EDX                //caractère précédent de str2
          STOSB
          LOOP @Boucle
 
@Sors:    POP   ECX
          POP   EDI
          POP   EDX
          POP   ESI
 
          POPAD
          POPFD
end; //asm
          //res:=trim(res);
          Result:=res;
end; // AdditionAsm
Ayant testé les performances de rapidité des fonctions utilisées par la calculatrice-pour-grands-nombres proposée dans les codes-source il s’avère que celles-ci sont fortement sanctionnées dans le cas d’appels répétitifs dans des boucles du fait de la lenteur des conversions des chaînes-numériques vers des Array Of Int64 et réciproquement, inutile donc de me proposer ce type de solution (qui reste néanmoins valable pour une calculatrice utilisée hors boucle)

Par contre si quelqu’un a de bonnes idées pour rectifier le code de la fonction ci-dessus en Asm cela m’enlèverait une épine du pied et peut-être que d’autres seraient également intéressés par la fonction rectifiée.

Merci par avance.
A+