2014-03-04 8 views
5

Ich habe ein Programm für AES-Operationen.Muss ich mehrere ausführbare Dateien für das Targeting verschiedener Befehlssätze erstellen?

Einige fortgeschrittene CPUs haben AES-NI-Befehlssatz und andere CPUs haben nicht.

Muss ich mein Programm in zwei ausführbare Dateien kompilieren: A_with_aes_ni.exe und B_without_aes_ni.exe?

+0

eine Alternative ist, die Verschlüsselung Sachen in einer dynamischen/gemeinsam genutzte Bibliothek zu trennen, die dann zwei Versionen haben –

+0

Sie könnten zwei Funktionen innerhalb der gleichen exe schreiben, eine, die AES-Anweisungen verwendet, eine andere, die AES in der Software ausführt, und dann zur Laufzeit auf der Basis der Ausgabe von CPUID zwischen ihnen auswählen. –

+0

@AndrewTomazos, meinst du, ich muss Assembler-Codes in meine C-Quelldateien einbetten? – xmllmx

Antwort

6

Was Sie wollen, heißt ein CPU-Dispatcher. Agner Fog hat 10 Seiten Text dazu in Kapitel 3 "Kritischen Code in mehreren Versionen für verschiedene Befehlssätze" von seinem Optimizing C++ manual. Er bespricht das sowohl mit GCC als auch mit ICC.

Sie benötigen nur eine ausführbare Datei, aber Sie müssen zwei verschiedene Objektdateien mit und ohne AES kompilieren. Dann ermittelt der Dispatcher, welcher Befehlssatz verfügbar ist, und wählt den darauf basierenden Codepfad aus.

Ich habe versucht, dies mit MSVC2010 cpu dispatcher for visual studio for AVX and SSE zu tun, ist aber nicht erfolgreich. Ich vermute, ich könnte es jetzt aber funktionieren.

Edit: In Agner Fog vectorclass er hat eine Datei dispatch_example.cpp und instrset_detech.cpp, die meisten haben sollten, was Sie brauchen einen Dispatcher zu machen. Sie müssen noch herausfinden, wie Sie feststellen können, ob eine CPU über AES verfügt. Sie müssen die Datei intrset_detect.cpp erweitern. Gemäß wikipedia wird beim Lesen der CPUID das Bit 23 im Register ECX gesetzt, wenn die CPU AES hat. Wikipedia Codebeispiele auch CPUID lesen muss (neben instrset_detech.cpp - ein weiteres gutes Beispiel ist bei https://github.com/Mysticial/Flops in der Datei cpuid.c)

2

Ein Weg, wir dies in Solaris tun ist, um Hardware-Fähigkeiten Bibliotheken, die zur Laufzeit durch den Linker dynamisch geladen werden.

Eine weitere Möglichkeit besteht darin, zuerst einen Trap-Handler für illegale Anweisungen zu laden und anschließend die gewünschten Anweisungen für die Maschinensprache zu testen. Wenn Sie die Falle treffen, dann wissen Sie, dass Sie die optimierte Version nicht verwenden können und die nicht optimierte (oder weniger optimierte) laden müssen.

Während ich Andrew Vorschlag oben mag, denke ich, dass es sicherer ist, für die spezifischen Anweisungen zu testen, die Sie benötigen. Auf diese Weise müssen Sie nicht Ihre Ihre App für neuere CPUID-Ausgabe aktualisieren.

Bearbeitet zu hinzufügen: Ich weiß, ich hätte ein Beispiel zur Verfügung gestellt. Für Solaris libc auf der x64 Plattform bieten wir hw-optimierte Versionen der Bibliothek - drei sind für 32bit, eins für 64bit. Wir können die Unterschiede sehen von elfdump -H auf die Datei von Interesse ausgeführt wird:

s11u1:jmcp $ elfdump -H /usr/lib/libc/libc_hwcap1.so.1 

Capabilities Section: .SUNW_cap 

Object Capabilities: 
    index tag    value 
     [0] CA_SUNW_HW_1  0x86d [ SSE MMX CMOV SEP CX8 FPU ] 

Symbol Capabilities: 
    index tag    value 
     [2] CA_SUNW_ID  hrt 
     [3] CA_SUNW_HW_1  0x40002 [ TSCP TSC ] 

    Symbols: 
    index value  size  type bind oth ver shndx   name 
     [1] 0x000f306c 0x00000225 FUNC LOCL D 0 .text   gettimeofday%hrt 
     [2] 0x000f2efc 0x00000165 FUNC LOCL D 0 .text   gethrtime%hrt 

Capabilities Chain Section: .SUNW_capchain 

Capabilities family: gettimeofday 
    chainndx symndx  name 
     1 [702]  gettimeofday 
     2 [1]   gettimeofday%hrt 

Capabilities family: gethrtime 
    chainndx symndx  name 
     4 [1939]  gethrtime 
     5 [2]   gethrtime%hrt 

s11u1:jmcp $ elfdump -H /usr/lib/libc/libc_hwcap2.so.1 

Capabilities Section: .SUNW_cap 

Object Capabilities: 
    index tag    value 
     [0] CA_SUNW_HW_1  0x1875 [ SSE2 SSE MMX CMOV AMD_SYSC CX8 FPU ] 

Symbol Capabilities: 
    index tag    value 
     [2] CA_SUNW_ID  hrt 
     [3] CA_SUNW_HW_1  0x40002 [ TSCP TSC ] 

    Symbols: 
    index value  size  type bind oth ver shndx   name 
     [1] 0x000f253c 0x00000225 FUNC LOCL D 0 .text    gettimeofday%hrt 
     [2] 0x000f23cc 0x00000165 FUNC LOCL D 0 .text   gethrtime%hrt 

Capabilities Chain Section: .SUNW_capchain 

Capabilities family: gettimeofday 
    chainndx symndx  name 
     1 [702]  gettimeofday 
     2 [1]   gettimeofday%hrt 

Capabilities family: gethrtime 
    chainndx symndx  name 
     4 [1939]  gethrtime 
     5 [2]   gethrtime%hrt 

Vermutung, die der oben für AMD-Systeme ist, und die für Intel?

Der Solaris-Linker hat Smart, um die richtige hwcap-Bibliothek zur Laufzeit zu laden, bevor Ihr Prozess '_init() aufgerufen wird.