AVX-Based Timing Side Channel - ASLR Detection


AVX

1 - Description :

- This project implements a low-level side channel based on AVX instructions to detect the presence of Address Space Layout Randomization (ASLR) in hardened Linux environments. It performs memory loading on a known libc symbol (open() in libc) and measures access latency using RDTSCP to infer the state of the memory layout. Fast access indicates a static layout where ASLR is disabled or bypassed, while slow access or a SIGSEGV suggests randomized or unmapped memory. The system utilizes advanced CPU features—AVX, AVX2, TSX, RDTSC, and RDTSCP—to construct a timing-based oracle that operates without direct memory inspection. Signal handling via sigsetjmp/siglongjmp ensures recovery from illegal instructions and segmentation faults without terminating the process. Execution is isolated using fork(), allowing the probing logic to run in a child process while the parent monitors its state via wait() and syscall-level introspection. This implementation transforms timing analysis into a deterministic side-channel framework capable of detecting ASLR through pure architectural feedback, without relying on brute-force techniques or binary parsing.

1.1 - Technique Overview :

- This technique detects the presence of Address Space Layout Randomization (ASLR) by performing AVX-based memory loads on known function addresses—such as open() in libc—and measuring access latency using RDTSCP. The number of CPU cycles required for access serves as a timing oracle: fast access indicates a mapped address, while slower access suggests randomized or unmapped memory. To enhance detection accuracy, optional SIGSEGV handling is implemented to catch illegal memory accesses, providing an additional side-channel signal. The method leverages modern CPU features—AVX, AVX2, TSX, RDTSC, and RDTSCP—to construct a precise timing-based side channel that reveals memory layout randomization patterns. This approach demonstrates how low-level architectural feedback can be used to bypass ASLR protections, exposing potential vulnerabilities in system-level security mechanisms.

1.2 - Check AVX :

- In this step, the script checks the system's support for CPU features required for AVX-based timing attacks, including AVX, AVX2, TSX, RDTSC, and RDTSCP. This ensures the environment is capable of performing precise memory access timing for ASLR detection :

2 - Requirements :

3 - Run :


# gcc avx.c -o AVX # ./AVX

4 - Output example :

 
[+] Fork CALL success.
[+] Child PID : 3113
[+] Running  PID : 3112
[+] Address Varaible Status : 0x7ffea48dec7c
[+] Parent PID : 3112 (dec : 3112)
[+] PID : 3113
[+] CPU Supported AVX + OSXSAVE . 
[+] Check Support RDTSC / RDTSCP...
  +-----------------------------------------------------------------------------+
| EAX : 0x406e3 CPUID Function 1        
| Dec : 263907
| Bin : 0000 0000 0000 0100 0000 0110 1110 0011 
+-----------------------------------------------------------------------------+
[+] RDTSC Supported (Bit shift 4 EDX).
[+] RDTSCP Supported (Bit shift 27 EDX).
[+] Check Support TSX (Transactional Synchronization Extensions)
+-----------------------------------------------------------------------------+
[+] Arg 1 (CPUID -> EAX = 07H): 
| EAX : 0x7  EAX = 07H CPUID 
| Dec : 7
....

Output Screenshot

5 - Author :

Byte Reaper : -

6 - Code :

File: avx.c — Size: 18,4 KB — Lines: 655

  
        
    #include <immintrin.h>
    #include <signal.h>
    #include <setjmp.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdint.h>
    #include <sys/wait.h>
    #define D_C 150
    #define B_F 32
    
    volatile sig_atomic_t f = 0;
    uint32_t eaxV;
    uint32_t ecxV;
    uint32_t ebxV;
    uint32_t edxV;
    sigjmp_buf b;
    void showBit(unsigned int n)
    {
      for (int i = 31; i >= 0; i--)
      {
         printf("%d", (n >> i) & 1);
         if (i % 4 == 0)
         {
          printf(" ");
         }
         
      }
      printf("\n");
    }
    
    void sH(int sig) 
    {
        const char *mes7 = "\e[0;31m[-] Segfault/Illegal instruction caught\e[0m\n";
        size_t len7 = strlen(mes7);
        __asm__ volatile
        (
        "mov $0x1, %%rax\n\t"
        "mov $0x1, %%rdi\n\t"
        "mov %[mes7], %%rsi\n\t"
        "mov %[len7], %%rdx\n\t"
        "syscall\n\t"
        :
        : [mes7] "r" (mes7),
          [len7] "r" (len7)
        : "rcx", 
          "r11", 
          "memory", 
          "rax", 
          "rdi", 
          "rsi", 
          "rdx"
        
      );
      __asm__ volatile
      (
        "add $0x1, %[f]\n\t"
        : [f] "+r" (f)
        :
        :
      );
        siglongjmp(b, 
          1);
    }
    static void avx(void)
    {
      uint64_t start,end;
      unsigned int time=0;
      uint8_t tmp[B_F];
      pid_t pid;
      long r;
      pid_t tid;
      long v;
      __asm__ volatile
      (
        "syscall"
        : "=a"(r)           
        : "a"(0x27)             
        : "rcx", 
          "r11",
          "memory" 
      );
      pid = (pid_t)r;
      if (pid == 0)
      {
        printf("\e[0;31m[-] Error Get PID !\e[0m\n");
        __asm__ volatile
          (
          "xor %%rdi, %%rdi\n\t"
          "mov $0x3C, %%rax\n\t"
          "syscall\n\t" 
          :
          :
          : "rcx", 
              "r11", 
              "memory", 
              "rax", 
              "rdi"
         );	
      }
      __asm__ volatile
      (
        "add $0x1, %[eaxV]\n\t"
        :[eaxV] "+r" (eaxV)
        :
        :
      );
        __asm__ volatile
        (
            "cpuid"
            : "=a"(eaxV), 
              "=b"(ebxV), 
              "=c"(ecxV), 
              "=d"(edxV)
            : "a"(eaxV)
        );
      printf("\e[0;32m[+] PID : %d\e[0m\n", pid);
        if (ecxV & (1 << 28)) 
        {
          if (!(ecxV & (1U << 27))) 
          {
                printf("\e[0;31m[-] OSXSAVE not supported (kernel/OS may not save YMM)\e[0m\n");
                __asm__ volatile
                (
              "xor %%rdi, %%rdi\n\t"
              "mov $0x3C, %%rax\n\t"
              "syscall\n\t" 
              :
              :
              : "rcx", 
                  "r11", 
                  "memory", 
                  "rax", 
                  "rdi"
              );	
            }
            else 
            {
            printf("[+] CPU Supported AVX + OSXSAVE . \e[0m\n");
            printf("[+] Check Support RDTSC / RDTSCP...\e[0m\n");
            printf("\e[0;35m	+-----------------------------------------------------------------------------+\n");
            printf("\e[0;37m| EAX : 0x%lx CPUID Function 1        \e[0m\n", eaxV);
            printf("\e[0;37m| Dec : %d\e[0m\n", (int)eaxV);
            printf("\e[0;37m| Bin : ");
            showBit(eaxV);
            printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
            __asm__ volatile
            (
                "cpuid"
                : "=a"(eaxV), 
                  "=b"(ebxV), 
                  "=c"(ecxV), 
                  "=d"(edxV)
                : "a"(1)
            );
            int hT = (edxV & (1u << 4)) ? 1 : 0;
            __asm__ volatile
            (
                "cpuid"
                : "=a"(eaxV), 
                  "=b"(ebxV), 
                  "=c"(ecxV), 
                  "=d"(edxV)
                : "a"(0x80000001)
            );
              
            int rdT = (edxV & (1u << 27)) ? 1 : 0;
            if (hT) 
            {
              
                printf("\e[0;34m[+] RDTSC Supported (Bit shift 4 EDX).\e[0m\n");
                if (rdT)
                {
                printf("\e[0;34m[+] RDTSCP Supported (Bit shift 27 EDX).\e[0m\n");
              }
              else
              {
                printf("\e[0;31m[-] RDTSCP Not Supported.\e[0m\n");
              }
                    
            } 
            else 
            {	
              printf("\e[0;31m[-] RDTSC / RDTSCP Not Supported, Exit...\e[0m\n");
              unsigned int a = 0xBA;
              
              printf("	+-----------------------------------------------------------------------------+\e[0m\n");
              printf("\e[0;37m| RAX : 0x%lx sys_gettid  \e[0m\n", 0xBA);
              printf("\e[0;37m| Dec : %d\e[0m\n", (int)0xBA);
              printf("\e[0;37m| Bin : ");
              showBit(a);
              printf("	+-----------------------------------------------------------------------------+\e[0m\n");
                
              __asm__ volatile 
              (
                  "syscall"
                  : "=a" (v)             
                  : "a" (0xBA)        
                  : "rcx", 
                    "r11", 
                    "memory"  
              );
              tid = (pid_t) v;
              if (tid  == 0)
              {
                printf("\e[0;31m[-] Error Get TID value !\e[0m\n");
                __asm__ volatile
                (
                  "xor %%rdi, %%rdi\n\t"
                  "mov $0x3C, %%rax\n\t"
                  "syscall\n\t" 
                  :
                  :
                  : "rcx", 
                      "r11", 
                      "memory", 
                      "rax", 
                      "rdi"
                 );	
              }
              const char *mes2 ="\e[0;31m[-] Error sys_tgkill return value != 0\e[0m\n";
              size_t len2 = strlen(mes2); 
              printf("\e[0;32m[+] TID : %d\e[0m\n", tid);
              unsigned int g = (unsigned int)0xBA;
              printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
              printf("\e[0;33m[+] Arg 1 (sys_tgkill):\e[0m\n");
              printf("\e[0;37m| RAX : 0x%lx syscall  \e[0m\n", 0xEA);
              printf("\e[0;37m| Dec : %d\e[0m\n", (int)0xEA);
              printf("\e[0;37m| Bin : ");
              showBit(g);
              unsigned int g2 = (int)pid;
              printf("\e[0;33m[+] Arg 2 (PID -> %d):\e[0m\n", pid);
              printf("\e[0;37m| RDI : 0x%lx sys_tgkill  \e[0m\n", pid);
              printf("\e[0;37m| Dec : %d\e[0m\n", (int)pid);
              printf("\e[0;37m| Bin : ");
              showBit(g2);
              unsigned int g3 = (int)tid;
              printf("\e[0;33m[+] Arg 3 (TID -> %d):\e[0m\n", tid);
              printf("\e[0;37m| RSI : 0x%lx sys_tgkill  \e[0m\n", tid);
              printf("\e[0;37m| Dec : %d\e[0m\n", (int)tid);
              printf("\e[0;37m| Bin : ");
              showBit(g3);
              unsigned int g4 = (unsigned int)0x9;
              printf("\e[0;33m[+] Arg 4 :\e[0m\n");
              printf("\e[0;37m| RDX : 0x%lx SIGKILL \e[0m \n", 0x9);
              printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x9);
              printf("\e[0;37m| Bin : ");
              showBit(g4);
              printf("	\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
              __asm__ volatile
              (
                "mov $0xEA, %%rax\n\t"
                "mov %q[pid], %%rdi\n\t"   
                "mov %q[tid], %%rsi\n\t" 
                "mov $0x9, %%rdx\n\t"
                "syscall\n\t"
                "cmp $0x0, %%rax\n\t"
                "je .d\n\t"
                ".d:\n\t"
                "mov $0x1, %%rax\n\t"
                "mov $0x1, %%rdi\n\t"
                "mov %[mes2], %%rsi\n\t"
                "mov %[len2], %%rdx\n\t"
                "mov $0x0, %%rdi\n\t"
                "mov $0x3C, %%rax\n\t"
                ".fD:\n\t"
                :
                : [pid] "r" (pid), 
                  [tid] "r" (tid),
                  [mes2] "r" (mes2),
                  [len2] "r" (len2)
                :"rax", 
                 "rdi", 
                 "rsi", 
                 "rdx"
              );
            }
            printf("\e[0;33m[+] Check Support TSX (Transactional Synchronization Extensions)\e[0m\n");
            unsigned int g6 = (unsigned int)0x7;
            printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
            printf("\e[0;33m[+] Arg 1 (CPUID -> EAX = 07H): \e[0m\n");
            printf("\e[0;37m| EAX : 0x%lx  EAX = 07H CPUID \e[0m\n", 0x7);
            printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x7);
            printf("\e[0;37m| Bin : ");
            showBit(g6);
            unsigned int g7= (unsigned int)0x0;
            printf("\e[0;33m[+] Arg 2 (CPUID -> ECX=0H): \e[0m\n");
            printf("\e[0;37m| ECX : 0x%lx  ECX=0H CPUID \e[0m\n", 0x0);
            printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x0);
            printf("\e[0;37m| Bin : ");
            showBit(g7);
            
            __asm__ volatile
            (
              "mov $0x7, %%eax\n\t"
              "mov $0x0, %%ecx\n\t"
              "cpuid\n\t"
              : "=a"(eaxV), 
                    "=b"(ebxV), 
                    "=c"(ecxV), 
                    "=d"(edxV)
                  : "a"(eaxV)
            );
            unsigned int g8= (unsigned int)0x7;
            printf("\e[0;33m[+] Result bit EBX \"TSX\": \e[0m\n");
            printf("\e[0;37m| EBX : 0x%lx  Ebx result \e[0m \n", ebxV);
            printf("\e[0;37m| Dec : %d\e[0m\n", (int)ebxV);
            printf("\e[0;37m| Bin : ");
            showBit(g8);
            printf("	\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
            if (ebxV & (1 << 11))
            {
              printf("[+] TSX/RTM Supported.\e[0m\n");
            }
            else 
            {
              printf("\e[0;31m[-] TSX/RTM  Not Supported\e[0m\n");
            }
            printf("\e[0;34m[+] Check Support AVX2...\e[0m\n");
            
            __asm__ volatile
            (
              "mov $0x7, %%eax\n\t"
              "mov $0x0, %%ecx\n\t"
              "cpuid\n\t"
              : "=a"(eaxV), 
                "=b"(ebxV), 
                "=c"(ecxV), 
                "=d"(edxV)
              :
              : "memory"
            );
            if (ebxV & (1u << 5))
            {
              printf("\e[0;34m[+] AVX2 Supported.\e[0m\n");
            }
            else 
            {
              printf("\e[0;31m[-] AVX2 Not Supported.\e[0m\n");
            }
                  goto run;
          }
           
        }
        else 
        {
            printf("\e[0;31m[-] CPU Not Supported AVX, exit...\e[0m\n");
            unsigned int g9 = (unsigned int)0x3C;
        printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
        printf("\e[0;33m[+] Arg 1 (exit): \e[0m\n");
        printf("\e[0;37m| RAX : 0x%lx  exit syscall \e[0m\n", 0x3C);
        printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x3C);
        printf("\e[0;37m| Bin : ");
        showBit(g9);
        unsigned int g10 = (unsigned int)0x0;
        printf("\e[0;33m[+] Arg 2 (exit): \e[0m\n");
        printf("\e[0;37m| RDI : 0x%lx  \e[0m\n", 0x0);
        printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x0);
        printf("\e[0;37m| Bin : ");
        showBit(g10);
        printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
            __asm__ volatile
            (
          "xor %%rdi, %%rdi\n\t"
          "mov $0x3C, %%rax\n\t"
          "syscall"
          :
          :
          :"rax", 
           "rdi"
          
        );
        }
        
        run :
          void *ptr = (void*) &open;
    
          if (ptr == NULL)
          {
          printf("\e[0;31m[-] Error get Address : NULL pointer !\e[0m\n");
          printf("\e[0;31m[-] Kill Proccess...\e[0m\n");
          printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
          unsigned int g11 = (unsigned int)0x3E;
          printf("\e[0;33m[+] Arg 1 (kill): \e[0m\n");
          printf("\e[0;37m| RAX : 0x%lx  exit syscall \e[0m\n", 0x3E);
          printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x3E);
          printf("\e[0;37m| Bin : ");
          showBit(g11);
          unsigned int g12 = (unsigned int)pid;
          printf("\e[0;33m[+] Arg 2 (PID -> %d): \e[0m\n", pid);
          printf("\e[0;37m| RDI : 0x%lx  PID \e[0m\n", pid);
          printf("\e[0;37m| Dec : %d\e[0m\n", (int)pid);
          printf("\e[0;37m| Bin : ");
          showBit(g12);
          unsigned int g13 = 0x0;
          printf("\e[0;33m[+] Arg 3 (sig -> 0x0): \e[0m\n");
          printf("\e[0;37m| RSI : 0x%lx  PID \e[0m\n", 0x0);
          printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x0);
          printf("\e[0;37m| Bin : ");
          showBit(g13);
          printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
          const char *mes6 = "\e[0;31m[-] Error kill process, exit group...\e[0m\n";
              size_t len6  = (size_t)strlen(mes6);
          __asm__ volatile
          (
            "mov $0x3E, %%rax\n\t"
            "mov %[pid], %%rdi\n\t"
            "mov $0x0, %%rsi\n\t"
            "syscall\n\t"
            "cmp $0x0, %%rax\n\t"
            "je .1\n\t"
            "1.\n\t"
            "mov $0x1, %%rax\n\t"
            "mov $0x1, %%rdi\n\t"
            "mov %[mes6], %%rsi\n\t"
            "mov %[len6], %%rdx\n\t"
            "syscall\n\t"
            "mov $0xE7, %%rax\n\t"
            "mov $0x0, %%rdi\n\t"
            "syscall\n\t"
            ".2:\n\t"
            :
            : [pid] "r" (pid),
              [mes6] "r" (mes6),
              [len6] "r" (len6)
            :"rax", 
             "rdi", 
             "rsi", 
             "rdx",  
             "rcx", 
             "r11",
             "memory"				
          );
              
        }
        int t = 0;
        void* ptr2 = NULL;
        __asm__ volatile
        (
            "lea %[var], %%rax\n\t"   
            "mov %%rax, %[value]\n\t" 
            : [value] "=r" (ptr2)    
            : [var] "m" (t)           
            : "rax"
        );
    
        if (ptr2 == NULL)
        {
          printf("[-] Error get address (flags Varaible)!\n");
        }
        
        printf("[+] flags Varaible time rdtscp address : %p\n", (void*)ptr2);
        __asm__ volatile
        (
            "movl $0, %[f]\n\t"
            : [f] "=m" (f)   
            :              
          :	
        );
        if (sigsetjmp(b, 1) == 0) 
        {
          printf("\e[0;34m[+] Address open() libc : %p\e[0m\n", (void *)ptr);
              start = __rdtscp(&time);
              __m256i ymm0 = _mm256_loadu_si256((__m256i*)ptr);
              __m256i ymm1 = _mm256_setzero_si256();  
              ymm0 = _mm256_xor_si256(ymm0, ymm1);
              _mm256_storeu_si256((__m256i*)tmp, ymm0);
              end = __rdtscp(&time);
              uint64_t result = end - start;
              printf("\e[0;37m[+] Result CPU cycles: %llu\e[0m\n", (unsigned long long) result);
              if ((uint64_t)result < D_C)
              {
              printf("\e[0;36m[+] Fast access, same address\e[0m\n");	
          }
          else 
          {
             printf("\e[0;31m[-] Slow access, ASLR or unmapped address\e[0m\n");
             __asm__ volatile
            (
              "add $0x1, %[t]\n\t"
              :[t] "+r" (t)
              :
              :
            );
          }
        }
        else 
        {
            printf("\e[0;31m[-] Returned from signal handler — load faulted (segfault/illegal instr)\e[0m\n");
            if (f==0) 
            {
              __asm__ volatile
              (
                "add $0x1, %[f]\n\t"
                :[f] "+r" (f)
                :
                :
              );
             }
    
        }
          
        printf("\e[0;35m[+] Result : =============================\e[0m\n");
    
          if (t == 1 && f == 1) 
          {
              printf("\e[0;33m[-] ASLR Detected by AVX-Based Timing Side Channel (rdtscp AND segfault)\e[0m\n");
          } 
          else if (t == 1) 
          {
              printf("\e[0;33m[-] ASLR Detected by AVX-Based Timing Side Channel (rdtscp)\e[0m\n");
          } 
          else if (f == 1) 
          {
              printf("\e[0;33m[-] ASLR Detected by AVX-Based Timing Side Channel (segfault)\e[0m\n");
          } 
          else 
          {
              printf("\e[0;36m[+] ASLR Not Detected by AVX-Based Timing Side Channel.\e[0m\n");
          }
      
          if (f == 0) 
          {
              printf("\e[0;36m[+] No segfault/page-fault detected for load of open()\e[0m\n");
          }
          if (t == 0) 
          {
              printf("\e[0;36m[+] No AVX-based timing side-channel detected (rdtscp)\e[0m\n");
          }
    }
    void run()
    {
        pid_t p;
        long y ;
        __asm__ volatile
        (
            "syscall\n\t"
            : "=a"(y)         
            : "a"(0x39)         
            : "rcx", 
              "r11", 
              "memory"
      );
      p = (pid_t) y;
        if (p < 0)
        {
            printf("[-] Fork Failed !\n");
            __asm__ volatile
            (
          "xor %%rdi, %%rdi\n\t"
          "mov $0xE7, %%rax\n\t"
          "syscall\n\t"
          :
          :
          : "rcx", 
              "r11", 
              "memory", 
              "rax", 
              "rdi"
        );
        }
        p = (pid_t) y;
        if (p == 0)
        {
            printf("[+] Fork CALL success.\n");
            long pI;
            pid_t yP;
            __asm__ volatile
            (
          "syscall\n\t"
          :"=a"(pI)
          :"a"(0x27)
          : "rcx", 
                  "r11", 
                 "memory"
        );
        yP = (pid_t)pI;
            printf("[+] Child PID : %d\n", 
                        (int)yP);
            long ret;
            __asm__ volatile
            (
          "syscall\n\t"
          :"=a"(ret)
          : "a"(0x6E)
          : "rcx", 
                  "r11", 
                 "memory"	
        );
            printf("[+] Parent PID : %ld (dec : %d)\n", 
                        ret, (int)ret);  
            avx();
        }
        else
        {
            printf("[+] Running  PID : %d\n", getpid()); 
                     
            int sT = 0;
            void* addr = NULL;
            __asm__ volatile
            (
                "lea %[var], %%rax\n\t"   
                "mov %%rax, %[value]\n\t" 
                : [value] "=r" (addr)    
                : [var] "m" (sT)           
                : "rax"
            );
        printf("[+] Address Varaible Status : %p\n",(void *)addr);
            long rV;  
            __asm__ volatile
            (
            "mov $0x3D, %%rax\n\t"          
            "mov %q[pidV], %%rdi\n\t"      
            "mov %q[sT], %%rsi\n\t"        
            "mov $0x0, %%rdx\n\t"          
            "xor %%r10, %%r10\n\t"       
            "syscall\n\t"
            : "=a"(rV)                
            : [pidV] "r"(p),
            [sT] "r"(&sT)
            : "rcx", 
              "r11", 
              "memory"    
        );
        p = (pid_t) rV;
        printf("[+] Return Value (wait syscall) : %ld\n",(long)rV);
        printf("[+] Status :  %d\n", (int)sT);
        if ((long)rV!= 0)
        {
          printf("[+] PID Finish Success.\n");
        }
            printf("[+] Parent process completed.\n");
        }
    }
    
    int main()
    {
      printf(" \e[1;37m\t[ Byte Reaper ]\e[0m\n");
      printf(" \e[1;37m[ AVX-Based Timing Side Channel ]\e[0m\n\n");
      run();
      __asm__ volatile
        (
        "xor %%rdi, %%rdi\n\t"
        "mov $0xE7, %%rax\n\t"
        "syscall\n\t"
        :
        :
          : "rcx", 
            "r11", 
            "memory", 
            "rax", 
            "rdi"
      );
    }
      

Download

7 - References :

  • Functions for loading an address into the YMM register : link
  • CPUID (AVX,AVX2,TSX,RTM...) : link