C++とアセンブラでCPU brand stringを表示

CPU brand stringを、C++から自身で開発したアセンブリ関数を呼び出し、表示してみた。
arques.hatenablog.com
のアゼンブラーバージョンです。

C++ソースリスト

#include <iostream>

extern "C" void asmCode(char*); // assembler function

int main()
{
    char CPUBrandString[4 * 4 * 3 + 1]{};

    asmCode(CPUBrandString);

    CPUBrandString[sizeof CPUBrandString -1] = '\0';
    std::cout << "CPU Brand String: " << CPUBrandString << std::endl;
}

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

asmCode の rcx には stringの先頭アドレスが格納されているので、そこへ読みだしたデータを書き込むが、 rcx は途中で利用するので、volatile な r9 をかわりに利用する。
rbx は非volatile だが、途中で破壊されるので、volatile な r10 を使って保存・復旧する。

_TEXT       segment

        public asmCode
        align 16

asmCode proc
        mov     r10, rbx        ; save reg

        mov     r9, rcx         ; addr

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

        mov     eax, 80000003h
        cpuid
        mov     [r9+16], eax
        mov     [r9+20], ebx
        mov     [r9+24], ecx
        mov     [r9+28], edx

        mov     eax, 80000004h
        cpuid
        mov     [r9+32], eax
        mov     [r9+36], ebx
        mov     [r9+40], ecx
        mov     [r9+44], edx

        mov     rbx, r10        ; restore
        ret

asmCode endp

_TEXT   ends
            end


prolog、epilogを持つアセンブリ関数ソースリスト

先のアセンブリ関数を書き換えて、少しスマートにする。
rbx は非volatile なので保護する必要がある。上の例は、たまたま空いてた r10 を使って保存・復旧したが、本例ではスタックに保存・復旧する。C++のコードは、先の例と同じものを使用する。

include ksamd64.inc

_TEXT       segment

        public  asmCode
        align   16

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

        mov     r9, rcx         ; addr

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

        mov     eax, 80000003h
        cpuid
        mov     [r9+16], eax
        mov     [r9+20], ebx
        mov     [r9+24], ecx
        mov     [r9+28], edx

        mov     eax, 80000004h
        cpuid
        mov     [r9+32], eax
        mov     [r9+36], ebx
        mov     [r9+40], ecx
        mov     [r9+44], edx

        ; epilog
        pop     rbx             ; restore
        ret

asmCode endp

_TEXT   ends
            end

実行例: