Accueil Ti-Gen Foire Aux Questions Chat sur le chan #tigcc sur IRC
Liste des membres Rechercher Aide
Bienvenue Invité !   Se connecter             Mes sujets   
Administrer
0 membre(s) et 1 visiteur(s) actif(s) durant les 5 dernières minutes Utilisateurs actifs : Aucun membre + 1 visiteur
Avant de poster sur le forum, il y a des régles de bases à respecter pour une bonne entente et un respect de tous.
Veuillez lire la charte du forum.
  :: Index » Forum Ti68K » Programmation Assembleur 68K » Conseil pour un débutant... (11 réponse(s))
./POST DE DEPART (post n°0)   Marquer comme non lu.
seb Ecrit le: Vendredi 28 avril 2006 à 15:24 Déconnecté(e)    Voir le profil de seb Envoyer un email à seb Envoyer un message privé à seb  

Pourquoi ça, ça marche pas ?
Ce n'est qu'un exercice inintéressant, mais c'est censé calculé n!, quand ça marchera...

Voici le code :


Partie en C :

______________________________________________________________

// C Source File
// Created 28/04/2006; 10:05:14


#include <tigcclib.h>
#define _V200

extern short nombre, factoriel;

void _main(void)
{
scanf("%d",&nombre);
fonction_asm();
ngetchx();
}

void fonction_c()
{
printf("%d\n",&factoriel);
}

______________________________________________________________

Partie en ASM :
______________________________________________________________

| Assembly Source File
| Created 28/04/2006; 10:05:00

.data
.even
.global nombre, factoriel

nombre:
.word
factoriel:
.word 1

.text
.global fonction_asm

fonction_asm:

move.w nombre,%d0
move.w factoriel,%d1
etiq1:
cmp.w #1,%d0
bne etiq2
move.w %d1,factoriel
rts

etiq2:
mulu.w %d0,%d1
sub.w #1,%d0
jbsr etiq1

______________________________________________________________
    
./Post n°1   Marquer comme non lu.
Sasume Ecrit le: Vendredi 28 avril 2006 à 16:08 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

seb :
Pourquoi ça, ça marche pas ?

Parce que :
  • Tu n'utilises pas correctement printf. Qu'est-ce que tu veux afficher ? L'adresse de la variable factoriel ? Connais-tu le C avant de tenter d'écrire du code ? Il faut avoir acquis la notion de pointeur pour pouvoir s'exprimer en C.
  • Ton code ASM est incorrect. Tu sais ce que signifie l'instruction jbsr ? As-tu la notion de pointeur de pile ?


Ta façon de calculer la factorielle est pour le moins étrange. Voici du pseudo code :
factorielle(n)
  si n <= 0
    retourner 1
  retourner n*factorielle(n-1)

Voici ce que ça donne en assembleur :
;Paramètre : d0.w = n
; Retourne : d0.l = n!
factorielle:
  tst.w   d0
  bgt.s   \non_nul
    moveq.l #1,d0
    rts
\non_nul:
  move.w  d0,-(a7)
  subq.w  #1,d0
  bsr.s   factorielle
  mulu.w  (a7)+,d0
  rts
    
./Post n°2   Marquer comme non lu.
Sasume Ecrit le: Vendredi 28 avril 2006 à 16:16 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

Au fait, j'oubliais : les données globales (comme le sont tes variables factoriel et nombre) sont stockées, si elles ne sont pas initialisées directement en dur dans le programme. Donc sur TI, cela implique que si ton programme n'est pas archivé (donc qu'il est en RAM), la valeur de la variable sera conservée d'une exécution sur l'autre.
Autrement dit, même si ta fonction était bonne, ton programme n'aurait fonctionné qu'au premier lancement.
    
./Post n°3   Marquer comme non lu.
seb Ecrit le: Vendredi 28 avril 2006 à 17:35 Déconnecté(e)    Voir le profil de seb Envoyer un email à seb Envoyer un message privé à seb  

J'ai lu un certain nombre de documents sur le C.
J'ai compris la notion de pointeur, même si la syntaxe ne m'ai pas familière, loin de là (*n = adresse et &n = contenu, je crois). (du coup, je vois l'erreur dans la partie C).
Ce que je veux, c'est faire quelques pas en assembleur, pour apprendre... et je n'ai pas le temps, pour l'instant, de me familariser avec toutes les subtilités du C. Ma démarche est sûrement un peu étrange... Mais faut-il forcément passer par le C ?
Pour le reste des commentaires, j'en prends connaissance et je réagis plus tard. (A la dernière ligne, c'est jsr que je voulais écrire...)
Merci en tout cas. J'espère ne pas trop énerver tout le monde avec mes questions d'ignorant. Un jour peut-être, je pourrais répondre moi aussi aux questions d'un débutant... ?

    
./Post n°4   Marquer comme non lu.
Kevin Kofler Ecrit le: Vendredi 28 avril 2006 à 18:20 Déconnecté(e)    Voir le profil de Kevin Kofler Envoyer un email à Kevin Kofler Visiter le site WEB de Kevin Kofler Envoyer un message privé à Kevin Kofler  


Dans printf("%d\n",&factoriel);, le & est en trop. (Faut lire les warnings de GCC, aussi...)

Et sinon, jsr est tout aussi faux que jbsr, c'est jbra etiq1 que tu veux (factorielle en itératif). Là, tu mélanges la version itérative et récursive (tu codes une boucle => itératif, mais tu essaies de faire un appel récursif (jbsr)), donc ça foire.
Membre de l'équipe de TIGCC: http://tigcc.ticalc.org
Mainteneur du portage Linux/Unix de TIGCC: http://tigcc.ticalc.org/linux/
Membre de l'équipe de CalcForge: http://www.calcforge.org:70/

Participez à la reprise de Ti-Gen!
    
./Post n°5   Marquer comme non lu.
Sasume Ecrit le: Vendredi 28 avril 2006 à 18:29 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

Merci Kevin pour l'erreur du printf... Ça aurait été bien qu'il comprenne tout seul. #roll#

seb :
J'ai compris la notion de pointeur, même si la syntaxe ne m'ai pas familière, loin de là (*n = adresse et &n = contenu, je crois). (du coup, je vois l'erreur dans la partie C).
Pourtant c'est le contraire : &var représente l'adresse de la variable var et *var donne le contenu à l'adresse pointée par var.
Ma démarche est sûrement un peu étrange... Mais faut-il forcément passer par le C ?
Absolument pas.
Merci en tout cas. J'espère ne pas trop énerver tout le monde avec mes questions d'ignorant.
Non non, c'est bon :)
C'est juste que j'avais l'impression que tu essayais de coder à l'aveuglette, et que cette stratégie est complètement stupide.
Il faut malheureusement commencer par se farcir un peu de documentation sur un langage quand on veut l'utiliser.
Ça prend du temps, mais au moins après tu avances beaucoup plus vite !
    
./Post n°6   Marquer comme non lu.
seb Ecrit le: Samedi 29 avril 2006 à 18:46 Déconnecté(e)    Voir le profil de seb Envoyer un email à seb Envoyer un message privé à seb  

Voilà, ça, ça marche :


PARTIE C :
--------------------------------------------------------------------------------------------------------------
// C Source File
// Created 28/04/2006; 10:05:14


#include <tigcclib.h>
#define _V200

extern short nombre, factorielle;
void fonction_c(void);
void fonction_asm(void);

void _main(void)
{
scanf("%d",&nombre);
fonction_asm();
fonction_c();
ngetchx();
}

void fonction_c()
{
printf("%d\n",factorielle);
}

--------------------------------------------------------------------------------------------------------------

PARTIE ASM :
--------------------------------------------------------------------------------------------------------------
| Assembly Source File
| Created 28/04/2006; 10:05:00

.data
.even
.global nombre, factorielle

nombre:
.word
factorielle:
.word 1

.text
.global fonction_asm

fonction_asm:

move.w nombre,%d0
move.w #1,%d1

etiq1:
cmp.w #1,%d0
jne etiq2
move.w %d1,factorielle
rts

etiq2:
mulu.w %d0,%d1
sub.w #1,%d0
jbra etiq1
--------------------------------------------------------------------------------------------------------------

C'est dèjà bien.

J'ai essayé d'écrire une version récursive... Mais là, je coince vraiment.
L'idée est celle-ci, me semble-t-il : on note que f(n) = n*f(n-1) ; on code ça à l'aide d'une fonction s'appelant elle-même, décrémentant n à chaque appel, jusqu'à ce que n=1. De cette façon, on calcule n*(n-1)*...*2.

Si je lis le code de Titan :

-------------------------------------------------------------------------------------------------------------
;Paramètre : d0.w = n
; Retourne : d0.l = n!
factorielle:
tst.w d0
bgt.s \non_nul
moveq.l #1,d0
rts
\non_nul:
move.w d0,-(a7)
subq.w #1,d0
bsr.s factorielle
mulu.w (a7)+,d0
rts
-------------------------------------------------------------------------------------------------------------

je comprends que la routine retourne 1 quand n = d0 = 0 et m'envoie sinon dans la sous-routine \non_nul. Dans cette partie du programme, on met n = d0 > 0 sur la pile, on décrémente n = d0, et on renvoie au début de factorielle.
Telles que je comprends les choses, ce programme décrémente n = d0 jusqu'à 0, empile les valeurs n, n-1, etc, successivement sur la pile, mais ne les utilise pas et retourne toujours 1. En particulier, j'ai l'impression que la ligne
mulu.w (a7)+,d0
n'est jamais exécutée. Mais je me trompe sûrement...

Bref, comme vous voyez, les progrès sont lents... Mais je suis prévenu, tous les tutoriels le disent bien...

Sinon, en revenant le post sur Kevin ci-dessus, je ne comprends pas pourquoi bra <label> serait à utiliser en itératif, bsr <label> serait à utiliser en récursif... Quelle différence y-a-t-il entre BRanch Always et Branch to Sub-Routine ? Elle nous envoie toutes les deux au même endroit, non ?


Voilà les dernières nouvelles du débuCHIant (Ah! Ah!).



    
./Post n°7   Marquer comme non lu.
Jfg Ecrit le: Samedi 29 avril 2006 à 19:42 Déconnecté(e)    Voir le profil de Jfg Envoyer un email à Jfg Visiter le site WEB de Jfg Envoyer un message privé à Jfg  


je pense que:
comme tu l'as dis, on empile n, n-1,... 1 sur la pile. En fait, chaque appel au ss-prgm factoriel empile d0. Mais les appels récursifs stop quand d0 vaut 1:

move.w d0,-(a7)
subq.w #1,d0

bsr.s factorielle
mulu.w (a7)+,d0
rts


à partir du moment où d0 vaut 1, la fonction fait des rts jusqu'a avoir dépillé et multiplié toutes les valeurs sur la pile.
-Edité le Samedi 29 avril 2006 à 19:43 par Jfg-
Kill Mario
    
./Post n°8   Marquer comme non lu.
Jfg Ecrit le: Samedi 29 avril 2006 à 20:12 Déconnecté(e)    Voir le profil de Jfg Envoyer un email à Jfg Visiter le site WEB de Jfg Envoyer un message privé à Jfg  


Tout d'abord, il faut que tu saches ce qu'est le PC.
Le PC est un registre qui enregistre l'adresse de la prochaine opération à exécuter. À chaque fois qu'une instruction est exécuté, le microprocesseur incrémente le PC pour qu'il pointe sur la prochaine instruction.
On peut modifier manuellement le contenu du PC pour faire des sauts, par exemple avec une instruction comme "BRA".
Si tu veux faire un appel de sous programme tu dois aussi faire un saut au début, mais après la fin de l'exécution du sous-programme tu va vouloir revenir dans le programme principal. La manière dont ce problème est résolu dans le microprocesseur, c'est que avant de modifier le PC pour sauter dans le sous programme, l'adresse de retour est mise sur la pile comme ça le sous programme sait où il devra revenir. Cela est fait avec l'instruction "BSR".

En résumé, bsr fait la même chose que bra (càd change la valeur du registre PC), mais en plus enregistre la valeur du PC sur la pile avant le saut.

=>Les bsr sont utilisés pour faire des appels de fonctions, les bra pour des sauts sans retour.
Kill Mario
    
./Post n°9   Marquer comme non lu.
Sasume Ecrit le: Samedi 29 avril 2006 à 21:53 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

Merci jfg :)
    
./Post n°10   Marquer comme non lu.
seb Ecrit le: Dimanche 30 avril 2006 à 14:44 Déconnecté(e)    Voir le profil de seb Envoyer un email à seb Envoyer un message privé à seb  

Je te remercie aussi.
C'est compris ! Mais sans quelqu'un pour t'expliquer, tu ne peux pas comprendre tout seul !
Merci donc...
    
./Post n°11   Marquer comme non lu.
Kevin Kofler Ecrit le: Dimanche 30 avril 2006 à 21:19 Déconnecté(e)    Voir le profil de Kevin Kofler Envoyer un email à Kevin Kofler Visiter le site WEB de Kevin Kofler Envoyer un message privé à Kevin Kofler  


Si, tout ce que JfG t'a expliqué est écrit dans le 68kguide. :)
Membre de l'équipe de TIGCC: http://tigcc.ticalc.org
Mainteneur du portage Linux/Unix de TIGCC: http://tigcc.ticalc.org/linux/
Membre de l'équipe de CalcForge: http://www.calcforge.org:70/

Participez à la reprise de Ti-Gen!
    
  :: Index » Forum Ti68K » Programmation Assembleur 68K » Conseil pour un débutant... (11 réponse(s))
Pages : 1/1     « [1] » »|

.Répondre à ce sujet
Les boutons de code
[B]old[I]talic[U]nderline[S]trikethrough[L]ine Flip Hori[Z]ontallyFlip [V]erticallySha[D]ow[G]low[S]poilerCode [G][C]ite
Bullet [L]istList Item [K] Link [H][E]mail[P]icture SmileysHelp
Couleurs :
Saisissez votre message
Activer les smileys
     

Forum de Ti-Gen v3.0 Copyright ©2004 by Geoffrey ANNEHEIM
Webmaster: Kevin KOFLER, Content Admins: list, Server Admins: Tyler CASSIDY and Kevin KOFLER, DNS Admin: squalyl
Page générée en 71.02ms avec 18 requetes