Convention d'appel de fonction PB_ (PB 4.40 x64)

Pour discuter de l'assembleur
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par ker2x »

la doc indique :
General notes:

- Only the registers 'eax', 'edx' and 'ecx' can be destroyed, all other must be preserved.
- A PureFunction name declaration begin always by 'PB_' (ex: PB_Right, PB_Left...)
- The first parameter is passed via the 'eax' register all other are on the stack.
- If Float is used on the first paramater, it's not passed on 'eax' but on 'ST0'
(first FPU register).
- Float or Double result must be put on ST0.
- Quad result has to be put in 'eax' (low word) and 'edx' (high word)
Le code asm generé pour appeler une fonction est :

Code : Tout sélectionner

 
; Plot(i,j,iter) 
  PUSH   qword [v_iter]
  MOVZX  rax,word [v_j]
  MOV    rax,rax
  PUSH   rax
  MOVZX  rax,word [v_i]
  MOV    rax,rax
  PUSH   rax
  POP    rcx
  POP    rdx
  POP    r8
  CALL   PB_Plot2
Je comprend pas du tout pourquoi il fait tous ces push et pop... sans parler du "MOV rax, rax" ...

Alors au final, c'est quoi la convention d'appel de fonction PB_ ?
Et quel sont les registres preservés au final ? (en particulier les xmm ? )

merci.
Dernière modification par ker2x le lun. 04/janv./2010 7:22, modifié 1 fois.
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par ker2x »

J'ai changé le code en :

Code : Tout sélectionner

 
  ; Plot(i,j,iter)
  MOVZX  rcx,r13w  ; arg i
  MOVZX  rdx, r14w ; arg j
  MOV    r8, qword [v_iter]
  CALL   PB_Plot2
Sachant que j'avais optimisé plus haut pout que r13w et et r14w contiennent i et j :)

C'est quand meme plus propre, et ca marche :)
Mais ca ne m'aide pas pour connaitre exactement les conventions d'appels.
Dernière modification par ker2x le lun. 04/janv./2010 7:47, modifié 1 fois.
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par ker2x »

Visiblement ca serait : rcx (1er arg), rdx (2eme arg), r8 (3eme arg), r9 (4eme arg), et le reste dans la stack.
et la valeur de retour dans rax.
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Re: Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par Anonyme2 »

Il me semble avoir lu sur le forum anglais, une explication de Fred sur la convention d'appel en 64 bits, mais je ne retrouve pas le lien et la recherche avec les nouveaux forums fonctionne très mal, on ne retrouve presque rien.
Fred
Site Admin
Messages : 2648
Inscription : mer. 21/janv./2004 11:03

Re: Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par Fred »

Plus d'infos ici: http://blogs.msdn.com/freik/archive/200 ... 98200.aspx. Et il faut à tout prix reserver 32 bytes sous Windows quand tu mets un argument sur la pile. Les MOV rax,rax sont comment dire.. superflux :). Je vais regarder ca. utilise des variables de type ".i" ca evitera la convertion en 64 bits. Il est pas conseiller de typer les variables en pur, sauf quand c'est pour des raisons bien precises.
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par ker2x »

Merci pour l'info, je vais lire ca.

Je force justement le 64bits car derriere je patche le code FASM (j'ai arreté l'inline ASM, pas assez souple) et utilise des instructions SSE,2,3 x64.
La portabilité c'est pas mon soucis :)

Au passage, il est tres facile d'optimiser du code FASM genere par PureBasic.
D'une part grace au code commenté, d'autre part parce PureBasic ne genere pas toujours du code optimal :)
Fred
Site Admin
Messages : 2648
Inscription : mer. 21/janv./2004 11:03

Re: Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par Fred »

Qu'est ce qu'il manque à l'inline asm pour que ce soit plus souple ?
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par ker2x »

Il manque aucune feature.
Mais comme l'optimisation consiste a modifier le code fasm generé par purebasic pour qu'il soit plus rapide, c'est plus simple de bosser directement sur le fichier FASM que de remplacer les fonctions purebasic par de l'InlineASM.

Bon par contre ca veut dire qu'on ne peut plus recompiler le fichier .pb sous peine d'ecraser toutes les optimisations.

Les 2 methodes ont leurs avantages et inconveniants :)


Mais de cette maniere j'ai triplé la vitesse de mon appli :
1) FPU -> SSE
2) deplacer des "MOV" hors des boucles critiques et utilisation des registres xmm0..15, puis reécriture des registres en memoire en sortie de boucle. plutot que de faire des lectures ecritures multiples en memoire a l'interieur des boucles.
3) utilisation des "packed" instructions (mmx, sse, ...)
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par ker2x »

Ha bein j'avais bien trouvé, une partie du moins :)

The x87 register stack is unused. It may be used, but must be considered volatile across function calls. All floating point operations are done using the 16 XMM registers.
The arguments are passed in registers RCX, RDX, R8, and R9.
If the arguments are float/double, they are passed in XMM0L, XMM1L, XMM2L, and XMM3L.
In addition to these registers, RAX, R10, R11, XMM4, and XMM5 are volatile.
Par contre je ne comprend toujours pas :
- The caller is responsible for allocating space for parameters to the callee, and must always allocate sufficient space for the 4 register parameters, even if the callee doesn’t have that many parameters.
- il faut à tout prix reserver 32 bytes sous Windows quand tu mets un argument sur la pile.

reserver ? ou ? quoi ? comment ?
Fred
Site Admin
Messages : 2648
Inscription : mer. 21/janv./2004 11:03

Re: Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par Fred »

Par example la fonction "Truc(a,b,c,d,e)". L'appel sera le suivant:

Code : Tout sélectionner

 PUSH qword [e]
  MOV r9,d
  MOV r8,c
  MOV rdx,b
  MOV rcx,a
  SUB rsp,32 ; Reserve 32 bytes (4 * 8) qui sera utilisé par la fonction pour mettre rcx->r9 sur la stack (si besoin est)
  CALL Truc
  ADD rsp,32
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: Convention d'appel de fonction PB_ (PB 4.40 x64)

Message par ker2x »

Je viens de trouver ca sur un site :
Bien que la pile utilise des quadruples mots (8 octets soit 64 bits), le pointeur de pile (RSP) doit toujours être aligné sur un multiple de 16 avant d'appeler une API.

Ref. : AMD64 ABI Ref. : http://msdn2.microsoft.com/en-us/librar ... S.80).aspx

Pour se prémunir de ce problème, on peut utiliser un code comme celui-ci :

Code : Tout sélectionner

PUSH RSP             ; sauvegarde la position courante de RSP sur la pile
PUSH [RSP]           ; garde une autre copie sur la pile
AND SPL,0F0h         ; ajuste RSP pour aligner la pile au cas où elle ne le serait pas.
                     ;
                     ;  paramètre(s) de l'API s'il y a lieu.
                     ;
SUB RSP, 32d         ; ajuste RSP pour la sauvegarde des paramètres (32d = 0x20)
CALL API
ADD RSP, xx          ; nettoie la pile (avec xx = 32d + (nombre de paramètre poussés * 8))
POP RSP              ; restaure RSP à sa valeur originale.
N.B : Certaines APIs supportent une pile mal alignée sans déclencher d'exception. Certaines déclenchent une exception en interne et rétablissent (toujours en interne) une pile alignée. D'autres encore ne supportent aucunement une pile mal alignée. Dans le doute : alignez la pile avant l'appel.
Merci pour ton aide.
Répondre