|
Trouver une ressource
Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !
STRING -> BINAIRE (LONGUEUR PSEUDO INFINIE)
Information sur la source
Description
voilà, comme vous savez en C il y a les fonctions atoi et itoa pour convertir une chaîne en int (entier) qui en fait n'est qu'un nombre binaire sur 4 octets et vice versa. Ce que je vous propose ici c'est une fonction (en fait y'en faut plusieurs, c'est pas aussi simple ;-)) qui permet de calculer le nombre binaire à partir d'une string, quelle que soit sa longueur... regardez le screenshot pour un petit exemple ;-) Now on s'interesse au code:
Source
- unit cpute;
-
- interface
-
- type
- TNumber = record
- buf: Pointer;
- len: Cardinal;
- end;
-
- function StrToBin(var n: TNumber): Cardinal;
- function BinToStr(var n: TNumber): Cardinal;
-
- implementation
-
- const
- _0000000ah: Cardinal = $a;
-
- // ******************************************************************
- // ******************************************************************
- // * Part 1:
- // * ~~~~~~~
- // *
- // * the coming functions do only convert numbers (base 10 (<)-> base 2)
- // ******************************************************************
- // ******************************************************************
-
- // ******************************************************************
- // * convert from ASCII digit to binary digit
- // * and check that the buffer doesn't contain any invalid digit
- // * Result = 0: ok; Result <> 0: position of the invalid digit in v_eax (buf)
- // * (where 1 is the first position)
- // ******************************************************************
- function ChrToBin(v_eax: Pointer; v_edx: Cardinal): Cardinal;
- asm
- xor ecx,ecx
- @loop:
- cmp ecx,edx
- je @end
- sub byte ptr [eax+ecx],30h
- jc @exit
- cmp byte ptr [eax+ecx],9
- ja @exit
- inc ecx
- jmp @loop
- @end:
- or ecx,0ffffffffh
- @exit:
- inc ecx
- mov eax,ecx
- end;
-
- // ******************************************************************
- // * convert from binary digit to ASCII digit
- // ******************************************************************
- procedure BinToChr(v_eax: Pointer; v_edx: Cardinal);
- asm
- xor ecx,ecx
- @loop:
- cmp ecx,edx
- je @end
- add byte ptr [eax+ecx],30h
- inc ecx
- jmp @loop
- @end:
- end;
-
- // ******************************************************************
- // * compute a binary number from a string (previously substracted by $30)
- // * result is the length of the binary number (unit: 32 bit)
- // ******************************************************************
- function CputeBin(v_eax: Pointer; v_edx: Cardinal): Cardinal;
- asm
- push ebx
- push ebp
- push esi
- push edi // regs we will use
-
- mov ebp,eax // v_eax (buf) is now ebp
- mov ebx,ebp // ebx is another pointer for buf, but it will be modified
- mov esi,edx // v_edx (len) is now esi
- xor edi,edi // edi will be the size of the binary number (in DWORD)
-
- @loop:
- cmp esi,0 // is it the end of the buffer?
- je @end // yes? let's go to the end
- cmp byte ptr [ebx],0 // is the current byte 0?
- jne @begin // no? then we can compute binary (000023, '0000' is obsolet)
- // obsolet zeros will be used to store the result
- inc ebx // yes? inc and dec pointers
- dec esi
- jmp @loop // ... and check next byte
-
- @begin: // let's convert to binary!
- xor ecx,ecx
- xor eax,eax
- xor edx,edx
-
- @loop2:
- mul _0000000ah // remainder * 10
- push edx // edx is the current numerator
- mov dl,byte ptr [ebx+ecx] // current digit
- add eax,edx // add decimal digits, eax becomes the new numerator
- pop edx
- jnc @nc // well, only a matter of addition remainder
- inc dl
- @nc:
- mov byte ptr [ebx+ecx],dl // new digit, dl represents the current
- // quotient given by a division by 2^32
- inc ecx
- cmp ecx,esi
- jb @loop2 // loop to treat the whole string
-
- // eax is the last remainder of a divsion by 2^32
- mov dword ptr [ebp+edi*4],eax // save our binary number 32 bits by 32 bits
- inc edi // adjust pointers...
- add ebx,4
- sub esi,4
- jnc @loop // let's offer ourselves a new division by 2^32 ;-)
- // till string number is greater than 2^32
- @end:
-
- mov eax,edi // eax is Result
-
- pop edi
- pop esi
- pop ebp
- pop ebx
- end;
-
- procedure CputeStr();
- asm
- end;
-
- procedure ReverBin(v_eax: Pointer; v_edx: Cardinal);
- asm
- dec edx
- xor ecx,ecx
- @loop:
- cmp ecx,edx
- jae @end
- push dword ptr [eax+ecx*4]
- push dword ptr [eax+edx*4]
- pop dword ptr [eax+ecx*4]
- pop dword ptr [eax+edx*4]
- inc ecx
- dec edx
- jmp @loop
- @end:
- end;
-
- procedure CpyStr();
- asm
- end;
-
- function StrToBin(var n: TNumber): Cardinal;
- begin
- // convert ASCII digit to binary digit and checks there is no invalid digit
- Result := ChrToBin(n.buf, n.len);
- if (Result <> 0) then Exit;
- // compute the binary number from input (and its length, 32 bits as unit)
- n.len := CputeBin(n.buf, n.len);
- if (n.len = 0) then Exit;
- // bytes are reversed
- ReverBin(n.buf, n.len);
- end;
-
- function BinToStr(var n: TNumber): Cardinal;
- begin
- end;
-
- // ******************************************************************
- // ******************************************************************
- // * Part 2:
- // * ~~~~~~~
- // *
- // * the coming functions do all the operations (+, -, *, /, gcd)
- // ******************************************************************
- // ******************************************************************
-
- // I am too busy with my studies...
-
- end.
unit cpute;
interface
type
TNumber = record
buf: Pointer;
len: Cardinal;
end;
function StrToBin(var n: TNumber): Cardinal;
function BinToStr(var n: TNumber): Cardinal;
implementation
const
_0000000ah: Cardinal = $a;
// ******************************************************************
// ******************************************************************
// * Part 1:
// * ~~~~~~~
// *
// * the coming functions do only convert numbers (base 10 (<)-> base 2)
// ******************************************************************
// ******************************************************************
// ******************************************************************
// * convert from ASCII digit to binary digit
// * and check that the buffer doesn't contain any invalid digit
// * Result = 0: ok; Result <> 0: position of the invalid digit in v_eax (buf)
// * (where 1 is the first position)
// ******************************************************************
function ChrToBin(v_eax: Pointer; v_edx: Cardinal): Cardinal;
asm
xor ecx,ecx
@loop:
cmp ecx,edx
je @end
sub byte ptr [eax+ecx],30h
jc @exit
cmp byte ptr [eax+ecx],9
ja @exit
inc ecx
jmp @loop
@end:
or ecx,0ffffffffh
@exit:
inc ecx
mov eax,ecx
end;
// ******************************************************************
// * convert from binary digit to ASCII digit
// ******************************************************************
procedure BinToChr(v_eax: Pointer; v_edx: Cardinal);
asm
xor ecx,ecx
@loop:
cmp ecx,edx
je @end
add byte ptr [eax+ecx],30h
inc ecx
jmp @loop
@end:
end;
// ******************************************************************
// * compute a binary number from a string (previously substracted by $30)
// * result is the length of the binary number (unit: 32 bit)
// ******************************************************************
function CputeBin(v_eax: Pointer; v_edx: Cardinal): Cardinal;
asm
push ebx
push ebp
push esi
push edi // regs we will use
mov ebp,eax // v_eax (buf) is now ebp
mov ebx,ebp // ebx is another pointer for buf, but it will be modified
mov esi,edx // v_edx (len) is now esi
xor edi,edi // edi will be the size of the binary number (in DWORD)
@loop:
cmp esi,0 // is it the end of the buffer?
je @end // yes? let's go to the end
cmp byte ptr [ebx],0 // is the current byte 0?
jne @begin // no? then we can compute binary (000023, '0000' is obsolet)
// obsolet zeros will be used to store the result
inc ebx // yes? inc and dec pointers
dec esi
jmp @loop // ... and check next byte
@begin: // let's convert to binary!
xor ecx,ecx
xor eax,eax
xor edx,edx
@loop2:
mul _0000000ah // remainder * 10
push edx // edx is the current numerator
mov dl,byte ptr [ebx+ecx] // current digit
add eax,edx // add decimal digits, eax becomes the new numerator
pop edx
jnc @nc // well, only a matter of addition remainder
inc dl
@nc:
mov byte ptr [ebx+ecx],dl // new digit, dl represents the current
// quotient given by a division by 2^32
inc ecx
cmp ecx,esi
jb @loop2 // loop to treat the whole string
// eax is the last remainder of a divsion by 2^32
mov dword ptr [ebp+edi*4],eax // save our binary number 32 bits by 32 bits
inc edi // adjust pointers...
add ebx,4
sub esi,4
jnc @loop // let's offer ourselves a new division by 2^32 ;-)
// till string number is greater than 2^32
@end:
mov eax,edi // eax is Result
pop edi
pop esi
pop ebp
pop ebx
end;
procedure CputeStr();
asm
end;
procedure ReverBin(v_eax: Pointer; v_edx: Cardinal);
asm
dec edx
xor ecx,ecx
@loop:
cmp ecx,edx
jae @end
push dword ptr [eax+ecx*4]
push dword ptr [eax+edx*4]
pop dword ptr [eax+ecx*4]
pop dword ptr [eax+edx*4]
inc ecx
dec edx
jmp @loop
@end:
end;
procedure CpyStr();
asm
end;
function StrToBin(var n: TNumber): Cardinal;
begin
// convert ASCII digit to binary digit and checks there is no invalid digit
Result := ChrToBin(n.buf, n.len);
if (Result <> 0) then Exit;
// compute the binary number from input (and its length, 32 bits as unit)
n.len := CputeBin(n.buf, n.len);
if (n.len = 0) then Exit;
// bytes are reversed
ReverBin(n.buf, n.len);
end;
function BinToStr(var n: TNumber): Cardinal;
begin
end;
// ******************************************************************
// ******************************************************************
// * Part 2:
// * ~~~~~~~
// *
// * the coming functions do all the operations (+, -, *, /, gcd)
// ******************************************************************
// ******************************************************************
// I am too busy with my studies...
end.
Conclusion
tout de suite vous avez remarquez deux choses: c'est du pur assembleur, et deuxio oui c'est de l'assembleur inline sous delphi (ce qui explique la première affirmation). Bon, je ne pense pas qu'il soit difficile d'adapter ce code pour qu'il compile sous un pur compilo assembleur comme tasm, mais je ne connais pas assez l'assembleur pour ça, je sais que écrire des algos (et encore ;-)). donc comment ça marche tout ce binz? première étape, on effectue une soustraction de 0x30 sur tous les octets de la string, ainsi on peut accéder directement aux chiffres (en binaire donc) de la string. Ensuite on effectue une succession de divisions par 2^32 jusqu'à ce que le reste soit inférieur à 2^32. Le résultat de la division est foutu dans la string, un chiffre par octet. Le dernier reste d'une division par 2^32 de la string constitue 32 bits de notre futur nombre en binaire... ouais c'est complexe, et c'est pas en trois lignes que je peux donner le détail. Pour bien comprendre faut vraiment étudier la source à fond. le buffer (en fait TNumber) donné à la fonction contient le nombre binaire une fois la fonction executée, SANS AUTRE ALLOCATION DE MEMOIRE (elle est pas belle la vie?). Donc il faut faire une copie de votre string avant si vous en avez besoin plus loin... Le blem c'est que j'ai pas le temps de faire la fonction dans l'autre sens, à savoir convertir un nombre binaire énorme en string... Après, ce serait interessant de programmer les opérations de base comme l'addition la soustraction la multiplication et la division, en traitant le nombre 32 bits par 32 bits, le plus rapidement possible. Après on peut encore combiner tout ça à un parseur et essayer de lui faire supporter des nombres réels etc. Bref, on s'reprogramme un p'tit maple9? lol. voilà, c'est complexe, mais si vous voulez essayer: foutez un très grand nombre en décimal dans le fichier 'in' puis tapez: int -b out in et c'est parti, regardez le résultat dans le fichier 'out' (les packs de 4 octets sont en little endian) Ptet un jour j'aurai le temps de continuer cette source mais pour l'instant c'est pas possible (grandes vacances?), donc si ça interesse quelqu'un en attendant je peux toujours l'aider un peu, et pis sinon ben bonne soirée quand même ;-) Twis++;
Fichier Zip
Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
Télécharger le zip
Historique
- 02 octobre 2004 21:21:18 :
- - nombre binaire (résultat) placé directement dans le buffer donné (en entrée) à la fonction StrToBin -> pas d'autre allocation de mémoire.
- nombre binaire (résultat) par paquets de 32 bits en little endian.
Sources de la même categorie
Commentaires et avis
|
Comparez les prix Nouvelle version

HTC Touch HD
Entre 25€ et 605€
|