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