2017-09-19 3 views
3

Ich habe mit IACA (Intels statische Code-Analysator) gespielt.
Es funktioniert gut, wenn es mit Montage-Schnipsel zu testen, wo ich manuell eingegeben der Magic Marker-Bytes kann, wie folgt aus:Verwenden von IACA mit Nicht-Assembly-Routine

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; 

Gibt es eine Möglichkeit/Suffix nicht Assembler-Code Präfix mit den erforderlichen Textmarkern, so dass ich den vom Compiler generierten Code analysieren?

Ich weiß, ich kann die erzeugte Baugruppe von der CPU-Ansicht copy-paste und eine Routine, dass schaffen, aber ich hatte gehofft, dass es einen einfacheren Workflow

EDIT
ist ich suche Lösungen, die im 64-Bit-Compiler funktionieren. Ich weiß, dass ich Assembler- und normalen Code im 32-Bit-Compiler mischen kann.

UPDATE
@ Dsm Vorschlag funktioniert. @ Rudys Trick nicht.

Der folgende Dummy-Code funktioniert:

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 

UPDATE 2
Wenn eine Call-Anweisung ist dort IACA zu bombardieren scheint und will nicht, um den Code zu analysieren. Sich über illegale Anweisungen beschweren. Die Grundidee funktioniert jedoch. Natürlich müssen Sie die ursprünglichen ret und die damit verbundenen Kosten subtrahieren.

+0

Beide Sequenzen sind genau 8 Bytes. Kannst du nicht: 'X: = $ 906764000000F6BB' am Anfang und' X: = $ 906764000000DEBB' am Ende deiner Routine, wo 'X' ein' UInt64' ist? –

+0

Was ist eine statische Analyse, wenn Sie den Maschinencode nicht ändern können?

+0

@RudyVelthuis, als Basislinie zum Vergleich zu verwenden. Non-Assembly-Code kann inline, Assembly-Code nicht sein. – Johan

Antwort

4

Ich benutze IACA nicht so kann ich diese Idee nicht testen, und ich werde die Antwort löschen, wenn es nicht funktioniert, aber kann man nicht einfach so etwas tun:

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; 

Dies war nur eine Beispielroutine von etwas anderem, um zu überprüfen, dass es kompiliert, was es tut.

Leider funktioniert das nur für 32 Bit - Johan weist darauf hin, dass es für 64 Bit nicht erlaubt ist.

Für 64 Bit funktioniert das Folgende, aber ich kann es nicht erneut testen.

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; 
+0

Die neueste Version von IACA funktioniert nur für x64. Der 64-Bit-Compiler erlaubt keine Mischung von Assembly und normalem Code. Es funktioniert für 32-Bit- und ältere Versionen von IACA. – Johan

+0

@Johan Ich habe den Code für eine hinterhältige Version geändert - ich weiß nicht, ob das für Ihre Bedürfnisse etwas zu kompliziert ist. – Dsm

+0

Es wird am Anfang der Routine einen fremden "ret" und vielleicht einen Ausrichtungscode geben, aber es kann sehr gut funktionieren. – Johan