【问题标题】:How to ensure 16byte code alignment of Delphi routines?如何确保 Delphi 例程的 16 字节代码对齐?
【发布时间】:2009-12-05 13:38:26
【问题描述】:

背景:

我有一个优化的 Delphi/BASM 例程单元,主要用于繁重的计算。其中一些例程包含内部循环,如果循环开始与 DQWORD(16 字节)边界对齐,我可以实现显着的加速。如果我知道例程入口点的对齐方式,我可以确保相关循环按照需要对齐。

据我所知,Delphi 编译器将过程/函数与 DWORD 边界对齐,例如向单元添加功能可能会改变后续功能的对齐方式。但是,只要我将例程的末尾填充为 16 的倍数,我就可以确保后续例程同样对齐 - 或未对齐,具体取决于第一个例程的对齐方式。因此,我尝试将关键例程放在单元实现部分的开头,并在它们之前放置一些填充代码,以便第一个过程与 DQWORD 对齐。

这看起来像下面这样:

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.

这有点让人头疼,但我可以在必要时让这种事情发挥作用。问题是当我在不同的项目中使用这样的单元,或者对同一个项目中的其他单元进行一些更改时,这可能仍然会破坏__PadFirstProcTo16本身的对齐方式。同样,使用不同编译器版本(例如 D2009 与 D2010)重新编译同一项目通常也会破坏对齐。所以,我发现做这种事情的唯一方法是当项目的所有其余部分都处于最终形式时,手工几乎是最后要做的事情。

问题 1:

是否有任何其他方法可以实现确保(至少某些特定)例程与 DQWORD 对齐的预期效果?

问题 2:

影响编译器代码对齐的确切因素有哪些?(如何)我可以使用这些特定知识来克服此处列出的问题?

假设为了这个问题,“不要担心代码对齐/相关的可能很小的速度优势”不是一个允许的答案。

【问题讨论】:

标签: delphi memory-alignment


【解决方案1】:

从 Delphi XE 开始,现在可以使用 $CODEALIGN 编译器指令轻松解决代码对齐问题(请参阅 this Delphi documentation page):

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

【讨论】:

    【解决方案2】:

    您可以做的一件事是在每个例程的末尾添加一个“魔术”签名,在明确的 ret 指令之后:

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

    现在您可以创建一个包含指向每个例程的指针的数组,在运行时扫描例程一次以查找魔术签名以查找每个例程的结尾以及其长度。然后,您可以将它们复制到您使用 PAGE_EXECUTE_READWRITE 使用 VirtualAlloc 分配的新内存块中,确保这一次每个例程都在 16 字节边界上开始。

    【讨论】:

    • 这似乎也是一种选择,谢谢。我将进一步研究这种方法。
    猜你喜欢
    • 2023-04-08
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    相关资源
    最近更新 更多