在内联汇编中将常量读入SSE/AVX寄存器

5

我正在尝试将Lazarus中的.o文件导入到Delphi中。

function Test: boolean;
const
  TestData: array[0..15] of byte = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
asm
  movdqu xmm0,[rip+testData]   //xmm0 should be all zeros
  pcmpeqq xmm1,xmm1        //xmm1 is all ones
  ptest xmm0,xmm1          //ZF = (xmm0 and xmm1) = 0
  setz al                  //return true if test works, false if not
end;

以上程序在Delphi中可行,但在Lazarus中会失败。

我正在使用以下方式导入.o文件:

   {$L 'C:\pathname\TestUnit.o'}

function TESTUNIT_TEST: boolean; external name 'TESTUNIT_$$_TEST$$BOOLEAN';

Lazarus用零偏移替换了对TestData的引用。

AVXGENERATE_TEST:
//never mind the stack frame
0000000000A0F3B0 488D6424F8       lea rsp,[rsp-$08]
//                                                        rel 0? why?
0000000000A0F3B5 F30F6F0500000000 movdqu xmm0,dqword ptr [rel $00000000]
0000000000A0F3BD 660F3829C9       pcmpeqq xmm1,xmm1
0000000000A0F3C2 660F3817C1       ptest xmm0,xmm1
0000000000A0F3C7 0F94C0           setz al
0000000000A0F3CA 488D642408       lea rsp,[rsp+$08]
0000000000A0F3CF C3               ret

以下是从`objdump -dr "C:\ pathname \ TestUnit.o"`的输出结果:

Disassembly of section .text.n_avxgenerate_$$_test$$boolean:

0000000000000000 <AVXGENERATE_$$_TEST$$BOOLEAN>:
   0:   48 8d 64 24 f8          lea    -0x8(%rsp),%rsp
   5:   f3 0f 6f 05 00 00 00    movdqu 0x0(%rip),%xmm0        # d <AVXGENERATE_$$_TEST$$BOOLEAN+0xd>
   c:   00
                        9: R_X86_64_PC32        .data.n_tc_$avxgenerate_$$_testdata
   d:   66 0f 38 29 c9          pcmpeqq %xmm1,%xmm1
  12:   66 0f 38 17 c1          ptest  %xmm1,%xmm0
  17:   0f 94 c0                sete   %al
  1a:   48 8d 64 24 08          lea    0x8(%rsp),%rsp
  1f:   c3

我该如何让Lazarus正确地将常量读入到寄存器中?是否有解决此问题的方法?
我计划在Delphi程序中包含一些使用Lazarus编写的AVX汇编代码。为了测试目的,我只是在这里使用SSE代码。
版本信息: FPC 3.0.0 Lazarus版本1.6.2

我不确定那个回答如何解决我的问题。我并没有让你手动插入任何内容。我只是问你的目标文件(你可能已经从中转储了)是否包含重定位条目,因为这样零偏移就是正常的。 - Jester
@jester,我已经包含了objdump的输出结果。 - Johan
当然,pxor xmm0,xmm0可以不使用常量就能工作 ;) - Arnaud Bouchez
1
如果我没记错的话,引用中的“00000000”是有效的,因为它在链接时被解析。 - Arnaud Bouchez
2
向EMB提出的一个好问题...当你需要外部引用时,我认为Delphi Win64链接器真的很讨厌。 - Arnaud Bouchez
显示剩余8条评论
1个回答

1

一种解决方法是将要导入的例程放到DLL中。


这意味着您不再拥有所有内容的独立.exe文件。


但至少所有代码链接正确。

Lazarus中

library Test_lib;

{$mode delphi}{$H+}

uses
  Classes,
  TestUnit;

{$R *.res}

exports
  Test;

begin
end.    

在Delphi中。
const
  Testlib = 'C:\pathname\Lazarus\Test_lib.dll';

function LazarusTest: boolean; external Testlib name 'Test';

现在的输出是:

0000000110020570 488D6424F8       lea rsp,[rsp-$08]
{                                 links to the correct location VVVVVV}
0000000110020575 F30F6F0553930000 movdqu xmm0,dqword ptr [rel $00009353]
000000011002057D 660F3829C9       pcmpeqq xmm1,xmm1
0000000110020582 660F3817C1       ptest xmm0,xmm1
0000000110020587 0F94C0           setz al
000000011002058A 488D642408       lea rsp,[rsp+$08]
000000011002058F C3               ret

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接