Simuler un gosub avec une macro ?

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
Ulix
Messages : 315
Inscription : ven. 04/juin/2004 14:27
Localisation : Frontignan

Simuler un gosub avec une macro ?

Message par Ulix »

Est-il possible de simuler un Gosub avec une macro ?

Pourquoi cette question ?
D'abord je m'attendais a ce que la nouvelle version de PB (Fred tu peut encore la rajouté) permette de geré des gosubs interne a une procedure avec un accés aux variables locale. Hélas...:mad: je suis déçu que ce ne soit pas le cas !

Ensuite un exemple etant plus parlant, voici ce que désirais faire :

Code : Tout sélectionner



;Procedure affichage() 		; Si décommentaire, marche pas
;Protected a, b, c, d
;Static f, g, h, i

a=100:b=50:c=25:d=10

For nombre = 1 To 4
Select nombre
Case 1 : Gosub colonne1
Case 2 : Gosub colonne2
Case 3 : Gosub colonne1_3
Case 4 : Gosub colonne1_5:Gosub colonne2
EndSelect
Next
End


Colonne1:
f+1
Debug "Utilisation de Colonne1 = "+Str(f)
Debug a=a+c
Return

Colonne2:
g+1
Debug "Utilisation de Colonne2 = "+Str(g)
Debug b=d+c
Return

Colonne1_3:
h+1
Debug "Utilisation de Colonne1_3 = "+Str(h)
Debug a=a-b
Return

Colonne1_5:
i+1
Gosub colonne1
Gosub colonne1_3
Debug "Utilisation de Colonne1_5 = "+Str(g)
Return
;EndProcedure

;affichage()




Quelques réflexions (vous les savez !)

On notera que les sous-programmes (labels) peut être appele de plusieurs endroits différents, qu'il peut être utilisé plusieurs fois, enfin qu'un sous-programme peut appeler un autre sous-programme.
Une fois le sous-programme fini, le programme reprend a l'instruction qui suit celle qui l'avait appelé.
Utilisation des gosub/return simplifie le code et le rend plus compacte.
Enfin l'accées aux variables locales permet de ne pas muiltiplié les procedures a l'excés et d'avoir une ribanbelle de données a passés comme arguments.
Bref, je leurs trouve que des avantages ! :lol:

Puisque le "Gosub nouvelle version" n'est pas au rendez-vous, ma question est :

Est-il possible de simuler un Gosub avec une macro ?


Est-il possible lorsque l'on appelle un sous-programme :
- de mémorisé la position mémoire de l'instruction qui appele le sous-programme (j'espére que vous comprenez),
- d'aller au sous-programme (le label:)
- d'executer le sous-programme et une fois finie (donc le return)
- de se repositionné sur l'instruction suivant (position mémoire + 1 instruction).


Je suppose que l'on doit faire appelle a du code assembleur, mais est-il possible d'intégré cela dans une macro ?


Est-il possible de "lorsque l'on appelle un sous-programme, de mémorisé la position mémoire de l'instruction qui appele le sous-programme" ?
Il y a bien la posibilité de connaitre l'adresse d'une variable, la position mémoire : Pointeur = ?Variable, peut-on connaitre l'instruction courante ?

Y a t-il des exemples ? :oops:


Merci de votre patience et de m'avoir lu ! :wink:
Guimauve
Messages : 1015
Inscription : mer. 11/févr./2004 0:32
Localisation : Québec, Canada

Message par Guimauve »

Il suffit simplement d'essayer ...

Enfin je ne sais pas si ça va répondre à ta question, à toi de voir.

Code : Tout sélectionner

Macro SubRoutineColone1()
   f+1
   Debug "Utilisation de Colonne1 = "+Str(f)
   Debug a=a+c
EndMacro 
   
Macro SubRoutineColonne2()
   g+1
   Debug "Utilisation de Colonne2 = "+Str(g)
   Debug b=d+c
EndMacro 
   
Macro SubRoutineColonne1_3()
   h+1
   Debug "Utilisation de Colonne1_3 = "+Str(h)
   Debug a=a-b
EndMacro
   
Macro SubRoutineCcolonne1_5()
   i+1
   SubRoutineColone1()
   SubRoutineColonne1_3()
   Debug "Utilisation de Colonne1_5 = "+Str(g)
EndMacro 


Procedure affichage()       ; Si décommentaire, marche pas
   Protected a, b, c, d
   Static f, g, h, i
   
   a=100
   b=50
   c=25
   d=10
   
   For nombre = 1 To 4
      Select nombre
         Case 1
            SubRoutineColone1()

         Case 2 
            SubRoutineColonne2()

         Case 3 
            SubRoutineColonne1_3()
 
         Case 4 
            SubRoutineCcolonne1_5()
            SubRoutineColonne2()

      EndSelect
   Next
   
   End

EndProcedure

affichage()
Attention très important.

Comme les procédures, si une macro en appelle une autre, le code de la macro appelée doit être placer avant celui de la macro appelante.

A+
Guimauve
Avatar de l’utilisateur
Ulix
Messages : 315
Inscription : ven. 04/juin/2004 14:27
Localisation : Frontignan

Message par Ulix »

Désolé Guimauve !

C'est déja ce que je fais.
Au niveau code source, ça le rend plus lisible - Ok
Au niveau executable, il grossit très rapidement pour peu de chaque macro contiennent plusieurs lignes et que l'on appele plusieurs fois les macros. En effet les macros inserrent le code qu'elle contient a l'endroit d'où on les appelent.

Alors que les vrais "Gosub" permette d'utilisé plusieurs fois la même portion de code. Donc un code plus petit !

Je pensais plutôt a quelque chose comme çà :

Code : Tout sélectionner


Procedure.l go_sub(a, b, c)
  If a = 1
    !jmp near lbl_a1;<-a Gosub here write next address (rett) into  at compilation time and then just jumps.
    !rett:;                                                       |
  EndIf;                                                         |
  ;                                                              /
  Debug "a="+Str(a)+", b="+Str(b)+", c="+Str(c) ;               |
  ProcedureReturn ;                                           /
;                                                              /
!lbl_a1:;                                                     /
;                                                            /
  a = b+c;                                                  /
!jmp near rett;<-------------------------------------------/
EndProcedure

go_sub(1, 1, 1) 

Trouvé sur :

http://www.purebasic.fr/english/viewtop ... ight=gosub


Apparament on mémorise l'endroit d'où on part, on fait un saut jusqu'au label, on l'execute, puis on refait un saut a l'endroit d'où on vient.
Peut-on simule cela avec les macros, ou bien intégré cela dans une macro ?

Mon niveau en langage machine frise la 0, alors de la a comprendre toutes les subtilités ?? :mad:

Trouvé aussi cela :

Code : Tout sélectionner

Procedure.l go_sub(a,b,c)
  If a=1
   ;Gosub routine1
                      !mov dword[l_routine1_ret-4],ret1-l_routine1_ret
                      !jmp l_routine1
                      !ret1:
  EndIf
 
  If a=3
   ;Gosub routine1  ;again
                      !mov dword[l_routine1_ret-4],ret2-l_routine1_ret
                      !jmp l_routine1
                      !ret2:
  EndIf

  Debug "a="+Str(a)+", b="+Str(b)+", c="+Str(c)
  ProcedureReturn
; --------SubRoutines:
  routine1:
   ;Gosub NestedRoutine
                      !mov dword[l_routine2_ret-4],NestRet-l_routine2_ret
                      !jmp l_nestedroutine
                      !NestRet:
    a=b+c
 ;Return:
                      !db $E9,0,0,0,0;<-jmp OpCode and a dword space
                      routine1_ret:

  NestedRoutine:
    b+c
 ;Return:
                      !db $E9,0,0,0,0;<-jmp OpCode and a dword space
                      routine2_ret:
EndProcedure

#PAGE_READWRITE=4
VirtualProtect_(?routine1,?routine2_ret-?routine1,#PAGE_READWRITE,@OrigMode.l)
go_sub(1,1,1)
VirtualProtect_(?routine1,?routine2_ret-?routine1,OrigMode.l,@Mode)
FlushInstructionCache_(GetCurrentProcess_(),?routine1,?routine2_ret-?routine1)

Si quelqu'un sait comme intégrer cette façon de faire dans une Macro, je suis prenneur !
Merci d'avance pour aux idées et solutions. :idea:
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

Tu te compliques la vie à vouloir absolument tout gérer comme çà.
Imagine cette façon de faire dans un programme dépassant les 2 ou 3000 lignes : au secours ! Tu dis qu'il n'y a que des avantages à utiliser les gosub/goto, moi j'y vois surtout un gros manque de lisibilité du code source.

mon expérience perso me conduit à tout mettre en procédures, sinon je n'arrive pas à me dépatouiller dès lors qu'un projet grossit trop...

par contre si tu as un gros besoin de rapidité, je peux comprendre et encore...
Dernière modification par Flype le jeu. 04/mai/2006 16:31, modifié 2 fois.
Image
Guimauve
Messages : 1015
Inscription : mer. 11/févr./2004 0:32
Localisation : Québec, Canada

Message par Guimauve »

Personnellement, moi je ferais des procédures avec les Sous routines si elles ont plusieurs instructions. Si non, des macros.
Oui mais les procédures c'est plus lent et les macros font grossir la taille de l'exe.
Ça va prendre quoi, 50 à 75 Nanosecondes de plus pour faire le travaille. Le fichier exe va faire 100 ko de plus.

Les disques durs les plus courants font 80 Go.

De plus, on ne fait pas d'omelette sans casser des oeufs.

Selon mon point de vue, les instructions GoSub/Goto c'est à banir de la programmation purement et simplement.

Voilà

Guimauve
Répondre