;Credits to "Core i7" & "bitRAKE"

format PE console

include 'win32a.inc'

_LEN=45
_SIZE=64
_KUSER_SHARED_DATA_ADDRESS = 0x7FFE0000
_PROCESSOR_FEATURES_OFFSET = 0x274

section '.data' readable writeable

    _data     rb _SIZE
    _dummy    dd 0
    _id       dd 0
    _handle   dd 0
    _status   dd 0

    _features dd _00
              dd _01
              dd _02
              dd _03
              dd _04
              dd _05
              dd _06
              dd _07
              dd _08
              dd _09
              dd _10
              dd _11
              dd _12
              dd _13
              dd _14
              dd _15
              dd _16
              dd _17
              dd _18
              dd _19
              dd _20
              dd _21
              dd _22
              dd _23
              dd _24
              dd _25
              dd _26
              dd _27
              dd _28
              dd _29
              dd _30
              dd _31
              dd _32
              dd _33
              dd _34
              dd _35
              dd _36
              dd _37
              dd _38
              dd _39
              dd _40
              dd _41
              dd _42
              dd _43
              dd _44
              dd _45
              dd _46
              dd _47
              dd _48
              dd _49
              dd _50
              dd _51
              dd _52
              dd _53
              dd _54
              dd _55
              dd _56
              dd _57
              dd _58
              dd _59
              dd _60
              dd _61
              dd _62
              dd _63

    _00 db 13,10,"PF_FLOATING_POINT_PRECISION_ERRATA         "
    _01 db 13,10,"PF_FLOATING_POINT_EMULATED                 "
    _02 db 13,10,"PF_COMPARE_EXCHANGE_DOUBLE                 "
    _03 db 13,10,"PF_MMX_INSTRUCTIONS_AVAILABLE              "
    _04 db 13,10,"PF_PPC_MOVEMEM_64BIT_OK                    "
    _05 db 13,10,"PF_ALPHA_BYTE_INSTRUCTIONS                 "
    _06 db 13,10,"PF_XMMI_INSTRUCTIONS_AVAILABLE             "
    _07 db 13,10,"PF_3DNOW_INSTRUCTIONS_AVAILABLE            "
    _08 db 13,10,"PF_RDTSC_INSTRUCTION_AVAILABLE             "
    _09 db 13,10,"PF_PAE_ENABLED                             "
    _10 db 13,10,"PF_XMMI64_INSTRUCTIONS_AVAILABLE           "
    _11 db 13,10,"PF_SSE_DAZ_MODE_AVAILABLE                  "
    _12 db 13,10,"PF_NX_ENABLED                              "
    _13 db 13,10,"PF_SSE3_INSTRUCTIONS_AVAILABLE             "
    _14 db 13,10,"PF_COMPARE_EXCHANGE128                     "
    _15 db 13,10,"PF_COMPARE64_EXCHANGE128                   "
    _16 db 13,10,"PF_CHANNELS_ENABLED                        "
    _17 db 13,10,"PF_XSAVE_ENABLED                           "
    _18 db 13,10,"PF_ARM_VFP_32_REGISTERS_AVAILABLE          "
    _19 db 13,10,"PF_ARM_NEON_INSTRUCTIONS_AVAILABLE         "
    _20 db 13,10,"PF_SECOND_LEVEL_ADDRESS_TRANSLATION        "
    _21 db 13,10,"PF_VIRT_FIRMWARE_ENABLED                   "
    _22 db 13,10,"PF_RDWRFSGSBASE_AVAILABLE                  "
    _23 db 13,10,"PF_FASTFAIL_AVAILABLE                      "
    _24 db 13,10,"PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE        "
    _25 db 13,10,"PF_ARM_64BIT_LOADSTORE_ATOMIC              "
    _26 db 13,10,"PF_ARM_EXTERNAL_CACHE_AVAILABLE            "
    _27 db 13,10,"PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE         "
    _28 db 13,10,"PF_RDRAND_INSTRUCTION_AVAILABLE            "
    _29 db 13,10,"PF_ARM_V8_INSTRUCTIONS_AVAILABLE           "
    _30 db 13,10,"PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE    "
    _31 db 13,10,"PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE     "
    _32 db 13,10,"PF_RDTSCP_INSTRUCTION_AVAILABLE            "
    _33 db 13,10,"PF_RDPID_INSTRUCTION_AVAILABLE             "
    _34 db 13,10,"PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE   "
    _35 db 13,10,"PF_MONITORX_INSTRUCTION_AVAILABLE          "
    _36 db 13,10,"PF_SSSE3_INSTRUCTIONS_AVAILABLE            "
    _37 db 13,10,"PF_SSE4_1_INSTRUCTIONS_AVAILABLE           "
    _38 db 13,10,"PF_SSE4_2_INSTRUCTIONS_AVAILABLE           "
    _39 db 13,10,"PF_AVX_INSTRUCTIONS_AVAILABLE              "
    _40 db 13,10,"PF_AVX2_INSTRUCTIONS_AVAILABLE             "
    _41 db 13,10,"PF_AVX512F_INSTRUCTIONS_AVAILABLE          "
    _42 db 13,10,"PF_ERMS_AVAILABLE                          "
    _43 db 13,10,"PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE       "
    _44 db 13,10,"PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE    "
    _45 db 13,10,"PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE    "
    _46 db 13,10,"PF_ARM_SVE_INSTRUCTIONS_AVAILABLE          "
    _47 db 13,10,"PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE         "
    _48 db 13,10,"PF_ARM_SVE2_1_INSTRUCTIONS_AVAILABLE       "
    _49 db 13,10,"PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE      "
    _50 db 13,10,"PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE "
    _51 db 13,10,"PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE  "
    _52 db 13,10,"PF_ARM_SVE_BF16_INSTRUCTIONS_AVAILABLE     "
    _53 db 13,10,"PF_ARM_SVE_EBF16_INSTRUCTIONS_AVAILABLE    "
    _54 db 13,10,"PF_ARM_SVE_B16B16_INSTRUCTIONS_AVAILABLE   "
    _55 db 13,10,"PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE     "
    _56 db 13,10,"PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE      "
    _57 db 13,10,"PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE     "
    _58 db 13,10,"PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE    "
    _59 db 13,10,"PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE    "
    _60 db 13,10,"PF_BMI2_INSTRUCTIONS_AVAILABLE             "
    _61 db 13,10,"(undocumented) 61                          "
    _62 db 13,10,"(undocumented) 62                          "
    _63 db 13,10,"(undocumented) 63                          "

section '.code' code readable executable

entry $

; BOOL ReadProcessMemory(
;   [in]  HANDLE  hProcess,
;   [in]  LPCVOID lpBaseAddress,
;   [out] LPVOID  lpBuffer,
;   [in]  SIZE_T  nSize,
;   [out] SIZE_T  *lpNumberOfBytesRead
; );

    call    [GetCurrentProcess]
    push    0
    push    _SIZE
    push    _data
    push    _KUSER_SHARED_DATA_ADDRESS + _PROCESSOR_FEATURES_OFFSET
    push    eax
    call    [ReadProcessMemory]
    or      eax, eax
    jz      .quit
    push    STD_OUTPUT_HANDLE
    call    [GetStdHandle]
    mov     [_handle], eax

.redo:
    mov     edx, [_id]
    lea     ebx, [_features]
    shl     edx, 2
    add     ebx, edx
    push    0
    push    _dummy
    push    _LEN
    push    dword [ebx]
    push    [_handle]
    call    [WriteFile]
    mov     edx, [_id]
    movzx   ebx, byte [_data + edx]
    add     ebx, 48
    mov     [_status], ebx
    push    0
    push    _dummy
    push    1
    push    _status
    push    [_handle]
    call    [WriteFile]
    add     [_id], 1
    cmp     [_id], _SIZE
    jb      .redo

.quit:
    push    0
    call    [ExitProcess]

section '.idata' import readable writable

    library kernel, 'KERNEL32.DLL'

    import kernel,\
           ExitProcess, 'ExitProcess',\
           GetStdHandle, 'GetStdHandle',\
           WriteFile, 'WriteFile',\
           ReadProcessMemory, 'ReadProcessMemory',\
           GetCurrentProcess, 'GetCurrentProcess'

