C++ とアセンブラでCPU を読みだす。

CPUのプロセッサ情報を読み出し、それを表示してみましょう。
arques.hatenablog.com
のアゼンブラーバージョンです。

#include <iostream>
#include <ios>
#include <iomanip>

using namespace std;

extern "C" void myCpuid(int*, int); // assembler function

void ptintRegs(int fNo, int regs[])
{
    string regName[] = { "EAX", "EBX", "ECX", "EDX" };

    cout << hex << uppercase << setfill('0') << right << setw(8) << fNo << " ";
    for (int i = 0; i < 4; i++)
    {
        cout << hex << setfill('0') << right << setw(8) << regs[i] << " ";
    }
    cout << endl;
}

int main()
{
    int regs[4];

    cout << "基本プロセッサ情報" << endl;
    myCpuid(regs, 0);
    int nMax = regs[0];
    for (int i = 0; i < nMax; i++)
    {
        myCpuid(regs, i);
        ptintRegs(i, regs);
    }

    cout << "拡張機能プロセッサ情報" << endl;
    myCpuid(regs, INT_MIN);
    nMax = regs[0];
    for (int i = 0x80000000; i <= nMax; ++i)
    {
        myCpuid(regs, i);
        ptintRegs(i, regs);
    }
}

アセンブリ関数ソースリスト

__cpuidイントリンシックを、アセンブリ言語の関数で実装します。関数名はmyCpuidです。基本的にmyCpuidは__cpuidイントリンシックと互換があります。

include ksamd64.inc    

_TEXT       segment

;
; rcx = stringの先頭アドレス。
; rdx = function #
;
; 結果は入力のrcxが指す領域に格納する。
; 
        public  myCpuid
        align   16

myCpuid proc    frame           ; prologを使う時はproc frame
        ; prolog
        rex_push_reg    rbx     ; マクロでrbxをpush
        .endprolog              ; end of prolog

        mov     r9, rcx         ; addr

        mov     eax, edx
        cpuid
        mov     [r9+0],  eax
        mov     [r9+4],  ebx
        mov     [r9+8],  ecx
        mov     [r9+12], edx

        ; epilog
        pop     rbx             ; restore
        ret

myCpuid endp

_TEXT   ends
        end

[11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz]で実行:

基本プロセッサ情報
00000000 0000001B 756E6547 6C65746E 49656E69
00000001 000806C1 06100800 7FFAFBBF BFEBFBFF
00000002 00FEFF01 000000F0 00000000 00000000
00000003 00000000 00000000 00000000 00000000
00000004 1C004121 02C0003F 0000003F 00000000
00000005 00000040 00000040 00000003 11121020
00000006 0017EFF7 00000002 00000009 00000000
00000007 00000002 F3BFA7EB 18C05FCE FC100710
00000008 00000000 00000000 00000000 00000000
00000009 00000000 00000000 00000000 00000000
0000000A 08300805 00000000 0000000F 00008604
0000000B 00000001 00000002 00000100 00000003
0000000C 00000000 00000000 00000000 00000000
0000000D 000002E7 00000A80 00000A88 00000000
0000000E 00000000 00000000 00000000 00000000
0000000F 00000000 00000000 00000000 00000000
00000010 00000000 00000004 00000000 00000000
00000011 00000000 00000000 00000000 00000000
00000012 00000000 00000000 00000000 00000000
00000013 00000000 00000000 00000000 00000000
00000014 00000001 0000004F 00000007 00000000
00000015 00000002 00000048 0249F000 00000000
00000016 00000578 00001068 00000064 00000000
00000017 00000000 00000000 00000000 00000000
00000018 00000008 00000000 00000000 00000000
00000019 00000007 00000014 00000003 00000000
0000001A 00000000 00000000 00000000 00000000
拡張機能プロセッサ情報
80000000 80000008 00000000 00000000 00000000
80000001 00000000 00000000 00000121 2C100800
80000002 68743131 6E654720 746E4920 52286C65
80000003 6F432029 54286572 6920294D 31312D35
80000004 37473533 32204020 4730342E 00007A48
80000005 00000000 00000000 00000000 00000000
80000006 00000000 00000000 01007040 00000000
80000007 00000000 00000000 00000000 00000100
80000008 00003027 00000000 00000000 00000000