如何在非汇编例程中使用IACA

3
我一直在使用IACA(Intel的静态代码分析器)进行实验。
当测试汇编片段并手动输入魔术标记字节时,它可以很好地工作,例如:
procedure TSlice.BitSwap(a, b: integer);
asm
  //RCX = self
  //edx = a
  //r8d = b

  mov ebx, 111      // Start IACA marker bytes
  db $64, $67, $90  // Start IACA marker bytes

  xor eax, eax
  xor r10d, r10d

  mov r9d, [rcx]  // read the value
  mov ecx,edx     // need a in cl for the shift
  btr r9d, edx    // read and clear the a bit

  setc al         // convert cf to bit
  shl eax, cl     // shift bit to ecx position

  btr r9d, r8d    // read and clear the b bit

  mov ecx, r8d    // need b in ecx for shift
  setc r10b       // convert cf to bit
  shl r10d, cl    // shift bit to edx position

  or r9d, eax     // copy in old edx bit
  or r9d, r10d    // copy in old ecx bit

  mov [r8], r9d   // store result
  ret

  mov ebx, 222      // End IACA marker bytes
  db $64, $67, $90  // End IACA marker bytes
end;

有没有一种方法可以在非汇编代码前缀/后缀所需的魔术标记,以便我可以分析编译器生成的代码?
我知道我可以从CPU视图中复制生成的汇编代码并创建一个例程,但我希望有一个更简单的工作流程。
编辑 我正在寻找适用于64位编译器的解决方案。我知道我可以在32位编译器中混合使用汇编和普通代码。
更新 @Dsm的建议可行。 @Rudy的技巧不行。
以下虚拟代码有效:
Throughput Analysis Report
--------------------------
Block Throughput: 13.33 Cycles       Throughput Bottleneck: Dependency chains (possibly between iterations)

Port Binding In Cycles Per Iteration:
---------------------------------------------------------------------------------------
|  Port  |  0   -  DV  |  1   |  2   -  D   |  3   -  D   |  4   |  5   |  6   |  7   |
---------------------------------------------------------------------------------------
| Cycles | 1.3    0.0  | 1.4  | 1.0    1.0  | 1.0    1.0  | 0.0  | 1.4  | 2.0  | 0.0  |
---------------------------------------------------------------------------------------

N - port number or number of cycles resource conflict caused delay, DV - Divider pipe (on port 0)
D - Data fetch pipe (on ports 2 and 3), CP - on a critical path
F - Macro Fusion with the previous instruction occurred
* - instruction micro-ops not bound to a port
^ - Micro Fusion happened
# - ESP Tracking sync uop was issued
@ - SSE instruction followed an AVX256/AVX512 instruction, dozens of cycles penalty is expected
X - instruction not supported, was not accounted in Analysis

| Num Of |                    Ports pressure in cycles                     |    |
|  Uops  |  0  - DV  |  1  |  2  -  D  |  3  -  D  |  4  |  5  |  6  |  7  |    |
---------------------------------------------------------------------------------
|   3^   | 0.3       | 0.3 | 1.0   1.0 |           |     | 0.3 | 1.0 |     | CP | ret
|   X    |           |     |           |           |     |     |     |     |    | int3
[... more int3's]
|   X    |           |     |           |           |     |     |     |     |    | int3
|   1    | 1.0       |     |           |           |     |     |     |     |    | shl eax, 0x10
|   1    |           | 0.6 |           |           |     | 0.3 |     |     |    | cmp eax, 0x64
|   3^   |           | 0.3 |           | 1.0   1.0 |     | 0.6 | 1.0 |     | CP | ret
|   X    |           |     |           |           |     |     |     |     |    | int3
|   X    |           |     |           |           |     |     |     |     |    | int3
[...]
Total Num Of Uops: 8

更新2
如果有一个调用语句,IACA似乎会崩溃并不想分析代码。抱怨非法指令。然而,基本思路是有效的。显然,您需要减去初始的ret及其相关成本。


这两个序列都恰好是8个字节。你不能在程序的开头设置 X := $906764000000F6BB,并在结尾处设置 X := $906764000000DEBB 吗?其中 X 是一个 UInt64 类型的变量。 - Rudy Velthuis
如果你无法更改机器代码,静态分析有什么用处呢?<g> - Rudy Velthuis
@RudyVelthuis,那个技巧不起作用。我将int64标记为volatile,这样它就不会被优化掉,移动和实际所需的字节也会显示出来。然而,IACA对代码进行反汇编并看到魔术字节是64位mov的一部分,因此忽略它们:COULD NOT FIND START_MARKER NUMBER 1 - Johan
你如何在Delphi中将UInt64标记为volatile?或者你是在使用C语言吗? - Rudy Velthuis
@RudyVelthuis var [volatile] x:int64;,请参见:http://docwiki.embarcadero.com/RADStudio/Tokyo/zh-CN/Compiler_Attributes - Johan
显示剩余4条评论
1个回答

4

我不使用IACA所以无法测试此想法,如果不可行的话我会删除答案,但你能否尝试这样做:

procedure TForm10.Button1Click(Sender: TObject);
begin
  asm
    //RCX = self
    //edx = a
    //r8d = b

    mov ebx, 111      // Start IACA marker bytes
    db $64, $67, $90  // Start IACA marker bytes
  end;

  fRotate( fLine - Point(0,1), 23 );

  asm
    mov ebx, 222      // End IACA marker bytes
    db $64, $67, $90  // End IACA marker bytes

  end;
end;

这只是一个样例代码,用来检查编译是否成功,目前它可以成功编译。

不幸的是,它只适用于32位系统 - 正如Johan所指出的那样,在64位系统上是不允许的。

对于64位系统,以下内容可能有效,但我无法测试。

procedure TForm10.Button1Click(Sender: TObject);
  procedure Test1;
  asm
    //RCX = self
    //edx = a
    //r8d = b

    mov ebx, 111      // Start IACA marker bytes
    db $64, $67, $90  // Start IACA marker bytes
  end;
  procedure Test2;
  begin
    fRotate( fLine - Point(0,1), 23 );
  end;
  procedure Test3;
  asm
    mov ebx, 222      // End IACA marker bytes
    db $64, $67, $90  // End IACA marker bytes

  end;
begin
  Test1;
  Test2;
  Test3;
end;

最新版本的IACA只适用于x64。64位编译器不允许混合汇编和普通代码。它将适用于32位和旧版本的IACA。 - Johan
@Johan 我修改了代码,做了一个隐秘版本 - 不过我不知道这是否对你的需求有点太复杂了。 - Dsm
这个例程可能会有一个多余的 ret,以及一些对齐代码,但它很可能能够正常工作。 - Johan

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