2009-12-05 15 views
4

Contexte:Comment assurer l'alignement du code 16 octets des routines Delphi?

J'ai une unité d'optimisation des routines Delphi/de BASM, la plupart du temps pour les calculs lourds. Certaines de ces routines contiennent des boucles internes pour lesquelles je peux obtenir une accélération significative si le début de la boucle est aligné sur une limite DQWORD (16 octets). Je peux m'assurer que les boucles en question sont alignées comme je le souhaite SI je connais l'alignement au point d'entrée de routine.

Pour autant que je puisse voir, le compilateur Delphi aligne les procédures/fonctions aux limites DWORD, et par ex. l'ajout de fonctions à l'unité peut modifier l'alignement des suivantes. Cependant, tant que je place la fin des routines à des multiples de 16, je peux m'assurer que les routines suivantes sont également alignées - ou mal alignées, en fonction de l'alignement de la première routine. J'ai donc essayé de placer les routines critiques au début de la section d'implémentation de l'unité, et de leur mettre un peu de code de remplissage pour que la première procédure soit alignée DQWORD.

Cela ressemble à quelque chose comme ci-dessous:

interface 

procedure FirstProcInUnit; 

implementation 

procedure __PadFirstProcTo16; 
asm 
    // variable number of NOP instructions here to get the desired code length 
end; 

procedure FirstProcInUnit; 
asm //should start at DQWORD boundary 
    //do something 
    //padding to align the following label to DQWORD boundary 
    @Some16BAlignedLabel: 
     //code, looping back to @Some16BAlignedLabel 
    //do something else 
    ret #params 
    //padding to get code length to multiple of 16 
end; 

initialization 

__PadFirstProcTo16; //call this here so that it isn't optimised out 
ASSERT ((NativeUInt(Pointer(@FirstProcInUnit)) AND $0F) = 0, 'FirstProcInUnit not DQWORD aligned'); 

end. 

C'est un peu d'une douleur dans le cou, mais je peux obtenir ce genre de choses à travailler, si nécessaire. Le problème est que lorsque j'utilise une telle unité dans différents projets, ou que je fais des changements à d'autres unités dans le même projet, cela peut encore casser l'alignement de __PadFirstProcTo16 lui-même. De même, recompiler le même projet avec différentes versions du compilateur (par exemple D2009 vs. D2010) casse généralement l'alignement. Donc, la seule façon de faire ce genre de chose que j'ai trouvé était à la main comme la dernière chose à faire quand tout le reste du projet est dans sa forme finale.

Question 1:

est-il un autre moyen pour obtenir l'effet désiré d'assurer que les routines (au moins certains spécifiques) sont alignés DQWORD?

Question 2:

Quels sont les facteurs exacts qui affectent l'alignement du compilateur de code et (comment) pourrais-je utiliser ces connaissances spécifiques pour résoudre le problème décrit ici? Supposons que, pour répondre à cette question, «ne vous inquiétez pas de l'alignement du code/des avantages associés vraisemblablement à une petite vitesse», et non une réponse admissible.

+1

Note: J'ai également posté au forum BASM Embarcadero: http: //forums.codegear.com/thread.jspa?threadID = 29333 – PhiS

Répondre

7

A partir de Delphi XE, le problème de l'alignement de code est maintenant facilement résolu en utilisant la directive du compilateur $CODEALIGN (voir this Delphi documentation page):

{$CODEALIGN 16} 
procedure MyAlignedProc; 
begin 
.. 
end; 
6

Une chose que vous pourriez faire, est d'ajouter une signature « magique » à la fin de chaque routine, après une instruction ret explicite:

asm 
    ... 
    ret 
    db <magic signature bytes> 
end; 

Maintenant, vous pouvez créer un tableau contenant des pointeurs à chaque routine , scanne les routines à l'exécution une fois pour la signature magique pour trouver la fin de chaque routine et donc sa longueur. Ensuite, vous pouvez les copier dans un nouveau bloc de mémoire que vous allouez avec VirtualAlloc en utilisant PAGE_EXECUTE_READWRITE, en vous assurant cette fois que chaque routine commence sur une limite de 16 octets.

+0

Cela semble aussi une option, merci. Je vais étudier cette approche un peu plus loin. – PhiS