はじめに
こちらの記事にてMind開発者の@killyさんより情報共有いただいたMind8のCランタイムディスパッチャ起動検証用Consoleをベースに一部正規のConsoleのコードを取り込んだ中間コードhellolevel1.mcoをリビルドしましたが、さらにその記事のコメントでkillyさんより別の構成のソースのご提案もいただきましたので、そのバージョンをhellolevel0.mcoとしました。本記事ではこの2つのバージョンの中間コードを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の中間コードファイル
こちらの記事とコメントをご参照ください。また、こちらの記事に正規版のC版オリジナルがディスパッチしたリストを確認しています。お題の「Hello by mind8」のコンソール出力を行って終了するまで、正規版は694(同一コード含む)のmcodeを処理します。それに対して起動検証用Console版が20(これはC#版も完走)、それをベースに少し正規版のコードを追加したlevel1が60、killyさんご提案(内容を私が解釈して)追加したlevel0が84です。
とりあえずどんな状況か
level1、level0に対して、それぞれ現状は下記のとおりです。
SqNo mcode mc(dec) mpoint dtp.point dtp+0 dtp+1 rtp.point rtp+0 rtp+1
1 8019 32793 114 1024 0 0 1024 0 0
2 002F 47 102 1024 0 0 1023 114 0
3 0012 18 5862 1024 0 0 1023 114 0
4 0036 54 5864 1024 0 0 1023 114 0
5 0080 128 5870 1024 0 0 1023 114 0
6 0036 54 5872 1024 0 0 1023 114 0
7 0070 112 5878 1024 0 0 1023 114 0
8 803A 32826 5880 1024 0 0 1023 114 0
9 002F 47 238 1024 0 0 1022 5880 0
10 80B8 32952 5858 1024 0 0 1022 5880 0
11 0012 18 5842 1024 0 0 1021 5858 0
12 0036 54 5844 1024 0 0 1021 5858 0
13 0071 113 5850 1024 0 0 1021 5858 0
14 8046 32838 5852 1024 0 0 1021 5858 0
15 8045 32837 326 1024 0 0 1020 5852 0
16 0012 18 314 1024 0 0 1019 326 0
17 0036 54 316 1024 0 0 1019 326 0
18 0074 116 322 1024 0 0 1019 326 0
19 0020 32 324 1024 0 0 1019 326 0
20 0020 32 328 1024 0 0 1020 5852 326
21 80A3 32931 5854 1024 0 0 1021 5858 5852
22 0036 54 3884 1024 0 0 1020 5854 326
23 0012 18 3890 1024 0 0 1020 5854 326
24 016E 366 3892 1024 0 0 1020 5854 326
25 0020 32 3898 1024 0 0 1020 5854 326
26 0020 32 5856 1024 0 0 1021 5858 5854
27 0020 32 5860 1024 0 0 1022 5880 5858
28 00A5 165 5882 1024 0 0 1023 114 5880
29 803C 32828 5906 1022 20 0 1023 114 5880
30 002F 47 246 1022 20 0 1022 5906 5858
31 001A 26 5802 1022 20 0 1022 5906 5858
32 006E 110 5804 1022 20 0 1020 0 114
33 0015 21 5808 1024 0 5884 1020 20 252
34 00ED 237 5810 1022 0 0 1020 20 252
35 0022 34 5830 1024 0 1 1020 20 252
36 00A5 165 5908 1024 0 1 1023 5858 5854
37 00C1 193 5926 1022 14 0 1023 5858 5854
$$COLD_FORTH
38 0020 32 5928 1024 0 5910 1023 5858 5854
39 0020 32 5860 1024 0 5910 1024 5906 5858
40 00A5 165 5908 1024 0 5910 1025 252 5906
41 00C1 193 5926 1022 14 0 1025 252 5906
$$COLD_FORTH
42 0020 32 5928 1024 0 5910 1025 252 5906
43 002F 47 254 1024 0 5910 1026 20 252
44 0095 149 258 1024 0 5910 1026 20 252
45 0020 32 260 1022 0 0 1026 20 252
例外がスローされました: 'System.IndexOutOfRangeException' (mind8dispatch.dll の中)
SqNo mcode mc(dec) mpoint dtp.point dtp+0 dtp+1 rtp.point rtp+0 rtp+1
1 8019 32793 114 1024 0 0 1024 0 0
2 002F 47 102 1024 0 0 1023 114 0
3 0036 54 8036 1024 0 0 1023 114 0
4 0080 128 8042 1024 0 0 1023 114 0
5 0036 54 8044 1024 0 0 1023 114 0
6 0070 112 8050 1024 0 0 1023 114 0
7 803A 32826 8052 1024 0 0 1023 114 0
8 002F 47 238 1024 0 0 1022 8052 0
9 80E6 32998 8032 1024 0 0 1022 8052 0
10 808F 32911 8026 1024 0 0 1021 8032 0
11 0097 151 3626 1024 0 0 1020 8026 0
12 0065 101 3628 1022 0 0 1020 8026 0
13 0020 32 3634 1024 0 2 1020 8026 0
14 80C1 32961 8028 1024 0 2 1021 8032 8026
15 0261 609 6430 1024 0 2 1020 8028 0
16 8053 32851 6432 1022 0 0 1020 8028 0
17 8052 32850 1042 1022 0 0 1019 6432 0
18 001A 26 950 1022 0 0 1018 1042 0
19 006B 107 952 1022 0 0 1016 8028 6432
20 0055 85 956 1024 0 2151888624 1016 8028 6432
21 008F 143 960 1022 0 0 1016 8028 6432
22 00ED 237 962 1022 0 0 1016 8028 6432
23 0055 85 978 1024 0 2151888624 1016 8028 6432
24 0012 18 982 1022 0 0 1016 8028 6432
25 00A2 162 984 1022 0 0 1016 8028 6432
26 00BF 191 990 1020 0 0 1016 8028 6432
27 0095 149 992 1022 65535 65535 1016 8028 6432
28 01D7 471 994 1020 0 0 1016 8028 6432
29 006B 107 996 1022 0 0 1016 8028 6432
30 0055 85 1000 1024 0 1 1016 8028 6432
31 00ED 237 1004 1022 0 0 1016 8028 6432
32 0055 85 1018 1024 0 1 1016 8028 6432
33 0055 85 1022 1022 0 0 1016 8028 6432
34 0103 259 1026 1020 0 0 1016 8028 6432
35 00BF 191 1028 1020 4294967295 0 1016 8028 6432
36 0055 85 1030 1022 1 1 1016 8028 6432
37 0055 85 1034 1020 0 0 1016 8028 6432
38 0107 263 1038 1018 0 0 1016 8028 6432
39 0022 34 1040 1020 2 1 1016 8028 6432
40 0122 290 1044 1020 2 1 1019 0 0
41 0020 32 1046 1022 0 0 1019 0 0
42 0020 32 2 1022 0 0 1020 1042 0
43 0122 290 1044 1022 0 0 1021 6432 1042
44 0020 32 1046 1024 0 0 1021 6432 1042
45 0012 18 6434 1024 0 0 1022 8028 6432
46 0165 357 6436 1024 0 0 1022 8028 6432
例外がスローされました: 'System.NullReferenceException' (mind8dispatch.dll の中)
プログラム '[5472] mind8dispatch.dll' がコード -1 (0xffffffff) で終了しました。
copy hellolevel0.mco C:\developments\vscode\mind8\kernel\mindexec.mco
level1は「$$COLD_FORTH」のコンソール出力まで正常進行しましたが、その後の処理でmcodeポインタのジャンプ先が不適切で、「$$COLD_FORTH」のコンソール出力を意図せず繰り返した後、byte配列のインデックス超過で落ちています。
level0は46ステップ目のmcode=0165が未実装のため関数配列のnull参照例外で落ちています。
お題のC#ソースコード
前回記事から修正・追加した関数は下記のとおりです。
Dispatcherクラス(C#関数配列)
C#の関数配列
/*--------------------- スタックポインタのアクセス --------------*/
private void StackKensa0(){/* ;WORD スタック検査0 */
/* Mコード=0x0015 */
// if ( DstackPointer == DataStackBase[RestartEnvCount] )
// {
// /* OK */
// PUSH_Q( 1, 0 );
// }
// else
// {
// /* NG */
// resetDataStackPointer(); /* in dispatch.c */
// PUSH_Q( 0, 0 );
// }
if(dtp.IsCurrentStackPointerInit()){
dtp.PushUl(1);
dtp.PushUl(0);
}else{
dtp.ResetStackPointer();
dtp.PushUl(0);
dtp.PushUl(0);
}
}
このデータスタックのポインタが初期値に等しいかの判定文IsCurrentStackPointerInit()をスタックポインタクラスに追加しています。
StackPointerクラス
namespace Mind8Kernel
{
/// <summary>スタックポインタ</summary>
public class StackPointer{
private readonly uint stackSize=4;
private uint stackMaxSize;
private uint stackIndex;
private uint stackPointer;
public byte[] dataArray =[];
public void SetupStackArray(uint size){
stackMaxSize=size;
dataArray =new byte[stackMaxSize];
stackPointer=stackMaxSize/stackSize;//stackPointerは1024が初期値
stackIndex=0;//stackIndexは0が初期値
}
public void ResetStackPointer(){
stackPointer=stackMaxSize/stackSize;
stackIndex=0;//byte配列インデックス=アドレスポインタ変数の値*4
}
//~略~
public bool IsCurrentStackPointerInit(){
return (stackIndex==0);
}
//~略~
}
}
つづく
生成されたhello.mcoを解釈して、C#側で「Hello by mind8」が出力されるようにするまでの長い道のりですが、(いったんショートカットバイパスでこの文字列定数のコンソール出力自体は動作していますが、正規版の処理内容に近づくには)まだまだ課題山積です。次回以降でもこのソースコードを肉付けして実際に動く範囲をステップバイステップで広げてまいります。