はじめに
こちらの記事にてMind開発者の@killyさんより情報共有いただいたMind8の検証用Consoleをベースに一部正規のConsoleのコードを取り込んだ中間コードhellolevel0.mco(Mind中間コードステップ数51)を完走させましたが、ステップ数60のhellolevel1.mcoはまだ完走できずにいます。そこで本記事ではMind8のオリジナルCランタイムディスパッチャのmcodeモニタ機能を改修して、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側検証環境で、お題のステップ数60のhellolevel1.mco中間コードファイルをディスパッチャで処理させた結果が下記です。途中略しています。
SqNo mcode mc(dec) mpoint dtp.point dtp+0 dtp+1 rtp.point rtp+0 rtp+1
1 8019 32793 57 1024 0 0 1024 0 0
2 002F 47 51 1024 0 0 1023 0 0
3 0012 18 2931 1024 0 0 1023 0 0
4 0036 54 2932 1024 0 0 1023 0 0
5 0080 128 2935 1024 0 0 1023 0 0
6 0036 54 2936 1024 0 0 1023 0 0
7 0070 112 2939 1024 0 0 1023 0 0
8 803A 32826 2940 1024 0 0 1023 0 0
9 002F 47 119 1024 0 0 1022 0 13385794
10 80B8 32952 2929 1024 0 0 1022 0 13385794
11 0012 18 2921 1024 0 0 1021 0 13391560
12 0036 54 2922 1024 0 0 1021 0 13391560
13 0071 113 2925 1024 0 0 1021 0 13391560
14 8046 32838 2926 1024 0 0 1021 0 13391560
15 8045 32837 163 1024 0 0 1020 0 13391538
36 00A5 165 2954 1024 0 0 1023 0 0
37 00C1 193 2963 1022 14 13391590 1023 14 0
$$COLD_FORTH
38 0020 32 2964 1024 0 0 1023 0 0
39 80C3 32963 58 1024 0 0 1024 0 0
40 00A5 165 3193 1024 0 0 1023 0 0
41 8083 32899 3202 1022 14 13392068 1023 14 0
42 0012 18 1755 1022 14 13392068 1022 14 13385796
43 004E 78 1756 1022 14 13392068 1022 14 13385796
44 00EC 236 1759 1020 0 0 1022 0 13385796
45 0096 150 1762 1022 14 13392068 1022 14 13385796
46 026D 621 1763 1020 0 1 1022 0 13385796
Hello by mind8
47 0020 32 1764 1024 0 0 1022 0 13385796
48 0020 32 3203 1024 0 0 1023 0 0
49 801A 32794 59 1024 0 0 1024 0 0
50 002F 47 53 1024 0 0 1023 0 0
51 00A5 165 2978 1024 0 0 1023 0 0
52 00C1 193 2985 1022 10 13391638 1023 10 0
実行終り
53 801B 32795 2986 1024 0 0 1023 0 0
54 002F 47 55 1024 0 0 1022 0 13385798
55 00A5 165 2965 1024 0 0 1022 0 13385798
56 00C1 193 2976 1022 18 13391612 1022 18 13385798
実行終り時の処理
57 0020 32 2977 1024 0 0 1022 0 13385798
58 0012 18 2987 1024 0 0 1023 0 0
59 004E 78 2988 1024 0 0 1023 0 0
60 0014 20 2991 1022 0 0 1023 0 0
お題のCソースコード
上記の出力は下記のコードによるものです。オリジナルのwinprintf文によるモニタコードは除去してあります。
ヘッダはテキスト編集しています。(手抜きのためコードからは出力していません。)
今回のお題のため下記コードを見直したところ、rtp+0の出力はリターンスタックの指す値ではなく、データスタックの指す値となっていることに気づきました。これは今回訂正します。
PRIVATE void /* 戻値:無し */
dispatcher( void ) /* 引数:無し */
{
tMcode mcode;
int retcode;
retcode = setjmp( RESTARTENV ); /* ←ディスパッチャ再 */
if ( retcode != 2 ) /* 強制脱出の検査 */
{
/* retcode = 0 or 1 */
int i=0;
for(;;)
{
i++;
//#define FETCH_MCODE (*McodePointer.w++)
mcode = FETCH_MCODE;
winprintf("%4d",i);
winprintf(" %04X",mcode);
winprintf(" %6d",mcode);
winprintf(" %6d",McodePointer.w-McodeBase);
winprintf(" %6d",(DstackPointer-DataStack));
winprintf(" %8d",(*DstackPointer));
winprintf(" %8d",(*(DstackPointer+1)));
winprintf(" %6d",(RstackPointer-RetnStack));
winprintf(" %8d",(*DstackPointer));
winprintf(" %8d\n",(*(RstackPointer+1)));
if ( !(mcode & 0x8000) )
{
/* C関数 */
C_Words_Addr[mcode]();
}
else
{
/* Mind単語 */
PUSH_R( McodePointer.l );//#define PUSH_R(addr) *(--RstackPointer)=(ULONG)(addr)
SET_MCODE_POINTER_BY_WORDNO( mcode & 0x7fff );
//McodePointer.b = (UCHAR *)(WordOffsetTable[wordNo])
}
}
}
}
上記のコードの状態でも、ディスパッチャが処理するmcodeの値とmcodeポインタの値、データスタックポインタの相対値、リターンスタックポインタの相対値はC#代替版と同じように出力できています。(mcodeポインタの値はC#版はC版の2倍となっています。C#は1バイトづつのインデックス値のため)
お題のCソースコード(改定版)
Cオリジナル版の場合、データスタックやリターンスタックにアドレス値が乗る場合がありますが、C#版はスタック用配列のインデックス値であるため、値の大きさがかなり異なった出力となります。本記事ではCオリジナル版のアドレス値を操作して、C#版のスタック用配列のインデックス値と同等の値に変換して出力してみます。
Cオリジナル版の場合、スタックはアドレスの高位から消費していく
C#代替版の場合、スタック配列はインデックス0から消費していく。ただし、スタックポインタは最大値から減算されるように実装されています。
下記のコードはリターンスタックポインタにはデータスタックのアドレスが置かれることが多いという仮説の上に実装されています。
winprintf("%4d",i);
winprintf(" %04X",mcode);
winprintf(" %6d",mcode);
winprintf(" %6d",(McodePointer.w-McodeBase)*2);
winprintf(" %6d",(DstackPointer-DataStack));
winprintf(" %8d",(*DstackPointer));
winprintf(" %8d",(*(DstackPointer+1)));
winprintf(" %6d",(RstackPointer-RetnStack));
if((*RstackPointer)==0){
winprintf(" %8d",(*RstackPointer));
}else{
winprintf(" %8d",(DataStack-(unsigned int *)(*RstackPointer)));
}
if((*RstackPointer+1)==0){
winprintf(" %8d",(*RstackPointer+1));
}else{
winprintf(" %8d\n",(DataStack-(unsigned int *)(*(RstackPointer+1))));
}
お題のMind8の中間コード実行リスト(上記モニタ改定版)
上記モニタ改定版のC側検証環境で、お題のステップ数60のhellolevel1.mco中間コードファイルをディスパッチャで処理させた結果が下記です。途中までとしています。
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 3025768
2 002F 47 102 1024 0 0 1023 6999 3025768
3 0012 18 5862 1024 0 0 1023 6999 3025768
4 0036 54 5864 1024 0 0 1023 6999 3025768
5 0080 128 5870 1024 0 0 1023 6999 3025768
6 0036 54 5872 1024 0 0 1023 6999 3025768
7 0070 112 5878 1024 0 0 1023 6999 3025768
8 803A 32826 5880 1024 0 0 1023 6999 3025768
9 002F 47 238 1024 0 0 1022 5558 6999
10 80B8 32952 5858 1024 0 0 1022 5558 6999
11 0012 18 5842 1024 0 0 1021 5563 5558
12 0036 54 5844 1024 0 0 1021 5563 5558
13 0071 113 5850 1024 0 0 1021 5563 5558
14 8046 32838 5852 1024 0 0 1021 5563 5558
15 8045 32837 326 1024 0 0 1020 5565 5563
16 0012 18 314 1024 0 0 1019 6946 5565
17 0036 54 316 1024 0 0 1019 6946 5565
18 0074 116 322 1024 0 0 1019 6946 5565
19 0020 32 324 1024 0 0 1019 6946 5565
20 0020 32 328 1024 0 0 1020 5565 5563
21 80A3 32931 5854 1024 0 0 1021 5563 5558
22 0036 54 3884 1024 0 0 1020 5564 5563
23 0012 18 3890 1024 0 0 1020 5564 5563
24 016E 366 3892 1024 0 0 1020 5564 5563
25 0020 32 3898 1024 0 0 1020 5564 5563
26 0020 32 5856 1024 0 0 1021 5563 5558
27 0020 32 5860 1024 0 0 1022 5558 6999
28 00A5 165 5882 1024 0 0 1023 6999 3025768
29 803C 32828 5906 1022 20 12080844 1023 6999 3025768
30 002F 47 246 1022 20 12080844 1022 5551 6999
31 001A 26 5802 1022 20 12080844 1022 5551 6999
32 006E 110 5804 1022 20 12080844 1020 5564 5563
33 0015 21 5808 1024 0 0 1020 3025763 5557
34 00ED 237 5810 1022 0 1 1020 3025763 5557
35 0022 34 5830 1024 0 0 1020 3025763 5557
36 00A5 165 5908 1024 0 0 1023 6999 3025768
37 00C1 193 5926 1022 14 12080870 1023 6999 3025768
$$COLD_FORTH
38 0020 32 5928 1024 0 0 1023 6999 3025768
39 80C3 32963 116 1024 0 0 1024 0 3025768
お題のMind8の中間コード実行リスト(C#代替版)
下記はC#代替版でお題のステップ数60のhellolevel1.mco中間コードファイルを処理させた結果です。ほぼ正常の途中までとしています。
39ステップ目がオリジナルとmcodeの値が異なってしまっていますが、それ以外では各ステップのmcodeの値、mcodeポインタの値、データスタックポインタの値、データスタックポインタの指す値、リターンスタックポインタの値は合致していることがわかります。
いまのところ合致が確認できないのは、データスタックポインタのオフセット1の指す値と、リターンスタックポインタのオフセット0,1の指す値ということになります。
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 5884
34 00ED 237 5810 1022 0 0 1020 20 5884
35 0022 34 5830 1024 0 1 1020 20 5884
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
つづく
生成されたhello.mcoを解釈して、C#側で「Hello by mind8」が出力されるようにするまでの長い道のりですが、いそがば回れということでオリジナルのCディスパッチャの挙動をもう少しうまくモニタできるようにしてみます。