LoginSignup
4
1

【祝!検証用Console完走】Mind8のランタイムディスパッチャC実装の代替実装をC#で行う(zzHyouji)

Last updated at Posted at 2024-05-15

はじめに

こちらの記事にてMind開発者の@killyさんより情報共有いただいたMind8のCランタイムディスパッチャ起動検証用Consoleでリビルドした中間コードをリビルドし前回記事ではそちらの中間コードを使ってのC#代替実装をリブートしました。本記事はその続きとなります。

前提条件

Windows11 Pro 22H2
VSCode(Visual Studo Code) 1.86.1
Microsoft Visual C++ 2008 Express Edition
Mind Version 8.0.08 for Windows
C# 12
dotnet-sdk-8.0.204-win-x64

VSCodeの拡張機能

C/C++ for Visual Studio Code 1.18.5 Microsoft
C/C++ Extension Pack 1.3.0 Microsoft
.NET Install Tool 2.0.2 Microsoft
Base language support for C# 2.18.16 Microsoft

C/C++のデバッガはCで実装されているMind8kernelの動作をデバッグ実行で探るために使用します。こちらの記事の環境となります。

お題のMind8の中間コードファイル

こちらの記事をご参照ください。Mind8のCランタイムディスパッチャ起動検証用Consoleでリビルドした中間コードのため、お題の「Hello by mind8」のコンソール出力までのmcode処理ステップ数は649から7までに削減されました:joy:

お題のC#ソースコード

Dispatcherクラス(C#関数配列)

C#の関数配列

今回実装するのは前回記事で未実装であったために落ちていたmcode=0x00C1の「$$表示」です。
C版オリジナルではdispword.cに実装されていますので分割クラスファイルのCsFunctionsDispword.csに実装しました。

CsFunctionsDispword.cs
using System.Text;
namespace Mind8Kernel
{
    public partial class Dispatcher
    {
        /*--------------------- 表示系  --------------------------------*/
        private void ZzHyouji()                	/* ;WORD $$表示 */
        {
                /* Mコード=0x00C1 */
            // ULONG	count;
            // UCHAR  *addr;
            // count = POP_C;
            // addr  = POP_A;
            // #define  POP_U                ((ULONG)(*DstackPointer++))
            // #define  POP_A                ((UCHAR *)(*DstackPointer++))
            // #define  POP_C                POP_U
            // printStrinf( addr, count );
            uint count=dtp.PopUl();
            uint index=dtp.PopUl();
            byte[] chars=mp.GetUb(index,count);
            string text = Encoding.GetEncoding("shift_jis").GetString(chars);
            Console.Write(text);   
    }
}

SetupCsFunctions内で.NETCoreでSHIFT-JISエンコードを使うためのおまじない実行を追加しました。

CsFunctions.cs
using System.Text;
using System.Dynamic;
using System.Runtime.InteropServices;

namespace Mind8Kernel
{
    public partial class Dispatcher
    {
        private readonly int maxCountCsFunctions = 1 + 0x0261;
        /// <summary>C#の関数配列を準備する</summary>
        /// <param name="csFunc">C#関数配列の参照</param>
        private void SetupCsFunctions(ref Action[] csFuncs){
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            csFuncs=new Action[maxCountCsFunctions];
        //~略~
        /*--------------------- 文字列定数  ----------------------------*/
            csFuncs[0x00A4]=ZzSliteralOdd;//
            csFuncs[0x00A5]=ZzSliteralEven;//
        /*--------------------- 文字列情報分解・合成  -------------------*/
            csFuncs[0x00BE]=MojiretuJyouhouBunkai;//
            csFuncs[0x00BF]=MojiretuJyouhouGousei;//
        /*--------------------- 表示系  --------------------------------*/
            csFuncs[0x00C1]=ZzHyouji;//
            
        /*--------------------- ならば~つぎに  -------------------------*/
            csFuncs[0x00EC]=zzif;//
            csFuncs[0x00ED]=zzNotif;//
            //~略~
        }

    }
}

今回追加したのはZzHyoujiだけです。

MCodePointerクラス

Mcode領域アクセスクラスに今回のZzHyoujiの実装のため、指定インデックスで指定バイト数(配列数)のbyte配列を返すメソッドを追加しました。

MCodePointer.cs
namespace Mind8Kernel
{
    /// <summary>MCode領域アクセスポインタ</summary>
    public class MCodePointer{
        //~略~
        public byte[] GetUb(uint index,uint count){
            byte[] chars = new byte[count];
            for (uint i = 0; i < count; i++) chars[i] = mcodeArray[index + i];
            return chars;
        }        
        //~略~
    }
}

前回記事で実装しましたmcode=0x00A5のZzSliteralEvenでは、MCode領域の文字列定数の開始インデックスとバイト数がデータスタックに積まれましたので、mcode=0x00C1のZzHyoujiでは、データスタックからMCode領域の開始インデックスとカウントをポップして、その値からMCode領域から文字列文のbyte配列を取得します。

デバッグ実行の結果

現状のディスパッチャのmcode到達状況です。

   1 8019  32793   1024        0        0        0        0        0        0   1024        0        0
   2 002F     47   1024        0        0        0        0        0        0   1023      114        0
   3 00A5    165   1024        0        0        0        0        0        0   1023      114        0
   4 00C1    193   1022       14        0        0        0        0        0   1023      114        0
$$COLD_FORTH
   5 0020     32   1024        0      132       14        0        0        0   1023      114        0
   6 8029  32809   1024        0      132       14        0        0        0   1024        0      114
   7 00A5    165   1024        0      132       14        0        0        0   1023      116        0
   8 00C1    193   1022       14        0        0        0        0        0   1023      116        0
Hello by mind8   9 0020     32   1024        0      628       14        0        0        0   1023      116        0
  10 801A  32794   1024        0      628       14        0        0        0   1024        0      116
  11 002F     47   1024        0      628       14        0        0        0   1023      118        0
  12 00A5    165   1024        0      628       14        0        0        0   1023      118        0
  13 00C1    193   1022       10        0        0        0        0        0   1023      118        0
実行終り
  14 801B  32795   1024        0      180       10        0        0        0   1023      118        0
  15 002F     47   1024        0      180       10        0        0        0   1022      194        0
  16 00A5    165   1024        0      180       10        0        0        0   1022      194        0
  17 00C1    193   1022       18        0        0        0        0        0   1022      194        0
実行終り時の処理
  18 0020     32   1024        0      154       18        0        0        0   1022      194        0
  19 004D     77   1024        0      154       18        0        0        0   1023      118      194
  20 0014     20   1022        0        0        0        0        0        0   1023      118      194
例外がスローされました: 'Mind8Kernel.Dispatcher.ExitModule' (mind8dispatch.dll の中)
プログラム '[11720] mind8dispatch.dll' がコード 0 (0x0) で終了しました。

最後が例外スローされていますが、これはmcode=0014の「プロセス終り0」で意図的にスローさせたアプリケーション例外でした。

CsFunctionsCompword.cs
        //~略~
        private void ProcessOwari(){ /* ;WORD プロセス終り0 */
                /* Mコード=0x0014 */
            // LONG retCode;
            // retCode = POP_L_OF_Q;
            // exit_program( retCode );

            // #define  POP_L_OF_Q           (DROP_F,POP_L)
            dtp.PopUl();
            int retCode =(int)dtp.PopUl();
            throw new ExitModule(retCode);
        }
        //~略~

とりあえず終了動作としては意図したものですので、無事に完走したようでした!:tada::tada:

つづく

生成されたhello.mcoを解釈して、C#側で「Hello by mind8」が出力されるようにするまでの長い道のりですが、とりあえずディスパッチャ起動検証用Consoleでリビルドした中間コードの完走をめざしましたが、意外とあっさり完走しました。:joy::joy:
まだまだ課題山積ですが、気を良くしたのでとりあえずディスパッチャ(の一部)をCからC#に書き換えてみるという野望の現状認識を「幕下」に昇格としてみます。次回以降でも実際に動く範囲をステップバイステップで広げてまいります。

4
1
4

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