2014-03-04 3 views
5

고려해보십시오. AES 작업을 수행 할 프로그램이 있습니다.다른 명령어 세트를 대상으로 여러 실행 파일을 만들어야합니까?

일부 고급 CPU에는 AES-NI 명령 세트가 있고 다른 CPU에는없는 CPU가 있습니다.

내 프로그램을 A_with_aes_ni.exe와 B_without_aes_ni.exe의 두 가지 실행 파일로 컴파일해야합니까?

+0

대안은 2 개 버전 –

+0

이있는 동적/공유 라이브러리에 암호화 물건을 분리하는 것입니다 (instrset_detech.cpp 외에 또 다른 좋은 예는 파일 cpuid.c에 https://github.com/Mysticial/Flops에있다) 당신은 같은 exe 안에 두 개의 함수를 쓸 수 있습니다. 하나는 AES 명령을 사용하고, 다른 하나는 소프트웨어에서 AES를 수행 한 다음, CPUID로부터의 출력에 따라 실행시에 두 함수를 선택합니다. –

+0

@AndrewTomazos, 내 C 소스 파일에 어셈블리 코드를 임베드해야한다는 것을 의미합니까? – xmllmx

답변

6

원하는 것을 CPU 디스패처라고합니다. Agner Fog는 자신의 Optimizing C++ manual에있는 3 장 "다른 명령어 세트에 대한 여러 버전의 중요한 코드 작성"에서 10 페이지의 텍스트를 제공합니다. 그는 GCC와 ICC 모두와 함께 이것을 논의합니다.

실행 파일이 하나만 필요하지만 AES를 사용하거나 사용하지 않는 두 개의 다른 오브젝트 파일을 컴파일해야합니다. 그런 다음 디스패처는 사용 가능한 명령어 세트를 결정하고이를 기반으로 코드 경로를 선택합니다.

MSVC2010 cpu dispatcher for visual studio for AVX and SSE으로이 작업을 시도했지만 성공하지 못했습니다. 나는 그것이 지금 일할 수 있다고 생각한다.

편집 : Agner 안개의 vectorclass에서 그 파일을 가지고 당신이 디스패처를 만들기 위해 필요한 대부분을 가져야한다 dispatch_example.cppinstrset_detech.cpp. CPU에 AES가 있는지 감지하는 방법을 알아 내야합니다. intrset_detect.cpp 파일을 보강해야합니다. wikipedia에 따르면 레지스터에 CPUID 비트 23을 읽을 때 CPU에 AES가 있으면 ECX가 설정됩니다. 위키 백과는 CPUID를 읽는 코드 예제를 가지고 -

2

Solaris에서이 작업을 수행하는 한 가지 방법은 하드웨어 기능 라이브러리 인 을 링커가 런타임에 동적으로로드하는 것입니다.

다른 옵션은 잘못된 명령어에 대한 트랩 처리기를 먼저로드 한 다음 원하는 기계어 명령어를 테스트하는 것입니다. 함정에 빠지면 최적화 된 버전을 사용할 수없고 최적화되지 않은 (또는 덜 최적화 된) 것을로드해야한다는 것을 알고 있습니다.

위의 Andrew의 제안이 마음에 들지만 특별히 필요한 지침 인 을 테스트하는 것이 더 안전하다고 생각합니다. 그렇게하면 최신 CPUID 출력을 위해 앱을 계속 업데이트 할 필요가 없습니다.

덧붙여 편집 : 나는 예제를 제공해야합니다. x64 플랫폼의 Solaris 'libc의 경우, 우리는 라이브러리의 hw 최적화 버전을 제공합니다. 세 가지는 32 비트 용이고, 하나는 64 비트 용입니다. 우리는 관심의 파일에 elfdump -H 을 실행하여 차이점을 볼 수

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 

맞춰 AMD 시스템을위한 위의, 어느 인텔?

Solaris 링커는 프로세스 '_init()가 호출되기 전에 런타임에 올바른 hwcap 라이브러리를로드하기 위해 런타임에 똑똑합니다.