先修复上一次的bug,添加新指令,并增加图形界面
#include <graphics.h>
#include <conio.h>
#include <windows.h>
#include <commdlg.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <thread>
#include <mutex>
#include <functional>
#include <vector>
#include <string>
#include <map>
void VM(const std::string& file);
// 虚拟机配置结构体
struct VMConfig {
std::string name;
std::string asmPath;
};
// 全局配置存储
std::map<std::string, VMConfig> vmConfigs;
const char* CONFIG_FILE = "vm.dll";
// 图形界面尺寸参数
const int WIDTH = 800;
const int HEIGHT = 600;
const int BTN_WIDTH = 200;
const int BTN_HEIGHT = 40;
// 当前操作状态
enum class AppState {
MAIN_MENU,
CREATE_VM,
OPEN_VM,
SETTINGS
};
AppState currentState = AppState::MAIN_MENU;
char vmNameInput[64] = {0};
char asmPathInput[256] = {0};
// 初始化图形界面
void InitGUI() {
initgraph(WIDTH, HEIGHT);
setbkcolor(WHITE);
cleardevice();
settextcolor(BLACK);
settextstyle(30, 0, "宋体");
}
// 保存配置到文件
void SaveConfig() {
std::ofstream fout(CONFIG_FILE);
for (auto it = vmConfigs.begin(); it!= vmConfigs.end(); ++it) {
fout << it->first << std::endl;
fout << it->second.asmPath << std::endl;
}
fout.close();
}
// 加载配置文件
void LoadConfig() {
vmConfigs.clear();
std::ifstream fin(CONFIG_FILE);
std::string name, path;
while (std::getline(fin, name) && std::getline(fin, path)) {
vmConfigs[name] = {name, path};
}
fin.close();
}
// 绘制主界面
void DrawMainMenu() {
cleardevice();
// 绘制标题
settextcolor(BLUE);
outtextxy(100, 50, "VMwork 虚拟机");
// 绘制按钮
setfillcolor(LIGHTGRAY);
// 新建虚拟机按钮
fillroundrect(300, 150, 300 + BTN_WIDTH, 150 + BTN_HEIGHT, 5, 5);
outtextxy(330, 155, "新建虚拟机");
// 打开虚拟机按钮
fillroundrect(300, 250, 300 + BTN_WIDTH, 250 + BTN_HEIGHT, 5, 5);
outtextxy(330, 255, "打开虚拟机");
// 设置按钮
fillroundrect(300, 350, 300 + BTN_WIDTH, 350 + BTN_HEIGHT, 5, 5);
outtextxy(350, 355, "设置");
}
// 文件选择对话框封装
std::string SelectFile() {
OPENFILENAMEA ofn;
char szFile[260] = {0};
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "ASM Files (*.asm)\0*.asm\0All Files (*.*)\0*.*\0";
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileNameA(&ofn)) {
return szFile;
}
return "";
}
// 输入框处理函数
bool InputBox(const char* title, char* buffer, int bufferSize) {
char prompt[10] = "";
// 这里直接调用 easyx 的 InputBox 函数,按照其参数要求传递
return InputBox(buffer, bufferSize, prompt, title);
}
// 创建虚拟机流程
void CreateVMProcess() {
// 第一步:选择ASM文件
std::string asmPath = SelectFile();
if (asmPath.empty()) return;
// 第二步:输入虚拟机名称
if (!InputBox("输入虚拟机名称", vmNameInput, sizeof(vmNameInput))) return;
// 保存配置
vmConfigs[vmNameInput] = {vmNameInput, asmPath};
SaveConfig();
}
void OpenVMProcess() {
LoadConfig();
// 创建选择列表
cleardevice();
settextcolor(BLACK);
outtextxy(50, 50, "选择虚拟机:");
// 绘制虚拟机列表
int y = 100;
for (auto it = vmConfigs.begin(); it!= vmConfigs.end(); ++it) {
std::string text = it->first + " (" + it->second.asmPath + ")";
outtextxy(100, y, text.c_str());
y += 50;
}
// 等待用户选择
int choice = 0;
while (true) {
if (MouseHit()) {
MOUSEMSG msg = GetMouseMsg();
if (msg.uMsg == WM_LBUTTONDOWN) {
int clickY = msg.y;
int index = 0;
for (auto it = vmConfigs.begin(); it!= vmConfigs.end(); ++it) {
int itemTop = 100 + index * 40;
if (clickY > itemTop && clickY < itemTop + 50) {
choice = index + 1;
break;
}
index++;
}
}
}
if (choice!= 0) break;
}
// 启动选定虚拟机
if (choice > 0 && choice <= vmConfigs.size()) {
auto it = vmConfigs.begin();
std::advance(it, choice - 1);
std::string selectedAsmPath = it->second.asmPath;
VM(selectedAsmPath);
}
}
void SetVMProcess() {
LoadConfig();
cleardevice();
cleardevice();
settextcolor(BLACK);
outtextxy(30, 50, "虚拟机");
outtextxy(50, 90, "处理器 : 1");
outtextxy(50, 130, "内存 : 64KB");
outtextxy(50, 170,"启动方式: 软盘");
outtextxy(50, 210,"光盘 : 无");
outtextxy(50, 250,"BIOS : VMwork");
outtextxy(50, 290,"方式 : .ASM");
while(1) {
}
}
// 主消息循环
void MainLoop() {
AppState prevState = AppState::MAIN_MENU;
while (true) {
if (MouseHit()) {
MOUSEMSG msg = GetMouseMsg();
if (msg.uMsg == WM_LBUTTONDOWN) {
// 主界面按钮处理
if (currentState == AppState::MAIN_MENU) {
if (msg.x > 300 && msg.x < 300 + BTN_WIDTH) {
if (msg.y > 150 && msg.y < 150 + BTN_HEIGHT) {
CreateVMProcess();
} else if (msg.y > 250 && msg.y < 250 + BTN_HEIGHT) {
OpenVMProcess();
} else if (msg.y > 350 && msg.y < 350 + BTN_HEIGHT) {
SetVMProcess();
}
}
}
}
}
switch (currentState) {
case AppState::MAIN_MENU:
if (prevState!= AppState::MAIN_MENU) {
//cleardevice();
}
DrawMainMenu();
break;
case AppState::CREATE_VM:
if (prevState!= AppState::CREATE_VM) {
//cleardevice();
}
DrawMainMenu();
break;
case AppState::OPEN_VM:
if (prevState!= AppState::OPEN_VM) {
//cleardevice();
}
DrawMainMenu();
break;
case AppState::SETTINGS:
if (prevState!= AppState::SETTINGS) {
//cleardevice();
}
DrawMainMenu();
break;
}
prevState = currentState;
Sleep(30);
}
}
// 寄存器声明
unsigned char al = 0, ah = 0, bl = 0, bh = 0, cl = 0, ch = 0, dl = 0, dh = 0, si = 0;
unsigned short ax = 0, bx = 0, cx = 0, dx = 0, sp = 0x8000, bp = 0;
unsigned int org = 0, end_times = 0, end_AA55 = 0;
bool ZF = false, CF = false, SF = false; // 标志寄存器
// 标签和指令指针
std::unordered_map<std::string, size_t> labels;
size_t current_line = 0;
size_t new_current_line;
std::vector<std::string> program_lines;
// 内存模拟
std::vector<unsigned char> memory(0x10000, 0); // 64KB内存
std::mutex fileMutex;
std::ifstream file;
// 线程函数,用于读取文件
void readFile(const std::string& filename) {
std::ifstream localFile(filename, std::ios::binary);
if (localFile.is_open()) {
const size_t bufferSize = 4096; // 每块读取4KB,可以根据需要调整
char buffer[bufferSize];
std::string currentLine;
while (localFile.read(buffer, bufferSize)) {
for (size_t i = 0; i < localFile.gcount(); ++i) {
if (buffer[i] == '\n') {
size_t commentPos = currentLine.find(';');
if (commentPos!= std::string::npos) {
currentLine = currentLine.substr(0, commentPos);
}
while (!currentLine.empty() && std::isspace(currentLine.front())) {
currentLine.erase(currentLine.begin());
}
while (!currentLine.empty() && std::isspace(currentLine.back())) {
currentLine.erase(currentLine.length() - 1);
}
if (!currentLine.empty()) {
std::lock_guard<std::mutex> lock(fileMutex);
program_lines.push_back(currentLine);
}
currentLine.clear();
} else {
currentLine += buffer[i];
}
}
}
// 处理剩余的行
size_t commentPos = currentLine.find(';');
if (commentPos!= std::string::npos) {
currentLine = currentLine.substr(0, commentPos);
}
while (!currentLine.empty() && std::isspace(currentLine.front())) {
currentLine.erase(currentLine.begin());
}
while (!currentLine.empty() && std::isspace(currentLine.back())) {
currentLine.erase(currentLine.length() - 1);
}
if (!currentLine.empty()) {
std::lock_guard<std::mutex> lock(fileMutex);
program_lines.push_back(currentLine);
}
localFile.close();
} else {
std::cerr << "无法打开文件" << std::endl;
}
}
// 图形输出参数
int textX = 0;
int textY = 48;
const int CHAR_WIDTH = 8;
const int LINE_HEIGHT = 16;
bool graphicsInitialized = false;
// 指令解析错误枚举
enum class InstructionError {
INVALID_OPCODE,
INVALID_OPERAND,
LABEL_NOT_FOUND,
UNKNOWN_INTERRUPT,
OTHER_ERROR
};
// 输出错误信息到终端
void printError(const InstructionError& error, const std::string& details = "") {
std::cerr << "ERROR: ";
switch (error) {
case InstructionError::INVALID_OPCODE:
std::cerr << "无效的操作码";
break;
case InstructionError::INVALID_OPERAND:
std::cerr << "无效的操作数";
break;
case InstructionError::LABEL_NOT_FOUND:
std::cerr << "标签未找到";
break;
case InstructionError::UNKNOWN_INTERRUPT:
std::cerr << "未知的中断号";
break;
case InstructionError::OTHER_ERROR:
std::cerr << "其他错误";
break;
}
if (!details.empty()) {
std::cerr << " - " << details;
}
std::cerr << std::endl;
}
int parseImmediate(const std::string& immediateStr) {
std::string result;
bool inQuote = false;
char quoteChar = '\0';
for (size_t i = 0; i < immediateStr.size(); ++i) {
const char c = immediateStr[i];
if (c == '\'' || c == '"') {
if (!inQuote) {
inQuote = true;
quoteChar = c;
result += c;
} else if (c == quoteChar) {
inQuote = false;
result += c;
} else {
result += c;
}
} else if (inQuote) {
// 直接将引号内的字符添加到结果中,包括空格
result += c;
} else if (!std::isspace(c)) {
// 非空格且不在引号内,将字符添加到结果中
result += c;
} else if (i > 0 &&!std::isspace(result.back())) {
// 如果前一个字符不是空格,添加当前字符以保留中间的空格
result += c;
}
}
// 去除结果字符串两端可能残留的空格
while (!result.empty() && std::isspace(result.front())) {
result.erase(result.begin());
}
while (!result.empty() && std::isspace(result.back())) {
result.erase(result.length() - 1);
}
if (result.empty()) return 0;
if (result.length() == 3 && result[0] == '\'' && result[2] == '\'') {
return static_cast<int>(result[1]);
}
else if (result.find("0x") == 0) {
try {
return std::stoi(result.substr(2), nullptr, 16);
} catch (const std::invalid_argument& e) {
throw std::invalid_argument("无效的十六进制立即数:" + result);
} catch (const std::out_of_range& e) {
throw std::out_of_range("十六进制立即数超出范围:" + result);
}
}
else if (result.back() == 'h') {
try {
return std::stoi(result.substr(0, result.length() - 1), nullptr, 16);
} catch (const std::invalid_argument& e) {
throw std::invalid_argument("无效的十六进制立即数(以h结尾):" + result);
} catch (const std::out_of_range& e) {
throw std::out_of_range("十六进制立即数(以h结尾)超出范围:" + result);
}
}
else {
try {
return std::stoi(result);
} catch (const std::invalid_argument& e) {
throw std::invalid_argument("无效的立即数:" + result);
} catch (const std::out_of_range& e) {
throw std::out_of_range("立即数超出范围:" + result);
}
}
}
std::unordered_map<std::string, unsigned char*>& createRegister8BitMap() {
static std::unordered_map<std::string, unsigned char*> map = {
{"al", &al}, {"ah", &ah}, {"bl", &bl}, {"bh", &bh},
{"cl", &cl}, {"ch", &ch}, {"dl", &dl}, {"dh", &dh},
{"si", &si}
};
return map;
}
std::unordered_map<std::string, unsigned short*>& createRegister16BitMap() {
static std::unordered_map<std::string, unsigned short*> map = {
{"ax", &ax}, {"bx", &bx}, {"cx", &cx}, {"dx", &dx},
{"sp", &sp}, {"bp", &bp}
};
return map;
}
void UpdateTextPosition() {
textX += CHAR_WIDTH;
if (textX > 620) {
textX = 20;
textY += LINE_HEIGHT;
}
if (textY + LINE_HEIGHT > 480) {
cleardevice();
textX = 0;
textY = 0;
}
}
void MovInstruction(const std::string& line) {
std::string processedLine = line;
std::replace(processedLine.begin(), processedLine.end(), ',', ' ');
std::istringstream iss(processedLine);
std::string opcode, dest, src;
iss >> opcode >> dest >> src;
auto& reg8 = createRegister8BitMap();
auto& reg16 = createRegister16BitMap();
auto parseOperand = [&](const std::string& op) -> int {
if (reg8.count(op)) return *reg8[op];
if (reg16.count(op)) return *reg16[op];
return parseImmediate(op);
};
int value = parseOperand(src);
if (reg8.count(dest)) {
*reg8[dest] = static_cast<unsigned char>(value);
}
else if (reg16.count(dest)) {
*reg16[dest] = static_cast<unsigned short>(value);
}
}
// add指令处理函数
void AddInstruction(const std::string& line) {
std::string processedLine = line;
std::replace(processedLine.begin(), processedLine.end(), ',', ' ');
std::istringstream iss(processedLine);
std::string opcode, dest, src;
iss >> opcode >> dest >> src;
auto& reg8 = createRegister8BitMap();
auto& reg16 = createRegister16BitMap();
auto parseOperand = [&](const std::string& op) -> int {
if (reg8.count(op)) return *reg8[op];
if (reg16.count(op)) return *reg16[op];
return parseImmediate(op);
};
int val1 = parseOperand(dest);
int val2 = parseOperand(src);
int result = val1 + val2;
if (reg8.count(dest)) {
*reg8[dest] = static_cast<unsigned char>(result);
}
else if (reg16.count(dest)) {
*reg16[dest] = static_cast<unsigned short>(result);
}
ZF = (result == 0);
SF = (result < 0);
CF = (static_cast<unsigned>(result) < static_cast<unsigned>(val1));
}
// sub指令处理函数
void SubInstruction(const std::string& line) {
std::string processedLine = line;
std::replace(processedLine.begin(), processedLine.end(), ',', ' ');
std::istringstream iss(processedLine);
std::string opcode, dest, src;
iss >> opcode >> dest >> src;
auto& reg8 = createRegister8BitMap();
auto& reg16 = createRegister16BitMap();
auto parseOperand = [&](const std::string& op) -> int {
if (reg8.count(op)) return *reg8[op];
if (reg16.count(op)) return *reg16[op];
return parseImmediate(op);
};
int val1 = parseOperand(dest);
int val2 = parseOperand(src);
int result = val1 - val2;
if (reg8.count(dest)) {
*reg8[dest] = static_cast<unsigned char>(result);
}
else if (reg16.count(dest)) {
*reg16[dest] = static_cast<unsigned short>(result);
}
ZF = (result == 0);
SF = (result < 0);
CF = (static_cast<unsigned>(val1) < static_cast<unsigned>(val2));
}
// inc指令处理函数
void IncInstruction(const std::string& line) {
std::istringstream iss(line);
std::string opcode, operand;
iss >> opcode >> operand;
auto& reg8 = createRegister8BitMap();
auto& reg16 = createRegister16BitMap();
if (reg8.count(operand)) {
*reg8[operand] += 1;
ZF = (*reg8[operand] == 0);
SF = (*reg8[operand] < 0);
}
else if (reg16.count(operand)) {
*reg16[operand] += 1;
ZF = (*reg16[operand] == 0);
SF = (*reg16[operand] < 0);
}
}
void CmpInstruction(const std::string& line) {
std::string processedLine = line;
std::replace(processedLine.begin(), processedLine.end(), ',', ' ');
std::istringstream iss(processedLine);
std::string opcode, op1, op2;
iss >> opcode >> op1 >> op2;
auto& reg8 = createRegister8BitMap();
auto& reg16 = createRegister16BitMap();
auto parseOperand = [&](const std::string& op) -> int {
if (reg8.count(op)) return *reg8[op];
if (reg16.count(op)) return *reg16[op];
return parseImmediate(op);
};
int val1 = parseOperand(op1);
int val2 = parseOperand(op2);
int result = val1 - val2;
ZF = (result == 0);
SF = (result < 0);
CF = (static_cast<unsigned>(val1) < static_cast<unsigned>(val2));
}
void JmpInstruction(const std::string& line) {
std::istringstream iss(line);
std::string opcode, label;
iss >> opcode >> label;
if (labels.count(label)) {
new_current_line = labels[label];
} else {
printError(InstructionError::LABEL_NOT_FOUND, "JMP指令中的标签: " + label);
}
}
void JeInstruction(const std::string& line) {
std::istringstream iss(line);
std::string opcode, label;
iss >> opcode >> label;
if (ZF) {
if (labels.count(label)) {
new_current_line = labels[label];
} else {
printError(InstructionError::LABEL_NOT_FOUND, "JE指令中的标签: " + label);
}
} else {
new_current_line = current_line + 1;
}
}
void JneInstruction(const std::string& line) {
std::istringstream iss(line);
std::string opcode, label;
iss >> opcode >> label;
if (!ZF) {
if (labels.count(label)) {
new_current_line = labels[label];
} else {
printError(InstructionError::LABEL_NOT_FOUND, "JNE指令中的标签: " + label);
}
} else {
new_current_line = current_line + 1;
}
}
void PushInstruction(const std::string& line) {
std::istringstream iss(line);
std::string opcode, src;
iss >> opcode >> src;
auto& reg16 = createRegister16BitMap();
unsigned short value = reg16.count(src)? *reg16[src] : parseImmediate(src);
sp -= 2;
memory[sp] = value & 0xFF;
memory[sp + 1] = (value >> 8) & 0xFF;
}
void PopInstruction(const std::string& line) {
std::istringstream iss(line);
std::string opcode, dest;
iss >> opcode >> dest;
auto& reg16 = createRegister16BitMap();
if (reg16.count(dest)) {
*reg16[dest] = memory[sp] | (memory[sp + 1] << 8);
sp += 2;
}
}
void XorInstruction(const std::string& line) {
std::string processedLine = line;
std::replace(processedLine.begin(), processedLine.end(), ',', ' ');
std::istringstream iss(processedLine);
std::string opcode, dest, src;
iss >> opcode >> dest >> src;
auto& reg8 = createRegister8BitMap();
auto& reg16 = createRegister16BitMap();
auto parseOperand = [&](const s