Microprocesseur intel 8086

Fermé
yeona9 Messages postés 7 Date d'inscription mardi 4 mars 2014 Statut Membre Dernière intervention 6 mars 2014 - 4 mars 2014 à 19:22
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 - 7 mars 2014 à 10:12
Bonsoir,

je suis coincé dans cette fonction récursive qui calcule la série de Fibonacci
J'ai travaillé avec la pile mais je perds l'adresse de retour chaque fois que j'appelle Fibonacci
donc s'il vous plaît si quelqu'un peut m'aider à cela, j'ai vraiment besoin, et je dois le rendre demain.

Merci d'avance

5 réponses

nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
4 mars 2014 à 20:38
Bonjour,

Pour éviter de perdre l'adresse de retour il suffirait d'utiliser call-ret tout simplement, non? Montre donc ton programme pour voir ce qui cloche!
0
yeona9 Messages postés 7 Date d'inscription mardi 4 mars 2014 Statut Membre Dernière intervention 6 mars 2014
4 mars 2014 à 21:56
Voila le programme que j'ai fait :

jmp debut
val dw 0002h
F dw ?
debut:
mov cx,val
push cx
call fibo
pop F
and F,0FF00h
hlt
;_________________________________
fibo proc near

mov ax,0000h
cmp ax,0001h
jne start

cmp dl,cl
ja fin
add bh,bl
mov bl,dh
mov dh,bh
inc dl
call fibo

start: push bp
mov bp,sp
push dx
push bx
mov dx,0100h
mov bx,0000h
mov cx,[bp+4]
inc ax

fin: mov [bp+4],bx
pop bx
pop dx
pop bp

endp fibo
ret
0
yeona9 Messages postés 7 Date d'inscription mardi 4 mars 2014 Statut Membre Dernière intervention 6 mars 2014
4 mars 2014 à 22:16
ET VOILA LA FONCTION PROPRE NON RÉCURSIVE AVEC LAQUELLE J AI TRAVAILLÉ NORMAL ET ELLE MARCHE TRÈS BIEN

jmp debut
val dw 0005h
F dw ?
debut:
mov cx,val
push cx
call fibo
pop F
and F,0FF00h
hlt
;_________________________________
fibo proc near
push bp
mov bp,sp
push dx
push bx
mov dx,0100h
mov bx,0000h
mov cx,[bp+4]


retour: cmp dl,cl
ja fin
add bh,bl
mov bl,dh
mov dh,bh
inc dl

jmp retour

fin: mov [bp+4],bx
pop bx
pop dx
pop bp

endp fibo
ret
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 4/03/2014 à 22:34
Huum.. c'est normal que tu perdes ton cadre de pile oui, puisque tu écris à une adresse illégale! Ton [Bp+04] n'est pas initialisé dans le cadre de pile local et peut être écrasé par toute interruption. Ce qui ne convient pas c'est la manière de retourner le paramètre, il vaut mieux qu'il soit retourné dans "ax" par convention. Sinon, si tu veux retourner un paramètre par la pile, il faut que ce soit l'appelant qui alloue l'espace pour ce paramètre, et non pas la fonction elle-même...
De plus, je trouve que tu fais bien compliqué pour une suite de fibonacci! à quoi bon s'embêter avec une fonction récursive alors qu'il s'agit d'additionner les deux derniers termes pour trouver le suivant! Autrement dit tu ajoute le terme précédent à celui que tu viens de trouver, et ça donne le suivant!
Bon, je fais pas d'asm 16 bits sans structuration, mais en gros ça donnerait ça:

Result DW [0..1000]  

Debut:
Mov DI,@Result
Mov [DI],0
Mov [DI+04],1
Mov CX,998
Mov AX,01

@Bcl:
Add AX,[DI]
Mov [DI+08],AX
Add DI,04
Dec CX;
Jnz @Bcl;


Le chêne aussi était un gland, avant d'être un chêne
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
4 mars 2014 à 22:35
Ha oui alors attend, j'avais pas vu ton post entre-temps, je regarde ce que ça donne!
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 4/03/2014 à 22:43
Ha oui, finalement on fait un peu la même chose maintenant, mais tu peux simplifier tout ton code! En fait la récursivité ne sert à rien du tout, ça ne fait que ralentir et alourdir, ce qu'il faut c'est soit remplir directement un tableau, soit renvoyer un résultat unique après un nombre d'itérations.
Et je vois que tu t'emmêles un peu les pédales dans les registres au niveau de la routine de calcul proprement dite, il faudrait que tu remettes à plat ta boucle maintenant que tu a repensée ta fonction! Tout le corps de fonction c'est de la soupe de registres épars! Et il faut songer que huit bits c'est très limité pour une suite de fibonacci! Tu dois y arriver dès la quinzaine d'itérations!
0
yeona9 Messages postés 7 Date d'inscription mardi 4 mars 2014 Statut Membre Dernière intervention 6 mars 2014
4 mars 2014 à 22:57
oui j'ai bien compris ça, le problème c'est que notre prof a insisté sur cette histoire de récursivité, même vraiment je sais bien qu'elle sert a rien, j'aurai du faire ce travaille plus simple que ça, mais il veut savoir comment on va manipuler la pile, alors je vais essayer ce que vous m'avez dit et je vous dis après qu'est ce que ça donne. Merci énormément pour votre aide :)
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 4/03/2014 à 23:04
De rien, ça me fait plaisir d'aider sur l'assembleur!
J'aurais peut-être plus de temps ce soir, mais je veux bien voir ce que tu auras fais pour résoudre ton problème de pile!
Je pense que pour simplifier, il faut que tu passes les paramètres à la fonction par les registres et que tu récupères par ax en retour (c'est le standard d'appel optimisé de fonction), et les valeurs que tu veux sauver au sein de la fonction, tu les sauves sur la pile. Autrement dit, tu conserves le problème de la pile qu'au sein de la fonction, en empilant avant l'appel récursif et en dépilant après, c'est plus simple. Oublie pas de faire tes calculs sur 16 bits aussi, 8 bits c'est trop court!
Bon courage!
0
yeona9 Messages postés 7 Date d'inscription mardi 4 mars 2014 Statut Membre Dernière intervention 6 mars 2014
4 mars 2014 à 23:13
Merci je vais bien le faire aussi sur 16 bits, je vais vous envoyer ma solution après, je vous souhaite une bonne soiré. Merci
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 7/03/2014 à 10:20
Oui ça va merci! Toi aussi j'espère!

Huuum!
à ce que je vois la récursivité marche par chance plus que par logique en fait! Disons qu'étant donné qu'elle ne sert vraiment à rien ça pose pas de soucis, mais sinon elle ne fonctionnerait pas! Notamment tu te cantonne à mettre les résultats aux deux emplacement définis dès le départ car tu fais "add sp,06" (au lieu de sub sp,06) et sans initialiser les valeurs par la suite! En fait tu ne fais pas du récursif, tu écrases l'appel de fonction précédent et les valeurs locales, donc ça revient au même que d'appeler une seule fonction. Mais de toute façon on ne peut pas récupérer les résultats en les mettant dans des variable locales comme c'est le cas, donc c'est très inutile c'est vrai! Attention au "mov [bp+8],dl " aussi, tu passes en huit bits alors que tu le lis aussi en 16 bits! Entre les deux vaut mieux choisir car certains processeurs stockent l'octet le plus faible en premier et d'autres en dernier, donc les octets sont inversés en mémoire! Sur motorola il faudrait faire "mov [bp+9],dl", donc mieux vaut faire "mov [bp+8],dx".

Et de mon point de vue, j'éliminerais le "push cx" et le fonctionnement aléatoire avec le registre "AL", je mettrais plutôt une comparaison directe avec "val" pour donner la limite. Et aussi il est inutile de faire "push dx", car ça ne sert à rien de sauvegarder sa valeur!
En restant sur la même base je te proposerais ceci qui revient exactement au même:

jmp debut 

val dw 0008h

debut:
push word ptr 0000h
push word ptr 0001h
call fibo
Add sp,04
hlt

fibo proc near
mov dx,[sp+2]
Xchg dx,[sp+4]
Add dx,[sp+4]
Mov [sp+2],dx

cmp dx,val
jb fibo
ret
endp fibo

Ensuite, le fait de réserver un espace pour les variables avant d'appeler est jouable, mais idéalement il faut le faire de manière plus fiable, soit en passant des paramètres via la pile en les officialisant, soit en passant l'adresse des variables utilisées en implémentant un enregistrement pour les déclarer. Sinon le souci c'est qu'à la moindre modification dans la manière d'appeler la fonction on risque de bouleverser le fonctionnement de la fonction elle-même, alors qu'en utilisant des conventions plus souples on contourne le problème. Dans les langages de haut niveau, le passage des paramètres se fait par les registres ou par la pile, mais si l'appel de routine court doit être changé en appel long par exemple, les déplacements sont ajustés automatiquement. Et la convention utilise EAX,EDX et ECX pour passer des paramètres par registre, dans cet ordre, et EAX pour le retour de fonction.

Et si on veut garder l'étalement des valeurs sur la pile il faudrait faire comme ça:

jmp debut

val dw 0008h

debut:
push word ptr 0000h
push word ptr 0001h
call fibo
Add sp,04
hlt

fibo proc near
Sub sp,04
mov dx,[sp+6]
mov [sp+02],dx
add dx,[sp+8]
mov [sp],dx

cmp dx,val
jae Fin
Call Fibo
Fin:
ret 04
endp fibo

Ici on utilise bien la récursivité mais on ne peut pas accéder librement aux valeurs calculées... il faudrait les mettre dans un tableau à part mais la récursivité devient alors complètement inutile! (et l'est déjà ici pour sûr). Je comprend pas pourquoi ton prof ne choisis pas un thème qui nécessite réellement une récursivité tant qu'à faire! C'est vrai que l'assembleur est tellement souple dans les branchements que la récursivité est moins souvent utile que dans les langages de haut-niveau, mais très pratique lorsqu'il s'agit de travailler sur des arbres à profondeur variable, partout où on ne sait pas combien d'éléments on aura à traiter et stocker temporairement.

Par ailleurs je trouverais plus élégant de passer un pointeur sur les deux variables plutôt que laisser la fonction piocher dedans. En fait la fonction ne devrait pas aller chercher au-dessus de l'adresse de retour due au call... Et le fait de stocker ces variables sur la pile est utile lorsqu'on est obligé de re-appeler la fonction tout en gardant des valeurs qui seront réutilisées après le résultat de l'appel, mais dans le cas présent on donne déjà tout à la fonction et il n'y a rien à faire en retour, et on pourrait tout passer pas les registres! Alors ce que je verrais comme solution, c'est que la pile ne serve pas à stocker les valeurs proprement dites, mais à stocker l'emplacement dans lequel elles doivent être stockées (dans un tableau global donc), dans ce cas précis il faudrait commencer par la fin et chaque fonction devrait conserver son pointeur et l'utiliser une fois que le calcul précédent serait effectué...
Voilà, je te laisse repenser le fonctionnement à ta sauce en essayant de faire du récursif véritable si tu en as vraiment besoin et on revoit ça!

Bon courage!

Le chêne aussi était un gland, avant d'être un chêne
0