C++とアセンブラーでCPUのキャッシュ情報を表示する

キャッシュ情報を読み込み表示してみましょう。
arques.hatenablog.com
のアゼンブラーバージョンです。

C++ソースリスト

include <iostream>

using namespace std;

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

int main()
{
    int regs[4];
    const unsigned int id = (unsigned int)0x80000006;

    myCpuid(regs, 0x80000000);
    if ((unsigned int)regs[0] >= id)
    {
        myCpuid(regs, 0x80000006);
        int nCacheLineSize = regs[2] & 0xff;
        int nL2Associativity = (regs[2] >> 12) & 0xf;
        int nCacheSizeK = (regs[2] >> 16) & 0xffff;

        cout << "Cache Line Size = " << nCacheLineSize << endl;
        cout << "L2 Associativity = " << nL2Associativity << endl;
        cout << "Cache Size =  " << nCacheSizeK << "[Kb]" << endl;
    }
}

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

__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

実行例:

Cache Line Size = 64
L2 Associativity = 7
Cache Size = 256[Kb]