はじめに
前回の記事にて、過日Mind開発者の@killyさんより情報共有いただいたMind8の検証用Consoleをベースにしたhellolevel1.mcoの中間コードのC#代替ディスパッチャとCオリジナルディスパッチャの処理結果の違いを探るべく、Cオリジナルディスパッチャのmcodeモニタ機能を改修して、C#代替ディスパッチャと同等となるようにスタック値をコンバートしてみましたが、スタック上のアドレス値のオフセット換算はうまくいっておりませんでした。そこで今回はC#ディスパッチャと同じインデックス値となるオフセット値を逆算して、そのオフセット値をEXCEL上でアドレス値から減算して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#代替版)
下記はC#代替版でお題のステップ数60のhellolevel1.mco中間コードファイルを処理させた結果です。39ステップ目のmcodeの値が、Cオリジナルでは80C3のところ、C#代替版では002Aとなってしまっています。これはリターンスタックの値が手前のステップでオリジナルと異なってしまっていることに起因することがわかっていて、直前の処理のmcode対応C#代替関数に問題があるのではないことはわかっています。この記事のお題は、この次のmcodeを指し示すリターンスタックの値がどこで狂ったかということを特定することにあります。
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
お題のCソースコード
前回の記事ではオリジナル版のアドレス値を操作して、C#版のスタック用配列のインデックス値と同等の値に変換して出力してみましたが、うまくいきませんでしたの本記事では素直な出力にいったん戻します。
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])
}
}
}
}
お題の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 1
2 002F 47 102 1024 0 0 1023 10305602 10305603
3 0012 18 5862 1024 0 0 1023 10305602 10305603
4 0036 54 5864 1024 0 0 1023 10305602 10305603
5 0080 128 5870 1024 0 0 1023 10305602 10305603
6 0036 54 5872 1024 0 0 1023 10305602 10305603
7 0070 112 5878 1024 0 0 1023 10305602 10305603
8 803A 32826 5880 1024 0 0 1023 10305602 10305603
9 002F 47 238 1024 0 0 1022 10311368 10311369
10 80B8 32952 5858 1024 0 0 1022 10311368 10311369
11 0012 18 5842 1024 0 0 1021 10311346 10311347
12 0036 54 5844 1024 0 0 1021 10311346 10311347
13 0071 113 5850 1024 0 0 1021 10311346 10311347
14 8046 32838 5852 1024 0 0 1021 10311346 10311347
15 8045 32837 326 1024 0 0 1020 10311340 10311341
16 0012 18 314 1024 0 0 1019 10305814 10305815
17 0036 54 316 1024 0 0 1019 10305814 10305815
18 0074 116 322 1024 0 0 1019 10305814 10305815
19 0020 32 324 1024 0 0 1019 10305814 10305815
20 0020 32 328 1024 0 0 1020 10311340 10311341
21 80A3 32931 5854 1024 0 0 1021 10311346 10311347
22 0036 54 3884 1024 0 0 1020 10311342 10311343
23 0012 18 3890 1024 0 0 1020 10311342 10311343
24 016E 366 3892 1024 0 0 1020 10311342 10311343
25 0020 32 3898 1024 0 0 1020 10311342 10311343
26 0020 32 5856 1024 0 0 1021 10311346 10311347
27 0020 32 5860 1024 0 0 1022 10311368 10311369
28 00A5 165 5882 1024 0 0 1023 10305602 10305603
29 803C 32828 5906 1022 20 10311372 1023 10305602 10305603
30 002F 47 246 1022 20 10311372 1022 10311394 10311395
31 001A 26 5802 1022 20 10311372 1022 10311394 10311395
32 006E 110 5804 1022 20 10311372 1020 10311342 10311343
33 0015 21 5808 1024 0 0 1020 20 21
34 00ED 237 5810 1022 0 1 1020 20 21
35 0022 34 5830 1024 0 0 1020 20 21
36 00A5 165 5908 1024 0 0 1023 10305602 10305603
37 00C1 193 5926 1022 14 10311398 1023 10305602 10305603
$$COLD_FORTH
38 0020 32 5928 1024 0 0 1023 10305602 10305603
39 80C3 32963 116 1024 0 0 1024 0 1
40 00A5 165 6386 1024 0 0 1023 10305604 10305605
41 8083 32899 6404 1022 14 10311876 1023 10305604 10305605
42 0012 18 3510 1022 14 10311876 1022 10311892 10311893
43 004E 78 3512 1022 14 10311876 1022 10311892 10311893
44 00EC 236 3518 1020 0 0 1022 10311892 10311893
45 0096 150 3524 1022 14 10311876 1022 10311892 10311893
46 026D 621 3526 1020 0 1 1022 10311892 10311893
Hello by mind8
47 0020 32 3528 1024 0 0 1022 10311892 10311893
48 0020 32 6406 1024 0 0 1023 10305604 10305605
49 801A 32794 118 1024 0 0 1024 0 1
50 002F 47 106 1024 0 0 1023 10305606 10305607
51 00A5 165 5956 1024 0 0 1023 10305606 10305607
52 00C1 193 5970 1022 10 10311446 1023 10305606 10305607
実行終り
53 801B 32795 5972 1024 0 0 1023 10305606 10305607
54 002F 47 110 1024 0 0 1022 10311460 10311461
55 00A5 165 5930 1024 0 0 1022 10311460 10311461
56 00C1 193 5952 1022 18 10311420 1022 10311460 10311461
実行終り時の処理
57 0020 32 5954 1024 0 0 1022 10311460 10311461
58 0012 18 5974 1024 0 0 1023 10305606 10305607
59 004E 78 5976 1024 0 0 1023 10305606 10305607
60 0014 20 5982 1022 0 0 1023 10305606 10305607
お題のMind8の中間コード実行リスト(上記Cオリジナル版)のリターンスタック値をC#代替互換にEXCELで加工する
OSがアロケートするメモリ論理アドレスは実行毎に異なりますので、上記は今回の実行結果です。一方、C#代替実装ではメモリ論理アドレスの代わりにbyte配列のインデックス値がアドレス相当としてリターンスタックにのり、その値は実行毎に同一です。この両者は直接比較できないので、どこでどうくるったのかがそのままでは特定しずらい状況でした。
そこでこの結果のうち、リターンスタックの値rtp+0をEXCEL上で下記のように加工します。
9ステップのリターンスタックの値10311368がC#版のリターンスタックの値5880(バイト配列のインデックス値)と等価の論理アドレス値と仮定して
10311368ー5880=10305488
オフセット値10305488を算出します。この値をアドレスっぽい値のリターンスタック値から減算します。
その結果をC#代替のリターンスタック値(インデックス値)と並べた結果が下記です。
SqNo mcodertp.point rtp+0 オフセット値 rtp+0(補正) rtp+0(C#)
1 8019 1024 0 0
2 002F 1023 10305602 10305488 114 114
3 0012 1023 10305602 10305488 114 114
4 0036 1023 10305602 10305488 114 114
5 0080 1023 10305602 10305488 114 114
6 0036 1023 10305602 10305488 114 114
7 0070 1023 10305602 10305488 114 114
8 803A 1023 10305602 10305488 114 114
9 002F 1022 10311368 10305488 5880 5880
10 80B8 1022 10311368 10305488 5880 5880
11 0012 1021 10311346 10305488 5858 5858
12 0036 1021 10311346 10305488 5858 5858
13 0071 1021 10311346 10305488 5858 5858
14 8046 1021 10311346 10305488 5858 5858
15 8045 1020 10311340 10305488 5852 5852
16 0012 1019 10305814 10305488 326 326
17 0036 1019 10305814 10305488 326 326
18 0074 1019 10305814 10305488 326 326
19 0020 1019 10305814 10305488 326 326
20 0020 1020 10311340 10305488 5852 5852
21 80A3 1021 10311346 10305488 5858 5858
22 0036 1020 10311342 10305488 5854 5854
23 0012 1020 10311342 10305488 5854 5854
24 016E 1020 10311342 10305488 5854 5854
25 0020 1020 10311342 10305488 5854 5854
26 0020 1021 10311346 10305488 5858 5858
27 0020 1022 10311368 10305488 5880 5880
28 00A5 1023 10305602 10305488 114 114
29 803C 1023 10305602 10305488 114 114
30 002F 1022 10311394 10305488 5906 5906
31 001A 1022 10311394 10305488 5906 5906
32 006E 1020 10311342 10305488 5854 0
33 0015 1020 20 20
34 00ED 1020 20 20
35 0022 1020 20 20
36 00A5 1023 10305602 10305488 114 5858
37 00C1 1023 10305602 10305488 114 5858
$$COLD_FORTH
38 0020 1023 10305602 10305488 114 5858
39 80C3 1024 0 10305488 5906
40 00A5 1023 10305604 10305488 116
41 8083 1023 10305604 10305488 116
42 0012 1022 10311892 10305488 6404
43 004E 1022 10311892 10305488 6404
44 00EC 1022 10311892 10305488 6404
45 0096 1022 10311892 10305488 6404
46 026D 1022 10311892 10305488 6404
Hello by mind8
47 0020 1022 10311892 10305488 6404
48 0020 1023 10305604 10305488 116
49 801A 1024 0
50 002F 1023 10305606 10305488 118
51 00A5 1023 10305606 10305488 118
52 00C1 1023 10305606 10305488 118
実行終り
53 801B 1023 10305606 10305488 118
54 002F 1022 10311460 10305488 5972
55 00A5 1022 10311460 10305488 5972
56 00C1 1022 10311460 10305488 5972
実行終り時の処理
57 0020 1022 10311460 10305488 5972
58 0012 1023 10305606 10305488 118
59 004E 1023 10305606 10305488 118
60 0014 1023 10305606 10305488 118
オリジナルのリターンスタックポインタ値がアドレスっぽくない値は補正していませんので、オリジナルのrtp+0をrtp+0(C#)と比較します。この場合はくるっていないようでした。
結論的にはステップ32でずれが検出されますので、その手前のステップ31のmcode(001A)のC#代替実装が怪しいということになりそうです。
現状のC#代替実装ディスパッチャではステップ39よりもう少し処理を継続しますが、ステップ39で処理対象のmcodeに差異が出ていますので、それより後の比較は割愛しています。
つづく
生成されたhello.mcoを解釈して、C#側で「Hello by mind8」が出力されるようにするまでの長い道のりですが、問題個所を特定できたっぽいので、次回はその改修を試みてみます。