「プログラム電卓」は TypeScript で書かれているので、これを C++ に変換して TypeScript から C++ に変換する方法を調べようと思ったのですが、C# で書かれたものもありました。これは C# から C++ に書き換えることにします。
この件はいったん保留して、Z80 アセンブラーを作ってもらうことにしました。これは昔 BASIC の中間コードを Z80 のコードに変換するものを作ったことがあるので、どんなものだったか、今 Z80 について思い出してもしかたがないのですが思い出しておこうと考えたためです。
C++ で Z80 アセンブラーを作ってください
と ChatGPT で入力すると以下の結果となりました。
了解です!Z80アセンブラーをC++で作るには、以下のようなコンポーネントが必要になります:
基本構成
1. 字句解析 (Lexer):
2. 構文解析 (Parser):
- トークン列を命令やラベルなどの構造に変換する。
3. コード生成 (Code Generator):
4. ラベルの解決:
- ジャンプ先などに使われるラベルを、アドレスに変換する。
最小構成のZ80アセンブラー(C++)
以下はシンプルなZ80命令(例:`LD A, 0x42`)のみを扱う最小構成の例です。
ファイル: `z80_assembler.cpp`
#include <iostream> #include <fstream> #include <sstream> #include <unordered_map> #include <vector> #include <iomanip> struct Instruction { std::string mnemonic; std::vector<std::string> operands; }; std::vector<std::string> tokenize(const std::string& line) { std::stringstream ss(line); std::string token; std::vector<std::string> tokens; while (ss >> token) { // カンマを削除 if (!token.empty() && token.back() == ',') { token.pop_back(); } tokens.push_back(token); } return tokens; } // 単純なLD命令のみ対応: LD A, n std::vector<uint8_t> assemble(const Instruction& inst) { if (inst.mnemonic == "LD" && inst.operands.size() == 2) { if (inst.operands[0] == "A") { uint8_t value = std::stoi(inst.operands[1], nullptr, 0); return {0x3E, value}; // LD A, n の機械語 } } std::cerr << "未対応の命令: " << inst.mnemonic << "\n"; return {}; } int main(int argc, char* argv[]) { if (argc != 3) { std::cerr << "使い方: " << argv[0] << " input.asm output.bin\n"; return 1; } std::ifstream infile(argv[1]); if (!infile) { std::cerr << "入力ファイルが開けません: " << argv[1] << "\n"; return 1; } std::vector<uint8_t> output; std::string line; while (std::getline(infile, line)) { auto tokens = tokenize(line); if (tokens.empty()) continue; Instruction inst; inst.mnemonic = tokens[0]; inst.operands.assign(tokens.begin() + 1, tokens.end()); auto code = assemble(inst); output.insert(output.end(), code.begin(), code.end()); } std::ofstream outfile(argv[2], std::ios::binary); if (!outfile) { std::cerr << "出力ファイルが開けません: " << argv[2] << "\n"; return 1; } outfile.write(reinterpret_cast<char*>(output.data()), output.size()); std::cout << "アセンブル完了: " << output.size() << " バイト生成されました。\n"; return 0; }使い方
アセンブリファイル `input.asm`
LD A, 0x42 LD A, 255







