2017-09-19 1 views
3

J'ai joué avec IACA (analyseur de code statique d'Intel).
Il fonctionne très bien lors des tests avec des extraits d'assemblage où je peux entrer le marqueur magique octets manuellement, comme ceci:Utilisation d'IACA avec une routine non-assemblée

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; 

est-il un moyen de préfixe/suffixe non code assembleur avec les marqueurs magiques nécessaires pour que je puisse analyser le code généré par le compilateur?

Je sais que je peux copier-coller l'ensemble généré à partir de la vue du processeur et de créer une routine à l'aide, mais j'espérais il y a un flux de travail plus facile

EDIT
Je cherche solutions qui fonctionnent dans le compilateur 64 bits. Je sais que je peux mélanger l'assemblage et le code normal dans le compilateur 32 bits.

MISE À JOUR
@ La suggestion de Dsm fonctionne. @ Le tour de Rudy ne fonctionne pas.

Le code fictif suivant fonctionne:

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 

MISE À JOUR 2
S'il y a une déclaration d'appel là-bas AICA semble bombe et que vous souhaitez ne pas analyser le code. Se plaindre d'instructions illégales. Cependant l'idée de base fonctionne. Évidemment, vous devez soustraire le ret initial et son coût associé.

+0

Les deux séquences ont exactement 8 octets. Ne pouvez-vous pas faire: 'X: = $ 906764000000F6BB' au début et' X: = $ 906764000000DEBB' à la fin de votre routine, où 'X' est un' UInt64'? –

+0

À quoi sert l'analyse statique si vous ne pouvez pas changer le code machine? –

+0

@RudyVelthuis, à utiliser comme ligne de base pour la comparaison. Le code non assemblé peut être inséré, le code d'assemblage ne le peut pas. – Johan

Répondre

4

Je ne me IACA je ne peux pas tester cette idée, et je vais supprimer la réponse si elle ne fonctionne pas, mais pouvez-vous pas faire quelque chose comme ceci:

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; 

Ce fut juste un exemple de routine de quelque chose d'autre pour vérifier qu'il compile, ce qu'il fait. Malheureusement, cela ne fonctionne que pour 32 bits - comme le fait remarquer Johan, il n'est pas autorisé pour 64 bits.

Pour 64 bits ce qui suit peut fonctionner, mais encore une fois je ne peux pas le tester.

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

La dernière version de l'IACA ne fonctionne que pour x64. Le compilateur 64 bits n'autorise pas le mélange de l'assembly et du code normal. Il fonctionnera pour les versions 32 bits et plus anciennes de l'IACA. – Johan

+0

@Johan J'ai modifié le code pour une version sournoise - je ne sais pas si c'est un peu trop compliqué pour vos besoins, cependant. – Dsm

+0

Il y aura un 'ret 'étranger et peut-être un code d'alignement au début de la routine, mais cela pourrait très bien marcher. – Johan