Question

Contexte:

J'ai une unité d'optimisation des routines Delphi / de BASM, la plupart du temps pour les calculs lourds. Certains de ces sous-programmes contiennent des boucles intérieures pour lesquelles je peux réaliser une accélération significative si le début de la boucle est alignée sur une frontière DQWORD (16 octets). Je peux assurer que les boucles en question sont alignées comme on le souhaite si je sais l'alignement au point d'entrée de routine.

Pour autant que je peux voir, le compilateur Delphi aligne les procédures / fonctions aux limites DWORD, et par exemple ajoutant des fonctions de l'appareil peut modifier l'alignement de celles ultérieures. Toutefois, aussi longtemps que l'extrémité tampon de routines à des multiples de 16, je peux faire en sorte que les routines suivantes sont également alignés - ou mal alignée, 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 de mise en œuvre de l'unité, et de mettre un peu de code de remplissage avant eux afin que la première procédure serait DQWORD alignée.

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.

est un peu d'une douleur dans le cou, mais je peux obtenir ce genre de chose à travailler, si nécessaire. Le problème est que lorsque j'utilise une telle unité dans différents projets ou apporter des modifications à d'autres unités dans le même projet, cela peut encore briser l'alignement de __PadFirstProcTo16 lui-même. De même, recompiler le même projet avec les différentes versions du compilateur (par exemple par rapport à D2009 D2010) rompt généralement aussi l'alignement. Ainsi, la seule façon de faire ce genre de chose que j'ai trouvé à la main que la dernière chose à peu près à faire quand tout le reste du projet est sous sa forme définitive.

Question 1:

est-il un autre moyen pour obtenir l'effet souhaité de faire en sorte que (au moins une partie spécifique) routines sont alignées DQWORD?

Question 2:

Quels sont les facteurs exacts qui affectent l'alignement du compilateur de code et (comment) pourrait-je utiliser ces connaissances spécifiques pour résoudre le problème décrit ici?

On suppose que pour le bien de cette question « ne vous inquiétez pas de l'alignement de code / les avantages de vitesse associés probablement faible » est pas une réponse admissible.

Était-ce utile?

La solution

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

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

Autres conseils

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 vers chaque routine, analyser les routines à 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 délimitez avec VirtualAlloc en utilisant PAGE_EXECUTE_READWRITE, assurant que chaque fois ce programme commence sur une limite de 16 octets.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top