● アセンブラからの呼び出し



例1.「加減算」 の例1 をインラインアセンブラで作る

#include <stdio.h>
#include "fixedX.h"

#define FIXED_BIT           128
#define FIXED_SIZE          (FIXED_BIT / 8)

void    main(void )
{
    FIXEDVAL        a[FIXED_SIZE],b[FIXED_SIZE];
    char            *pszA = "1156262128751139";
    char            *pszB = "6643456757654475";
    char            *pformat = "%s\n";
    char            buf[39+1];

    _asm{
        lea         edi,a
        lea         esi,b

        ;; a に値をセット
        push        dword ptr pszA              ; 変換対象の文字列
        push        dword ptr FIXED_SIZE        ; 変数 a の数値幅
        push        edi                         ; 変数 a のアドレス
        call        dword ptr fixed_atoui       ; __stdcall fixed_atoui

        ;; b に値をセット
        push        dword ptr pszB              ; 変換対象の文字列
        push        dword ptr FIXED_SIZE        ; 変数 b の数値幅
        push        esi                         ; 変数 b のアドレス
        call        dword ptr fixed_atoui       ; __stdcall fixed_atoui

        ;; 加算
        push        dword ptr FIXED_SIZE        ; 変数の数値幅
        push        esi                         ; 加数 b
        push        edi                         ; 被加数 a
        call        dword ptr fixed_add         ; __stdcall fixed_add

        ;; 結果を文字列に変換
        lea         eax,buf
        push        eax                         ; 文字列を受け取るバッファのアドレス
        push        dword ptr FIXED_SIZE        ; 変数 a の数値幅
        push        edi                         ; 変数 a のアドレス

        call        dword ptr fixed_num2str10   ; __stdcall fixed_num2str10
                                                ; void : この時点で eax の内容は変わらず

        ;; 結果表示
        push        eax                         ; 文字列を格納しているバッファのアドレス
        push        dword ptr pformat           ; 表示フォーマット
        call        printf                      ; printf
        add         esp,8                       ; __cdecl
    }
}


例2.「double値の変換」にある「FIXEDVAL型 → double型」の例1 を MASM で作る

MASM の場合はインラインアセンブラより呼び出し手続きが簡単ですが、
当然の事ながら、対象関数を全てアセンブラで作る必要があります。

    .486
    .model flat,stdcall
    option casemap : none

fixed_neg proto stdcall :dword,:dword
fixed_bsr proto stdcall :dword,:dword
fixed_rshift proto stdcall :dword,:dword,:dword

    .code

BIT_SIGN        equ         80000000h       ; 符号ビット
MANTCNT         equ         52              ; 仮数部ビットサイズ

;; double __stdcall     to_double(PFIXEDVAL pval,int len);

to_double proc public uses eax ecx edx esi pval:dword,len:dword
    mov         esi,pval                    ; esi ... pval
    mov         ecx,len
    mov         edx,[esi+ecx-4]
    and         edx,BIT_SIGN                ; 符号チェック
    jz          @f
    invoke      fixed_neg,esi,ecx           ; 負なら絶対値に変換
@@:
    invoke      fixed_bsr,esi,ecx           ; 最上位ビットの検索
    test        eax,eax
    jge         @f
    fldz                                    ; 値自体がゼロなら 0.0 で終了
    ret

@@:
    sub         eax,MANTCNT-1               ; 数値の幅 > 52bit ?
    jg          @f
    xor         eax,eax                     ; 52bit以下なら全部入る
    jmp         next_step
@@:
    invoke      fixed_rshift,esi,eax,ecx    ; 上位を残し、下位側を切り捨てる

next_step:
    ;; ここでは標準ライブラリの ldexp を使用しません。
    push        eax
    fild        dword ptr [esp]
    lea         esp,[esp+4]
    fild        qword ptr [esi]
    fscale                                  ; [esi] * 2^eax → st(0)
    fstp        st(1)
    test        edx,edx
    jz          @f
    fchs                                    ; 負にする
@@:
    ret
to_double       endp
end