[USR] コマンド

Memory上に用意された(Load済みの)機械語、または実行SubProgramの関数を呼び出し実行します。
CALLと違って、値を返します。機械語ルーチンを使った関数の機能になります。
文法 USR[<番号>][(<引数>)]
文例  I=USR3(J)
   K=USR5(ARG1$)
   L#=USR7((3.141592653)#)
   M#=USR1((3.14/159.2653+8.91)#)
   N#=USR3((A%/B!+C#)#)
呼び出したい機械語関数はあらかじめメモリ上に用意しておき、またDEF USERにより、
その実行開始アドレスを設定しておかねばなりません。
機械語関数を用意するには、[POKE][BLOAD] 命令を用いることができます。
 <番号>には、DEF USERにより定義された番号を 0から 9までの値で指定します。
省略された場合には 0と解釈されます。
 <引数>には、BASICから機械語関数に渡す変数、定数、式を指定します。
CALL文とは異なり、引数は値渡しです。引数の数値を渡します。
機械語関数で変数や配列を操作するときは、変数のアドレスを引数にします。
引数が必要でない場合でも、ダミーの引数を与えねばなりません。
引数の型は整数、単精度実数、倍精度実数、文字型のデータですが、
USRが返す値は引数と同じでなければなりません。
 引数が単一の変数の場合、その変数の型で、機械語に渡します。
 引数が定数、数式の場合には引数全体を()に囲んで、末尾に#、!、%を付けてください。
省略時は単精度実数(!)と見なします。
USRでの引数の取り出し、返す値の格納の方法は次のとうりです。
与える引数の型は、CLにセットして、機械語に入ります。
与える引数は浮動小数点アキュムレーター(FAC)に下記のとうりに書き込み、
機械語サブプログラムに渡します。FACは内部に8Byteの領域として確保します。

 

CL

EBX

 

.0

.1

.2

.3

.4

.5

.6

.7

文字型

3

.0番地

 

長さ

 

 

 

整数型

2

.4番地

 

 

 

 

 

 

 

単精度

4

.4番地

 

 

 

 

 

倍精度

8

.0番地

 





@ 文字型の場合、 レジスターCLに 3をセット、レジスターEBXにFACの開始アドレス、オフセット0
のアドレスをセットし、FACのオフセット 0の 1Byteに文字列の長さを、オフセット 4からの 4Byteに
文字列の開始番地をセットします。

A 整数型の場合、 レジスターCLに 2をセット、レジスターEBXにFACのオフセット 4のアドレスを
セットし、FACのオフセット 4からの 2Byteに整数の値(整数)をセットします。

B 単精度型の場合、 レジスターCLに 4をセット、レジスターEBXにFACのオフセット 4のアドレスを
セットし、FACのオフセット 4からの 4Byteに単精度(浮動小数点)の値をセットします。

C 倍精度型の場合、 レジスターCLに 8をセット、レジスターEBXにFACの開始アドレス、オフセット0
のアドレスをセットし、FACのオフセット 0からの 8Byteに倍精度(浮動小数点)の値をセットします。

尚、浮動小数点演算は、VisualC++でのCプログラムを作成の場合、8087プロセッサーの関係でプロ
グラム作成上注意すべき点があります。下に示す、Sample46、Sample46_2とCプログラムの説明を見
て下さい。
 USRが実行されると、直前に実行された[DEF_SEG] で指定されたセグメン
トベースに、DEF USRにより定義された機械語関数の実行開始アドレス(相対アドレス値)が加えられ
た番地に実行が移されます。USRによって呼び出された機械語関数は、機械語のIRET命令により
BASICに制御をもどすことができます。
 なお、機械語サブプログラムを呼び出す方法としては、USRの他に[CALL] 命令が
用意されています。CALLでは複数の引数を機械語プログラムに受け渡すことができます。

[参考]浮動小数点演算のプログラミングについて。
Sample46は単精度、倍精度の2とうりに対して、直径を与えて円の面積を計算、円の面積を与えて直
径を計算、度で角度を与えてSINを計算して表示するSampleです。いずれも8087プロセッサーを使いますが、
VisualC++でのCプログラム例を次に示します。

円の面積を与えて直径を計算するプログラム例。
/************************* Start of MAIN-C.C *************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include <math.h>
#include "main.h"
#include <stdarg.h>
#include <direct.h>
#include <io.h>
#include <conio.h>
#include <ctype.h>
#include <process.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#ifdef __STDC__

#else

#endif


void main()
{
//////////////This is type=4,single variable////////////

float pai,*ppai,*pf0;
float $fc1,*pfc1;

__asm {
PUSH ECX;
CMP CL,4;
JNZ last;
MOV pf0,EBX;
}
pai=(float)3.14159;
$fc1=(float)4.0;
ppai=&pai;
pfc1=&$fc1;
__asm {//Here step is link treatment with 8087 processor
MOV EAX,ppai;
MOV ppai,EAX;
MOV EAX,pfc1;
MOV pfc1,EAX;
}

*pf0= (float)(*pf0 * *pfc1 / *ppai);
*pf0= (float) sqrt(*pf0);
last:
__asm {
POP ECX;
}

return ;
}
/************************** End of MAIN-C.C **************************/



角度(Degree)を与えて、SINを計算するプログラム例。
/************************* Start of MAIN-C.C *************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include <math.h>
#include "main.h"
#include <stdarg.h>
#include <direct.h>
#include <io.h>
#include <conio.h>
#include <ctype.h>
#include <process.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#ifdef __STDC__


#else


#endif

void main()
{
//////////////This is type=8,double variable////////////

double pai,*ppai,*pd0;
double dc180,*pdc180;

__asm {
PUSH ECX;
CMP CL,8;
JNZ last;
}
pai=3.141592653;
dc180=180;
ppai=&pai;
pdc180=&dc180;

__asm {//Relations 8087 Processor
MOV pd0,EBX;
MOV EAX,ppai;
MOV ppai,EAX;
MOV EAX,pdc180;
MOV pdc180,EAX;
}

*pd0= (*pd0 * pai )/ dc180;
*pd0= sin(*pd0);
last:
__asm {
POP ECX;
}

return ;
}
/************************** End of MAIN-C.C **************************/

8087Processorは普通は自動作動していますが、このように、親プロセスからの呼び出しである子プロ
セスの場合、子プロセスで定義した浮動小数点定数は8087が認定せず、0と扱われます。
__asm {//Here step is link treatment with 8087 processor
MOV EAX,ppai;
MOV ppai,EAX;
MOV EAX,pfc1;
MOV pfc1,EAX;
}
このため、子プログラム内で、ASMレベルに一度下りてこれらの定数のPointerを通しておけば、8087
が認定します。8086CPU内の操作だけで、8087を必要とする浮動小数点演算以外は、このような操作
は無用です。
文字型、整数型の例は、Sample46_2を参照してください。ASM、VisualC++でのCプログラム例も示して
あります。