X68000 用のプログラムでスーパーバイザーモードの中にコンパイラが出力するアセンブリ言語のプログラムを書くのが目的なので、少しやり方を変えます。スタックの状態がよくわからないのが問題の一つと考えられます。まずそれを調べるために以下のようなことを ChatGPT で調べてみました。
GCC の 68000 向けの C++ コンパイラが出力する 68000 のアセンブリ言語を解釈して、スタックの状態を確認するための簡易的なインタープリターを作ってください
と入力すると以下のような結果が返ってきました。
GCC が 68000 向けに出力するアセンブリコードを扱うための「簡易インタープリター(スタックの状態を追跡する)」を C++ で作るサンプルを以下に示します。
🎯 目的
- `move`, `add`, `sub`, `link`, `unlk`, `jsr`, `rts` などの命令を解釈
- スタックポインタ (`A7`) とスタック領域をシミュレート
- 命令の実行ごとにスタックの状態を出力
📘 制約と前提
🧪 例に対応するアセンブリコード例
link a6,#-8 move.l d0,-(a7) add.l #4,d0 move.l (a7)+,d1 unlk a6 rts🛠️ 簡易インタープリターの C++ コード
#include <iostream> #include <sstream> #include <map> #include <vector> #include <iomanip> using namespace std; using u32 = uint32_t; struct CPU { map<string, u32> D; // D0-D7 map<string, u32> A; // A0-A7 vector<u32> stack; // スタック領域(32ビット値) u32 baseSP = 0x1000; // スタックベースアドレス CPU() { for (int i = 0; i < 8; ++i) { D["d" + to_string(i)] = 0; A["a" + to_string(i)] = 0; } A["a7"] = baseSP; // スタックポインタの初期化 stack.resize(1024, 0); // スタックは 4KB 分確保 } // SP に基づくアドレスインデックス int spIndex() { return (baseSP - A["a7"]) / 4; } void push(u32 val) { A["a7"] -= 4; stack[spIndex()] = val; } u32 pop() { u32 val = stack[spIndex()]; A["a7"] += 4; return val; } void dumpStack() { cout << "SP = $" << hex << A["a7"] << dec << endl; for (int i = spIndex(); i < (int)stack.size(); ++i) { cout << " [$" << hex << (baseSP - i * 4) << "] = $" << stack[i] << dec << endl; } } }; void interpret(const vector<string>& lines) { CPU cpu; for (const string& line : lines) { cout << "> " << line << endl; istringstream iss(line); string op; iss >> op; if (op == "link") { string reg, offset; iss >> reg >> offset; reg.pop_back(); // remove comma int disp = stoi(offset); cpu.push(cpu.A[reg]); // save old frame pointer cpu.A[reg] = cpu.A["a7"]; cpu.A["a7"] += disp; // allocate space } else if (op == "unlk") { string reg; iss >> reg; cpu.A["a7"] = cpu.A[reg]; cpu.A[reg] = cpu.pop(); } else if (op == "move.l") { string src, dst; iss >> src >> dst; if (src == "d0" && dst == "-(a7)") { cpu.push(cpu.D["d0"]); } else if (src == "(a7)+" && dst == "d1") { cpu.D["d1"] = cpu.pop(); } } else if (op == "add.l") { string imm, dst; iss >> imm >> dst; if (imm[0] == '#') { int val = stoi(imm.substr(1)); cpu.D[dst] += val; } } else if (op == "rts") { cout << "Return from subroutine" << endl; } else if (op == "jsr") { cout << "Jump to subroutine (not simulated)" << endl; } cpu.dumpStack(); cout << endl; } }🧪 使用例
int main() { vector<string> asmCode = { "link a6,#-8", "move.l d0,-(a7)", "add.l #4,d0", "move.l (a7)+,d1", "unlk a6", "rts" }; interpret(asmCode); return 0; }✅ 実行結果の一例(概略)
> link a6,#-8 SP = $0ffc [$0ffc] = $1000 > move.l d0,-(a7) SP = $0ff8 [$0ffc] = $1000 [$0ff8] = $0 > add.l #4,d0 SP = $0ff8 [$0ffc] = $1000 [$0ff8] = $0 > move.l (a7)+,d1 SP = $0ffc [$0ffc] = $1000 > unlk a6 SP = $1000 > rts Return from subroutine
