C++とアセンブラーで開発した関数について一通り解説してきた。今回は、スタックへレジスターの保存を行うだけでなく、スタックに作業領域を割り当てて使う方法を紹介する。レジスターの保護と、作業領域確保の両方を行う例を紹介する。
スタックに作業領域を確保
rbxとrsiレジスターを保護し、かつ2つの作業領域を確保する例を紹介する。アセンブリ関数は、レジスターを保護を行うとともに、作業領域を使用する。以降に、呼び出し側のC++ソースコードを示す。これまでに紹介したものと変更はないが念のため示す。
#include <iostream> using namespace std; extern "C" void myCpuid(int*, int); // assembler function int main() { int regs[4]; char CPUString[(sizeof(int)) * 3 + 1]{}; try { myCpuid(regs, 0); *((int*)(CPUString + 0)) = regs[1]; *((int*)(CPUString + 4)) = regs[3]; *((int*)(CPUString + 8)) = regs[2]; CPUString[sizeof CPUString - 1] = '\0'; cout << "Vender Id: " << CPUString << endl; } catch (...) // その他の例外をキャッチ { cerr << "unknown exeption" << endl; } return 0; }
プロローグ、エピローグ、そして構造体の定義に加え、スタックに確保した作業領域を使う関数を示す。
include ksamd64.inc _TEXT segment ; prolog PROLOG macro stack alloc_stack(size stack) ; prolog mov stack.rbxsv[rsp], rbx mov stack.rsisv[rsp], rsi .endprolog ; end of prolog endm ; epilog EPILOG macro stack mov rbx, stack.rbxsv[rsp] mov rsi, stack.rsisv[rsp] add rsp, size stack ; end of epilog ret endm ; data structure to push on the stack stkF struct rbxsv dq ? rsisv dq ? work0 dq ? work1 dq ? dq ? ; padding stkF ends ; error, if size is not a 16 multiples and plus 8 .erre (size stkF mod 16) eq 8, <the size of stack structure must be 16n+8> ; ; rcx = stringの先頭アドレス。 ; rdx = function # ; public myCpuid align 16 myCpuid proc frame PROLOG stkF ; prolog mov r9, rcx ; save param addr mov eax, edx cpuid mov bl, 'A' mov stkF.work0[rsp], rbx ; use work xor ebx, ebx ; clear eax mov rbx, stkF.work0[rsp] ; restore eax form work mov [r9+0], eax mov [r9+4], ebx mov [r9+8], ecx mov [r9+12], edx EPILOG stkF ; epilog myCpuid endp _TEXT ends end
実行結果:Vender Id: AenuineIntel
コマンドラインでビルド・実行:
C:\Master>ml64 /c asmCode.asm Microsoft (R) Macro Assembler (x64) Version 14.33.31629.0 Copyright (C) Microsoft Corporation. All rights reserved. Assembling: asmCode.asm C:\Master>cl /EHsc /Fe:withWork Source.cpp asmCode.obj Microsoft(R) C/C++ Optimizing Compiler Version 19.33.31629 for x64 Copyright (C) Microsoft Corporation. All rights reserved. Source.cpp Microsoft (R) Incremental Linker Version 14.33.31629.0 Copyright (C) Microsoft Corporation. All rights reserved. /out:withWork.exe Source.obj asmCode.obj C:\Master>withWork Vender Id: AenuineIntel