Unité A6: Conversions Unité A6: Conversions
Transcription
Unité A6: Conversions Unité A6: Conversions
Unité A6: Conversions Objectifs : À la fin de cette unité, vous saurez comment on peut programmer en assembleur les conversions usuelles binaire décimal et décimal binaire. Pour y parvenir, vous devrez atteindre les objectifs suivants : - décrire les principaux algorithmes de conversion entre le décimal et le binaire. ©Pierre Marchand, 2001 210 Unité A6: Conversions On effectue souvent en assembleur les conversions élémentaires de binaire à décimal et vice-versa, parce que ces fonctions sont appelées très souvent et ont donc intérêt à être performantes. La conversion entre le décimal et le binaire s'effectue habituellement comme suit : Décimal (BCD) à binaire (voir supplément au volume, section 3.3.1) : R = d + 10 × R Pour la conversion binaire à décimal, trois méthodes sont fréquemment utilisées : • R = b + 2 × R en arithmétique BCD • Divisions répétées par 10 -> séquence de restes • Tables Celle qu'on choisit dépend du processeur utilisé, du jeu d'instructions dont il dispose, et du temps d'exécution de chacune. ©Pierre Marchand, 2001 211 1 Unité A6: Conversions 9.1 Conversion décimal à binaire Effectuons la conversion d'une chaîne de caractères décimaux représentant un nombre positif vers un nombre binaire de 32 bits non signé. On utilise l’algorithme d + 10 x R. Exemple sur 16 bits : Nombre à convertir en BCD 1 2 3 410 ©Pierre Marchand, 2001 R = 0000 01 + 000A x 0000 = 0001 02 + 000A x 0001 = 000C 03 + 000A x 000C = 007B 04 + 000A x 007B = 04D2 212 Unité A6: Conversions 9.1 Conversion décimal à binaire dec2Long proc decString:LPSTR mov xor While: movzx inc test je sub imul add jmp fin: ret dec2Long endp ©Pierre Marchand, 2001 esi, decString eax, eax ebx, byte ptr[esi] esi bl, bl fin bl, '0' eax, 10 eax, ebx While ; résultat = 0 ; while (*decString++) ; terminé si nul ; conversion ASCII-binaire ; résultat *= 10 ; résultat += digit ; résultat dans eax 213 2 Unité A6: Conversions 9.2 Conversion binaire à décimal 1e méthode : divisions par 10 Exemple sur 16 bits : ABCD / 000A 112E / 000A 01B7 / 000A 002B / 000A 0004 / 000A = 112E reste 01 = 01B7 reste 08 = 002B reste 09 = 0004 reste 03 = 0000 reste 04 Résultat : 04 03 09 08 01 en BCD, 34 33 39 38 31 en ASCII, ou 4398110 ©Pierre Marchand, 2001 214 Unité A6: Conversions 9.2 Conversion binaire à décimal 1e méthode : divisions par 10 Stratégie : comme le résultat est la séquence des restes, mais inversée, nous écrirons ces restes vers la gauche à partir du 11e octet dans une variable Temp de 12 octets initialisée à 0. Nous aurons ainsi automatiquement notre caractère de fin de chaîne. Ainsi, dans l’exemple précédent, on aurait : Temp : 00 00 00 00 00 00 34 33 39 38 31 00 Pointeur à la fin des divisions Pointeur initial Il nous restera à incrémenter le pointeur final et à faire un strcopy vers la destination. ©Pierre Marchand, 2001 215 3 Unité A6: Conversions 9.2 Conversion binaire à décimal 1e méthode : divisions par 10 temp db 12 dup(0) ; espace pour restes = 12 zéros bin2String proc n:DWORD, String:LPSTR divis: mov eax, n lea esi, temp ; nombre à convertir add esi, 10 ; pointer sur fin de temp mov ecx,10 ; 10 pour la division mov edx, 0 ; eax = quotient précédent div ecx ; diviser par 10 add dl, ’0 ’ ; convertir reste en ASCII mov [esi], dl ; stocker dans temp dec esi ; écrire le suivant à gauche 216 ©Pierre Marchand, 2001 Unité A6: Conversions 9.2 Conversion binaire à décimal 1e méthode : divisions par 10 test eax, eax jne divis inc esi ; pointer sur dernier reste mov edi, String ; adresse destination ; tant que quotient != 0 ; copier temp dans destination copy: lodsb ; reste suivant stosb test al, al jne copy ; tant que reste ≠ 0 ret bin2String endp ©Pierre Marchand, 2001 217 4 Unité A6: Conversions 9.2 Conversion binaire à décimal 2e méthode : R = b + 2 * R Addition BCD Sur 2 octets Exemple sur 8 bits : 10111101 ©Pierre Marchand, 2001 R = 00 00 1 + 00 00 + 00 00 = 00 01 0 + 00 01 + 00 01 = 00 02 1 + 00 02 + 00 02 = 00 05 1 + 00 05 + 00 05 = 00 11 1 + 00 11 + 00 11 = 00 23 1 + 00 23 + 00 23 = 00 47 0 + 00 47 + 00 47 = 00 94 1 + 00 94 + 00 94 = 01 89 218 Unité A6: Conversions 9.2 Conversion binaire à décimal 2e méthode : R = b + 2 * R Exemple sur 8 bits : Il faut ensuite décompacter les octets pour les convertir en ASCII. 01 89 -> 00 01 08 09 -> 30 31 38 39 00 Pour décompacter, on met un octet du résultat dans al et dans ah : ax = 89 89 On fait ensuite le AND de ax avec 0xF00F : and ax,0xF00F ax = 80 09 Puis on décale ah de 4 bits vers la droite : shr ah, 4 ax = 08 09 Finalement, on ajoute 0x30 à chacun : add eax,0x3030 ax = 38 39 ©Pierre Marchand, 2001 219 5 Unité A6: Conversions 9.2 Conversion binaire à décimal 2e méthode : R = b + 2 * R Comme un nombre de 32 bits peut aller jusqu’à 4 294 967 296 qui a 10 chiffres, il nous faudra faire nos additions BCD sur 5 octets (un octet contient 2 chiffres en BCD compacté. 220 ©Pierre Marchand, 2001 Unité A6: Conversions 9.2 Conversion binaire à décimal 2e méthode : R = b + 2 * R temp db 5 dup(0) bin2decString proc n:DWORD, decString:LPSTR mov ebx, n decal: mov edx, 32 lea edi, temp rcl ebx, 1 mov esi, 4 mov ecx, 5 ©Pierre Marchand, 2001 ; 32 bits à traiter ; mettre le msb dans CF 221 6 Unité A6: Conversions 9.2 Conversion binaire à décimal 2e méthode : R = b + 2 * R abcd: mov al, byte ptr [edi+esi| ; addition bcd sur 5 octets adc al, al ;b+2*R daa ; ajustement BCD mov byte ptr [edi+esi], al ; résultat dans temp dec esi dec ecx jne abcd dec edx jne decal mov ecx, 5 mov esi, str ; fin abcd ; fin décal 222 ©Pierre Marchand, 2001 Unité A6: Conversions 9.2 Conversion binaire à décimal 2e méthode : R = b + 2 * R copy: mov al, [edi] mov and shr add xchg mov inc add dec jne mov ret ah, al ax, 0xF00F ah, 4 ax, 0x3030 ah, al word ptr [esi], ax edi esi, 2 ecx copy byte ptr[edi], 0 ©Pierre Marchand, 2001 ; copier dans destination et ; convertir le BCD compacté ; en BCD non compacté ; masquer lsb et msb ; décaler msb en place ; convertir en ASCII ; little endian ; stocker deux car ; incrémenter source ; incrémenter destination ; car de fin de chaîne 223 7 Unité A6: Conversions 9.2 Conversion binaire à décimal 3e méthode : à l’aide d'une table Soit n le nombre à convertir. Le résultat r est un nombre de 10 chiffres ASCII qu’on initialise à 0 : r = ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0 , ‘0’, ‘0’, ‘0’, 0 Tant que n >= 1000000000, n = n - 1000000000, Tant que n >= 100000000, n = n - 10000000, Tant que n >= 10000000, n = n - 10000000, Tant que n >= 1000000, n = n - 1000000, Tant que n >= 100000, n = n - 100000, Tant que n >= 10000, n = n - 10000, Tant que n >= 1000, n = n - 1000, Tant que n >= 100, n = n - 100, Tant que n >= 10, n = n - 10, ©Pierre Marchand, 2001 r[0] = r[0] + 1 r[1] = r[1] + 1 r[2] = r[2] + 1 r[3] = r[3] + 1 r[4] = r[4] + 1 r[5] = r[5] + 1 r[6] = r[6] + 1 r[7] = r[7] + 1 r[8] = r[8] + 1 r[9] = n 224 Unité A6: Conversions 9.2 Conversion binaire à décimal 3e méthode : à l’aide d'une table Table dd 1000000000, 100000000, 10000000, 1000000, 100000, dd 10000, 1000, 100, 10, 1 bin2decString proc n:DWORD, decString:LPSTR mov eax, n lea esi, Table xor ebx, ebx mov edi, decString mov ecx, 10 ; 10 nombres dans Table digit: mov byte ptr [edi+ebx], ’0’ ; résultat = ‘ 0 ’ mov edx, dword ptr [esi+ebx*4] ; Table[i] comp: cmp eax, edx ; peut-on soustraire? jb suiv ©Pierre Marchand, 2001 225 8 Unité A6: Conversions 9.2 Conversion binaire à décimal 3e méthode : à l’aide d'une table sub add jmp suiv: inc loop mov ret bin2decString endp ©Pierre Marchand, 2001 eax. edx byte ptr [edi+ebx], 1 comp ebx digit byte ptr [edi+ebx], 0 ; soustraire Table[i] ; incrémenter résultat ; tant que eax > Table[i] ; élément suivant ; car de fin de chaîne 226 Unité A6: Conversions 9.2 Conversion binaire à décimal Certains raffinements pourraient s'avérer souhaitables dans les programmes présentés dans cette section. Notamment : Conversion décimal-binaire Traitement des nombres négatifs Traitement des espaces au début Conversion binaire-décimal Traitement des nombres négatifs Éliminer les zéros initiaux, par exemple, retourner 3 au lieu de 000000003 ©Pierre Marchand, 2001 227 9 Unité A6: Conversions 9.3 Conversion binaire à chaîne hexadécimale Pour effectuer cette conversion, on effectue une rotation de eax de 4 bits vers la gauche pour mettre les 4 bits les plus significatifs à droite. 12 34 56 78 23 45 67 81 On copie al dans bl. On masque ensuite les 4 bits de poids fort de bl avec : and bl, 0x0F. 81 01 On ajoute 0x30 à bl pour le convertir en ASCII : add bl, 0x30 01 31 On écrit bl dans le résultat et on incrémente le pointeur. On effectue cette opération 8 fois. ©Pierre Marchand, 2001 228 Unité A6: Conversions 9.3 Conversion binaire à chaîne hexadécimale Long2HexString proc num:DWORD, HexString:LPSTR mov edi, HexString mov eax, num mov ecx, 8 ; 8 car. pour représenter un long lp: rol eax, 4 ; 4 bits suivants mov bl, al and bl, 0x0F ; masquer les 4 bits de droite add bl, ‘ 0 ’ ; convertir en ASCII cmp bl, ‘ 9 ’ jbe ok ; si c’est un chiffre 0-9 add bl, 7 ; si c’est une lettre A-F ©Pierre Marchand, 2001 229 10 Unité A6: Conversions 9.3 Conversion binaire à chaîne hexadécimale ok: mov [edi],bl inc edi dec ecx jnz lp mov byte ptr [edi], 0 ret long2HexString endp ©Pierre Marchand, 2001 ; placer dans la chaîne ; caractère de fin de chaîne 230 Unité A6: Conversions 9.3 Conversion binaire à chaîne hexadécimale Une autre façon d’effectuer cette conversion utilise une table de 16 entrées contenant les codes ASCII des chiffres et des lettres correspondant aux nombres hexadécimaux 0 à F. On place le nombre à convertir dans edx. On effectue comme dans la façon précédente une rotation vers la gauche de edx, et on copie dl dans al. On masque les 4 bits de poids fort. Ensuite on se sert de al comme indice dans la table de 16 codes ASCII. L’instruction XLAT remplace al par le contenu de [ebx + al]. Par exemple, 0x0B donnera le code 0x42 = ‘B’. On écrit ensuite al dans le résultat et on incrémente le pointeur. ©Pierre Marchand, 2001 231 11 Unité A6: Conversions 9.3 Conversion binaire à chaîne hexadécimale table db '0123456789ABCDEF' Long2HexString proc num:DWORD, HexString:LPSTR mov edi, HexString lea ebx, table ; table de traduction dans ebx mov ecx, 8 ; toujours 8 car. mov edx, num ; nombre à convertir lp: rol edx, 4 ; digit suivant mov al, dl and al, 0x0F ; garder 4 bits seulement xlat ; traduire mov [edi], al ; écrire dans destination ©Pierre Marchand, 2001 232 Unité A6: Conversions 9.3 Conversion binaire à chaîne hexadécimale inc edi dec ecx jne lp move byte ptr [edi], 0 ret Long2HexString endp ©Pierre Marchand, 2001 ; caractère de fin de chaîne 233 12