Programme en assembleur un peu tordu....

Signaler
Messages postés
6
Date d'inscription
mardi 27 décembre 2005
Statut
Membre
Dernière intervention
31 décembre 2005
-
Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
-
Bonjour,





Voilà un petit programme pour un exo qui me semble un peu tordu.





Les questions sont tout d'abord que fait ce programme (pour moi il tourne en rond) et corriger l'erreur algorithmque.





Code:, ----
.data

str: .zero 11

i: .long 463960

d: .long 1

j: .zero 4

.text .globl _start

_start: movl i,%ebx

L1: movl i,%eax

movl $0,%edx

movl d,%ecx

divl %ecx

push %edx

movl $10,%eax

mull %ecx

pop %edx

movl %eax,d

cmpl %edx,%ebx

jbe L1

movl $str,%ebx

movl d,%eax

movl $0,%edx

movl $10,%ecx

divl %ecx

movl %eax,d

L2: movl d,%eax

movl $0,%edx

movl $10,%ecx

divl %ecx

movl %eax,d

movl i,%eax

movl $0,%edx

movl d,%ecx

divl %ecx

movl %edx,i

movl j,%ecx

movl $0,%edx

addl $'0',%eax

movb %al,%ds:(%ebx,%ecx,1)

inc %ecx

movl %ecx,j

movl i,%eax

movl $0,%edx

cmpl %eax,%edx

jne L2

movl j,%eax

addl $str,%eax

movl $0,%edx

movb $0,%ds:(%edx,%eax,1)

movl $1,%eax

movl $0,%eax

int $0x80






D'avance merci pour vos réponses.





A vos compilateurs !

12 réponses

Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
salut,

Déjà, on peut voir qu'il s'agit de l'assembleur de Linux.
donc "instruction src,dst"
Je commence, tu finis.

str: .zero 11 ; = db 0,0,0,0,0,0,0,0,0,0,0
i: .long 463960 = dd 463960
d: .long 1 = dd 1
j: .zero 4 = db 0,0,0,0

movl i,%ebx ; ebx i 463960
movl i,%eax ; eax i 463960
movl $0,%edx ; edx = 0
movl d,%ecx ; ecx d 1
divl %ecx ; edx:eax / ecx ( edx reste 0, eax = quotient = 463960)
push %edx ; sauve reste ( esp -sizeof LONG, [esp] edx )
movl $10,%eax ; eax 10h ( $ hex ou dec ? )
mull %ecx; edx:eax = eax * ecx
pop %edx ; restore reste ( edx = [esp]; esp += sizeof LONG )
movl %eax,d ; d = eax
cmpl %edx,%ebx ; si ebx <= edx -> L1 ( verifier ordre des comparaison )

;...

une fois que tu auras tout traduit, tu pourra comprendre l'objectif de ce code.

@++
Messages postés
6
Date d'inscription
mardi 27 décembre 2005
Statut
Membre
Dernière intervention
31 décembre 2005

Salut,
Alors alors... J'ai mis sur papier ce que tu m'avais donné et j'ai vu qu'en fait ce bout de code ne faisait.... rien ! En fait, la dernière instruction compare ebx et edx. ebx 463960 vu que l'on n'y a pas touché depuis le début et edx 0 (c'est le reste restauré avec le pop). Donc, avec ce bout de code, jamais on aura ebx <= edx pourquoi faire le teste alors ? Elle est la l'erreur ? Donc on ne saute pas à L1 et on continue :

Le reste ...
movl $str,%ebx ; ebx str 0,0,0,0,0,0,0,0,0,0,0 (??) movl d,%eax ; eax d 1
movl $0,%edx ; edx = 0
movl $10,%ecx ; ecx = 10divl %ecx ; edx:eax / ecx ( edx reste 10, eax = quotient = 0)
movl %eax,d ; ah qu'est-ce qu'on fait la, on met eax dans d ou d dans eax ? Le premier me parait impossible.

En tout cas merci pour ta réponse... on avance petit à petit.
Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
salut,

ton code doit etre un convertisseur numerique vers ascii.
movl %eax,d ; donne bien d = eax ( instruction src,dst )

@++
Messages postés
6
Date d'inscription
mardi 27 décembre 2005
Statut
Membre
Dernière intervention
31 décembre 2005

Salut patatalo,

Alors ce serait un convertisseur ASCII. Mais qu'est-ce que l'on cherche à convertir ? Une donnée tapée au clavier ? Ou plutôt 463960 ? ou une autre variable ?

Pour le reste voyons voir :
movl %eax,d ; d eax 463960 (avant d valait 1) L2: movl d,%eax ; eax d 463960 (étrange on a fait l'inverse juste au dessus.)
movl $0,%edx ; edx = 0
movl $10,%ecx ; ecx = 10 divl %ecx ; edx:eax / ecx ( edx reste 0, eax = quotient = 46396) movl %eax,d ; d eax 46396 movl i,%eax ; eax i 463960
movl $0,%edx ; edx = 0 (il le valait déjà) movl d,%ecx ; ecx d 1 divl %ecx ; edx:eax / ecx ( edx reste 0, eax = quotient = 463960) movl %edx,i ; i edx 0 movl j,%ecx ; ecx j 0,0,0,0 (comprend pas la)
movl $0,%edx ; edx = 0 addl $'0',%eax ; on additionne le code ASCII de '0' avec eax, le résultat est dans eax : eax 463960 + 48 464008
movb %al,%ds:(%ebx,%ecx,1) ; alors la je coince

Ne sachant pas si ecx a été modifié je ne peux pas continuer pour l'instant.

inc %ecx
movl %ecx,j
movl i,%eax
movl $0,%edx
cmpl %eax,%edx
jne L2
movl j,%eax
addl $str,%eax
movl $0,%edx
movb $0,%ds:(%edx,%eax,1)
movl $1,%eax
movl $0,%eax
int $0x80

Sinon, concrêtement, je ne vois pas comment ça converti en code ASCII.

Merci encore pour ton aide.
Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
re,

movb $0,%ds:(%edx,%eax,1) ; donne "mov byte ptr [edx+eax*1],0" ( mais alors là a verifier soit au desassembleur soit sur la doc de l'assembleur linux, je ne le connais pas assez ).Le segment ds n'est pas a preciser a moins d'utiliser ebp et esp en base d'acces memoire.

ce bout de code:
movl %eax,d
L2:
movl d,%eax
on met a jour la variable d mais eax peut necessiter une remise a jour lors de la boucle L2 donc cette suite d'instruction est tout a fait normal.

que cherche t'on dans la boucle L1:
cmpl %edx,%ebx
jbe L1 ; edx ebx quand d ecx = 1000000 ( le below est pour plus de sureté )
cette boucle ne cherche qu'a ajuster d

ensuite, d est redivisé par 10 juste avant L2 ( d = 100000 )

il ne te reste plus que L2 a traduire.
c'est L2 qui convertis decimal -> ascii dans le buffer str
la convertion en ascii s'opere par l'ajout du caractere '0' a la valeur eax.
on sauve ensuite dans [ebx+ecx*1] ( ebx = OFFSET str et ecx = j a ce moment là )
la suite ascii "0123456789" donne 30h,31h,32h,... ( "0" = 30h )

le zero terminal est ajouté au final.
movb $0,%ds:(%edx,%eax,1) ( ebx OFFSET str, eax j )

là par contre, je comprends pas:
movl $1,%eax ; eax = 1
movl $0,%eax ; eax = 0
int $0x80 ; syscall linux ? terminaison programme

@++
Messages postés
6
Date d'inscription
mardi 27 décembre 2005
Statut
Membre
Dernière intervention
31 décembre 2005

re,
Bon je viens de me rendre compte que j'ai mal recopié l'exo, le jump vers L1 c jne et pas jbe. Vraiment désolé...

bon on récapépette.

.data
str: .zero 11
i: .long 463960
d: .long 1
j: .zero 4
.text .globl _start
_start: movl i,%ebx ; ebx = 463960
L1: movl i,%eax ; eax = 463960 movl $0,%edx ; edx 0 ($ dec) movl d,%ecx ; ecx d 1 divl %ecx ; edx:eax / ecx ( edx reste 0, eax = quotient = 463960) la on a rien changé
push %edx ; sauve le reste 0 dans la pile
movl $10,%eax ; eax = 10 mull %ecx ; eax * ecx 10 * 1, le resultat est dans eax, donc eax 10 on a rien changé
pop %edx ; on restore le reste edx = 0 movl %eax,d ; d eax 10 cmpl %edx,%ebx ; si ebx !edx alors on retourne a L1, et ebx 463960 et edx = 0 (cf le pop)
jne L1 ; donc on retourne a L1

L1: movl i,%eax ; eax = 463960

movl $0,%edx ; edx 0 ($ dec)

movl d,%ecx ; ecx d 10

divl %ecx ; edx:eax / ecx ( edx reste 0, eax = quotient = 46396)

push %edx ; sauve le reste 0 dans la pile

movl $10,%eax ; eax = 10

mull %ecx ; eax * ecx 10 * 10, le resultat est dans eax, donc eax 100

pop %edx ; on restore le reste edx = 0

movl %eax,d ; d eax 100

cmpl %edx,%ebx ; si ebx !edx alors on retourne a L1, et ebx 463960 et edx = 0 (cf le pop)
jne L1 ; donc on retourne a L1

......
Donc en gros on effectue la boucle 7 fois, jusqu'à ce que d = 1000000 pour que, lors de la division, on ait le reste égale à 463960. Algorithmiquement, ce n'est pas très malin.

Pour L1, c'est ok !
La suite....
movl $str,%ebx ; on mets str dans ebx (c'est pour travailler avec ebx au lieu de travailler directement avec str ?) movl d,%eax ; eax d 1000000
movl $0,%edx ; edx = 0
movl $10,%ecx ; ecx = 10 divl %ecx ; edx:eax / ecx ( edx reste 0, eax = quotient = 100000)
movl %eax,d
Messages postés
6
Date d'inscription
mardi 27 décembre 2005
Statut
Membre
Dernière intervention
31 décembre 2005

oup désolé j'ai cliqué alors que j'avais pas fini !

je continue...

movl %eax,d ; on met à jour d = 100000

La voila l'erreur algorithmique ! Enfin je pense.... On sait que l'on a un zéro de trop pour d, donc on refait une division par 10. Cette erreur aurait pu être corrigé dans la boucle L1.

J'ai toujours une petit question : qu'est-ce que l'on cherche à convertir en ASCII ? quelle valeur ? là je vois pas.

Je vais bouquinner pour la ligne movb $0,%ds:(%edx,%eax,1)

@++ et encore merci
Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
re,

la valeure convertie est i ( laquelle veut tu que ce soit d'autre ??? )

c'est une methode qui permet de partir par la valeur la plus elevée vers la valeur la moins elevée, il doit effectivement etre plus judicieux de partir par la valeur la plus basse, de stocker dans un buffer temporaire et de reverser du buffer temporaire vers str. ( on evite la boucle L1 mais on s'oblige a avoir une valeur max de X caracteres qui definira la taille du buffer temporaire )

@++
Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
un petit detail:
j devrait plutot etre défini comme:
j: .long 0 ( c'est l'index de stockage dans str )

effectivement, cherche l'erreur du coté de d ;-)

@++
Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
voilà le code par la méthode du buffer temporaire, tu pourra faire des test de vitesse.

c'est en assembleur Intel, je te laisse traduire pour Linux.

decimal2ascii:
push ebp
push ebx
sub esp,16
mov ebp,esp

mov ecx,10
mov eax,i
lea ebx,str

L1:
xor edx,edx
div ecx
add dl,'0'
or eax,byte 0
mov [ebp],dl
lea ebp,[ebp+1]
jne L1

L2:
dec ebp
mov al,[ebp]
cmp ebp,esp
mov [ebx],al
lea ebx,[ebx+1]
jne L2

xor eax,eax
mov [ebx],al
pop ebx
pop ebp
int 0x80

bon courage dans tes etudes...
@++
Messages postés
6
Date d'inscription
mardi 27 décembre 2005
Statut
Membre
Dernière intervention
31 décembre 2005

Merci pour ton aide, je pense que j'arriverai à m'en sortir avec ça.

Bonne fête de fin d'année et bon courage à toi aussi.
Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
oups, faudrait voir a mettre le pointeur de pile a jour avant de poper

xor eax,eax
add esp,16
mov [ebx],al
pop ebx
pop ebp
int 0x80

@++