C++とアセンブラー⑦

C++アセンブラーで開発した関数について一通り解説してきた。今回は、戻り値を持つ関数の説明を行う。

戻り値がchar

戻り値がchar の例を紹介する。アセンブリ関数は、ALレジスターに値を設定すると良い。ここで紹介する例は、引数で渡したアルファベットの次の順の文字を返す。例えば、"C"を渡すと"D"を返す。
C++ソースコード

#include <iostream>

using namespace std;

extern "C" char asmCode(char);

int main(void)
{
    char a = 'A';
    char c = asmCode(a);
    cout << "a = " << a << ", c = " << c;

    return 0;
}

アセンブリ言語で記述した関数:

_TEXT       segment

; cl = 入力, al = 出力

        public  asmCode
        align   16

asmCode proc
        mov     al, cl
        inc     al

        ret

asmCode endp

_TEXT   ends
        end

実行結果:a = A, c = B

戻り値がshort

戻り値がshort の例を紹介する。アセンブリ関数は、AXレジスターに値を設定すると良い。ここで紹介する例は、引数で渡した2つのshort値を加算して返す。
C++ソースコード

#include <iostream>

using namespace std;

extern "C" short asmCode(short, short);

int main(void)
{
    short a = 2, b = 3;
    short c = asmCode(a, b);
    cout <<  a << " + " << b << " = " << c;

    return 0;
}

アセンブリ言語で記述した関数:

_TEXT       segment

; rcx = 入力, rdx = 入力, eax  = 出力

        public  asmCode
        align   16

asmCode proc
        add     cx, dx
        mov     ax, cx

        ret

asmCode endp

_TEXT   ends
        end

実行結果:2 + 3 = 5

戻り値がint

戻り値がint の例を紹介する。アセンブリ関数は、RAXレジスターに値を設定すると良い。ここで紹介する例は、引数で渡した2つのint値を加算して返す。
C++ソースコード

#include <iostream>

using namespace std;

extern "C" int asmCode(int, int);

int main(void)
{
    int a = 2, b = 3;
    int c = asmCode(a, b);
    cout <<  a << " + " << b << " = " << c;

    return 0;
}

アセンブリ言語で記述した関数:

_TEXT       segment

; rcx = 入力, rdx = 入力, eax  = 出力

        public  asmCode
        align   16

asmCode proc
        add     cx, dx
        mov     ax, cx

        ret

asmCode endp

_TEXT   ends
        end

実行結果:2 + 3 = 5

戻り値がポインター

戻り値がポインターの例を紹介する。アセンブリ関数は、RAXレジスターに値を設定すると良い。ここで紹介する例は、引数で渡したint* のアドレスを、そのまま返す。
C++ソースコード

#include <iostream>

using namespace std;

extern "C" int* asmCode(int*);

int main(void)
{
    int a = 2;
    int* c = asmCode(&a);
    cout << "a = " << a << ", c = " << (*c) ;

    return 0;
}

アセンブリ言語で記述した関数:

_TEXT       segment

; rcx = 入力, eax  = 出力

        public  asmCode
        align   16

asmCode proc
        mov     rax, rcx

        ret

asmCode endp

_TEXT   ends
        end

実行結果:a = 2, c = 2

戻り値が単精度浮動小数

戻り値がfloat の例を紹介する。アセンブリ関数は、xmm0レジスターの下位32bitに値を設定すると良い。ここで紹介する例は、引数で渡した2つのfloat値を加算して返す。
C++ソースコード

#include <iostream>
#include <iomanip>

using namespace std;

extern "C" float asmCode(float, float);

int main(void)
{
    float a = 2.31f, b = 3.53f;
    float c = asmCode(a, b);
    cout << fixed << setprecision(2) << a << " + " << b << " = " << c;

    return 0;
}

アセンブリ言語で記述した関数:

_TEXT       segment

; xmm0 = 入力, xmm1 = 入力, xmm0  = 出力

        public  asmCode
        align   16

asmCode proc
        addss xmm0, xmm1

        ret

asmCode endp

_TEXT   ends
        end

実行結果:2.31 + 3.53 = 5.84

戻り値が倍精度浮動小数

戻り値がdouble の例を紹介する。アセンブリ関数は、xmm0レジスターの下位64bitに値を設定すると良い。ここで紹介する例は、引数で渡した2つのdouble値を加算して返す。
C++ソースコード

#include <iostream>
#include <iomanip>

using namespace std;

extern "C" double asmCode(double, double);

int main(void)
{
    double a = 2.31, b = 3.53;
    double c = asmCode(a, b);
    cout << fixed << setprecision(2) << a << " + " << b << " = " << c;

    return 0;
}

アセンブリ言語で記述した関数:

_TEXT   segment

; xmm0 = 入力, xmm1 = 入力, xmm0  = 出力

        public  asmCode
        align   16

asmCode proc
        addsd xmm0, xmm1

        ret

asmCode endp

_TEXT   ends
        end

実行結果:2.31 + 3.53 = 5.84