LoginSignup
4
1

Mindコンパイラによる変数操作の様子

Last updated at Posted at 2024-03-12

 @mylifewithviolinさんが独自の固定小数操作をされようとしているようなので、ご参考までに変数アクセスとコンパイラの処理について解説させてください。

 たとえば、

   変数を クリア

というソースがあった時のコンパイラの動きですが、一般的な処理単語のように

   ”クリア”という処理単語を呼ぶ

・・わけではなくて、もし少し複雑な処理をおこないます。
 コンパイラはクリア対象となる変数の型を見て、適切なカーネル内のC記述処理単語を呼び出します。上記の場合(32bit整数のクリア)ですと、次のようなC関数が呼ばれます。

PRIVATE void
    zzClearDvar( void )         /* ;WORD $$CLR_DVAR */
{
        /* (. → .) */

        /*-[変数]----------------------*/
        /*   +0(D): value              */       /* ←[AccessPointer] */
        /*-----------------------------*/

        *AccessPointer.l = 0;
}

この関数が呼ばれる直前に、カーネル内の大域変数 "AccessPointer" に変数のアドレスがセットされています。zzClearDvar() は「AccessPointerが指すところの32bit変数」をクリアします。

 変数が倍精度整数の場合は zzClearLvar() が呼ばれます。

 このようなコンパイラによる特殊なコード生成は以下のソース記述の場合に行われます。

 ・変数参照
 ・(スタックのデータを)変数に入れる
 ・(リテラルを)変数に入れる
 ・変数をクリア
 ・変数を一つを増加
 ・変数を一つ減少
 ・変数をセット
 ・変数を増加
 ・変数を減少

 現状がどうなっているかをご説明します(Mind8での場合です)。
 kernel\compword.c に以下の関数定義があります。

compword.c
 (変数参照)
    zzPushBvar( void )          /* ;WORD $$PUSH_BVAR */
    zzPushWvar( void )          /* ;WORD $$PUSH_WVAR */
    zzPushDvar( void )          /* ;WORD $$PUSH_DVAR */
    zzPushLvar( void )          /* ;WORD $$PUSH_LVAR */

 (スタックから変数に入れる)
    zzPopBvar( void )           /* ;WORD $$POP_BVAR */
    zzPopWvar( void )           /* ;WORD $$POP_WVAR */
    zzPopDvar( void )           /* ;WORD $$POP_DVAR */
    zzPopLvar( void )           /* ;WORD $$POP_LVAR */

 (リテラルを変数に入れる)
    zzWriteBvar( void )         /* ;WORD $$WRITE_BVAR */
    zzWriteWvar( void )         /* ;WORD $$WRITE_WVAR */
    zzWriteDvar( void )         /* ;WORD $$WRITE_DVAR */
    zzWriteLvar( void )         /* ;WORD $$WRITE_LVAR */

 (リテラルを変数に入れる・局所変数)
    zzWriteBvarLocal( void )    /* ;WORD $$WRITE_BVAR_LOCAL */
    zzWriteWvarLocal( void )    /* ;WORD $$WRITE_WVAR_LOCAL */
    zzWriteDvarLocal( void )    /* ;WORD $$WRITE_DVAR_LOCAL */
    zzWriteLvarLocal( void )    /* ;WORD $$WRITE_LVAR_LOCAL */

 (変数をクリア)
    zzClearBvar( void )         /* ;WORD $$CLR_BVAR */
    zzClearWvar( void )         /* ;WORD $$CLR_WVAR */
    zzClearDvar( void )         /* ;WORD $$CLR_DVAR */
    zzClearLvar( void )         /* ;WORD $$CLR_LVAR */

 (変数を一つを増加)
    zzIncBvar( void )           /* ;WORD $$INC_BVAR */
    zzIncWvar( void )           /* ;WORD $$INC_WVAR */
    zzIncDvar( void )           /* ;WORD $$INC_DVAR */
    zzIncLvar( void )           /* ;WORD $$INC_LVAR */

 (変数を一つ減少)
    zzDecBvar( void )           /* ;WORD $$DEC_BVAR */
    zzDecWvar( void )           /* ;WORD $$DEC_WVAR */
    zzDecDvar( void )           /* ;WORD $$DEC_DVAR */
    zzDecLvar( void )           /* ;WORD $$DEC_LVAR */

 (変数をセット)
    zzSetBvar( void )           /* ;WORD $$SET_BVAR */
    zzSetWvar( void )           /* ;WORD $$SET_WVAR */
    zzSetDvar( void )           /* ;WORD $$SET_DVAR */
    zzSetLvar( void )           /* ;WORD $$SET_LVAR */

 (変数を増加)
    zzAddBvar( void )           /* ;WORD $$ADD_BVAR */
    zzAddWvar( void )           /* ;WORD $$ADD_WVAR */
    zzAddDvar( void )           /* ;WORD $$ADD_DVAR */
    zzAddLvar( void )           /* ;WORD $$ADD_LVAR */

 (変数を減少)
    zzSubBvar( void )           /* ;WORD $$SUB_BVAR */
    zzSubWvar( void )           /* ;WORD $$SUB_WVAR */
    zzSubDvar( void )           /* ;WORD $$SUB_DVAR */
    zzSubLvar( void )           /* ;WORD $$SUB_LVAR */

 上記のように、各グループごとに、8bit整数、16bit整数、32bit整数、64bit整数の順にきれいに並んでいます。順番はこの通りである必要があります。
 したがって、倍精度変数の操作をカスタマイズされたい場合は、上記で $$xxx_LVAR いう関数を修正すれば良いことになります。

 独自フォーマットの64bitデータを扱われたいと仮定しますと、上記のグループ群のうち、参照、代入、クリアはこのままて良い可能性もあります。特にクリアについては変数に0を代入すれば良いだけなのでたぶんフォーマットは関係ないと思われます(ゼロを表す特殊な値というものが無ければ)。

 そうすると、「増加」、「減少」系の処理と「セット」ぐらいをおこなえば良いのかも知れません。
 以上の特殊な変数操作が面倒なところで、それ以外は普通の処理単語として実現すれば良いかと思います。

4
1
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1