C++计算精解【20】

动手做汇编解释器【3】

跳转语句

  1. 增加了条件跳转指令,无条件跳转指令
  2. 增加了cmp,没有这个指令,无法进行跳转
  3. int cmp_flag = 0;作为cmp比较结果的标志位
  4. opcode_map是指令hash,所有支持的指令都在这个hash的key中,不在hash的key中的指令运行抛出异常。
  5. labels标签hash,记录标签标注指令的ip(索引)。
  6. instructions存放指令集。
  7. registers为寄存器。
    代码如下:
#include 
#include 
#include 
#include 
#include 

class AsmVM {
    public:
        AsmVM() {
            initRegs();
            initOpcodes();
        }
        void loadProgram(const std::vector<std::string>& program);
        void execute();
        double getRegVal(const std::string& regName);
    private:
        size_t ip = 0;
        bool running = true;
        int cmp_flag = 0;
        std::unordered_map<std::string, int> opcode_map;
        std::unordered_map<std::string, size_t> labels;
        std::vector<std::string> instructions;
        std::unordered_map<std::string, double> registers;


        void initRegs();
        void initOpcodes();
 
        bool isRegister(const std::string& name);
        void executeInstruction(const std::string& instruction);
        void jumpToLabel(const std::string& label);
        double getValue(const std::string& arg);
};

void AsmVM::loadProgram(const std::vector<std::string>& program) {
    for (size_t i = 0; i < program.size(); i++) {
        std::string codeLine = program[i];
        // 转换成小写
        std::transform(codeLine.begin(), codeLine.end(), codeLine.begin(), ::tolower);
        codeLine.erase(0, codeLine.find_first_not_of(" "));

        if (codeLine.back() == ':') {
            std::string label = codeLine.substr(0, codeLine.size() - 1);
            labels[label] = instructions.size();  // 记录标签位置
        }
        else {
            instructions.push_back(codeLine);
        }

    }
}

void AsmVM::execute() {
    while (running && ip < instructions.size()) {
        executeInstruction(instructions[ip]);
        ip++;
    }
}
void AsmVM::initRegs() {
    registers = { {"eax", 0}, {"ebx", 0}, {"ecx", 0}, {"edx", 0} };
}

void AsmVM::initOpcodes() {
    opcode_map = {
        {"mov", 1}, {"add", 1}, {"sub", 1}, {"mul", 1}, {"div", 1},
        {"cmp", 1}, {"jmp", 1}, {"jl", 1}, {"jg", 1}, {"je", 1}, {"jne", 1},
        {"hlt", 1}, {"out", 1}
    };
}
double AsmVM::getRegVal(const std::string& regName) {
    if (registers.find(regName) == registers.end()) {
        throw std::runtime_error("寄存器不存在: " + regName);
    }
    return registers.at(regName);
}
bool AsmVM::isRegister(const std::string& name) {
    return registers.find(name) != registers.end();
}
void AsmVM::executeInstruction(const std::string& instruction) {
    std::istringstream iss(instruction);
    std::string opcode, args, arg1, arg2;

    iss >> opcode;
    std::getline(iss, args);
    args.erase(0, args.find_first_not_of(" "));
    if (opcode_map.find(opcode) == opcode_map.end()) {
        throw std::runtime_error("未知指令: " + opcode);
    }

    size_t commaPos = args.find(',');
    if (commaPos != std::string::npos) {
        arg1 = args.substr(0, commaPos);
        arg2 = args.substr(commaPos + 1);
        arg1.erase(arg1.find_last_not_of(" ") + 1);
        arg2.erase(0, arg2.find_first_not_of(" "));
    }
    else {
        arg1 = args;
    }

    if (opcode == "mov") {
        if (!isRegister(arg1)) throw std::runtime_error("找不到寄存器 " + arg1);
        registers[arg1] = getValue(arg2);
    }
    else if (opcode == "add") {
        registers[arg1] += getValue(arg2);
    }
    else if (opcode == "sub") {
        registers[arg1] -= getValue(arg2);
    }
    else if (opcode == "mul") {
        registers[arg1] *= getValue(arg2);
    }
    else if (opcode == "div") {
        double divisor = getValue(arg2);
        if (divisor == 0) throw std::runtime_error("除数不能为 0");
        registers[arg1] /= divisor;
    }
    else if (opcode == "cmp") {
        double val1 = registers[arg1];
        double val2 = getValue(arg2);
        cmp_flag = (val1 == val2) ? 0 : (val1 > val2 ? 1 : -1);
    }
    else if (opcode == "out") {
        std::cout << "Register "<< arg1 <<":"<< getRegVal(arg1) << std::endl;
    }
    else if (opcode == "jl" && cmp_flag == -1) {
        jumpToLabel(arg1);
    }
    else if (opcode == "jg" && cmp_flag == 1) {
        jumpToLabel(arg1);
    }
    else if (opcode == "je" && cmp_flag == 0) {
        jumpToLabel(arg1);
    }
    else if (opcode == "jne" && cmp_flag != 0) {
        jumpToLabel(arg1);
    }
    else if (opcode == "jmp") {
        jumpToLabel(arg1);
    }
    else if (opcode == "hlt") {
        running = false;
    }
}
void AsmVM::jumpToLabel(const std::string& label) {
    if (labels.find(label) == labels.end()) {
        throw std::runtime_error("标签不存在: " + label);
    }
    ip = labels[label] - 1;
}
double AsmVM::getValue(const std::string& arg) {
    if (isRegister(arg)) return registers[arg];
    return std::stod(arg);
}
int main() {
    AsmVM vm;
    std::vector<std::string> program = {
        "MOV eax,10.5",
        "MOV ebx, 25.2",
        "ADD eax, 0.5",
        "CMP eax, ebx",
        "JL less",
        "SUB eax, ebx",
        "JMP end",
        "less:", // label必须单独一行
        "MOV eax, 0",
        "end:",  // label必须单独一行
        "out eax",
        "out ebx",
        "HLT"
    };

    try {
        vm.loadProgram(program);
        vm.execute();
    }
    catch (const std::runtime_error& e) {
        std::cerr << "程序异常: " << e.what() << std::endl;
        return -1;
    }

    return 0;
}

C++计算精解【20】_第1张图片

参考文献

  1. chatgpt

你可能感兴趣的:(游戏引擎与高性能计算,c++,开发语言)