2009-12-05 49 views
4

背景:如何确保Delphi例程的16字节代码对齐?

我有一个优化的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:

这是影响的代码编译器的定位和准确的因素(如何)我可以使用这些特定的知识来克服这里列出的问题呢?

假设为了这个问题“不必担心代码对齐/相关的推测小速度好处”是而不是一个允许的答案。

+1

注:我也张贴了这个给Embarcadero公司的BASM论坛: HTTP: //forums.codegear.com/thread.jspa?threadID = 29333 – PhiS 2009-12-05 13:43:14

回答

7

德尔福XE的,代码比对现在的问题是使用$CODEALIGN编译器指令(见this Delphi documentation page)迎刃而解:

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

一件事,你可以做的,就是在每个例程的末尾添加一个“神奇”的签名,明确ret指令后:

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

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

+0

这似乎也是一种选择,谢谢。我会进一步调查这种方法。 – PhiS 2009-12-06 12:31:04

相关问题