当前位置: 首页 > news >正文

自己免费网站建设/网站访问量统计工具

自己免费网站建设,网站访问量统计工具,江门网红打卡点,如何建设网站pdf开源地址:VMwork 要使终端不弹出&#xff0c; #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") 还要实现jmp near 0x01类似的 本次的main.cpp #include <graphics.h> #include <conio.h> #include <windows.h> #includ…

开源地址:VMwork

要使终端不弹出,

#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")

还要实现jmp near 0x01类似的

本次的main.cpp

#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>
#include <shlwapi.h>using namespace std;#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")void VM(const string& file);void ShowErrorDialog(const string& message) {MessageBox(GetHWnd(), message.c_str(), "VMwork 错误", MB_ICONERROR | MB_OK);
}string GetCurrentDirectoryPath() {char buffer[MAX_PATH] = {0};GetModuleFileNameA(NULL, buffer, MAX_PATH);string::size_type pos = string(buffer).find_last_of("\\/");return string(buffer).substr(0, pos);
}// 虚拟机配置结构体
struct VMConfig {string name;string filePath;  // 统一文件路径字段string fileType;  // "ASM" 或 "IMG"
};// 全局配置存储
map<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);HWND hWnd = GetHWnd();SetWindowText(hWnd, "VMwork 虚拟机");ShowWindow(hWnd, SW_SHOWNORMAL);setbkcolor(WHITE);cleardevice();settextcolor(BLACK);settextstyle(30, 0, "宋体");
}void SaveConfig() {ofstream fout(CONFIG_FILE);for (auto& entry : vmConfigs) {auto& name = entry.first;auto& config = entry.second;fout << name << endl;fout << config.filePath << endl;fout << config.fileType << endl;}fout.close();
}void LoadConfig() {vmConfigs.clear();ifstream fin(CONFIG_FILE);string name, path, type;while (getline(fin, name) && getline(fin, path) && getline(fin, type)) {vmConfigs[name] = {name, path, type};}fin.close();
}void DrawMainMenu() {cleardevice();setbkcolor(WHITE);settextcolor(BLUE);settextstyle(30, 0, "宋体");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, "设置");
}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 = "IMG Files (*.img)\0*.img\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] = "";return InputBox(buffer, bufferSize, prompt, title); 
}void CreateVMProcess() {int fileType = MessageBox(GetHWnd(), "是否启用读取nasm语法?\n[否]则以img软盘读取", "VMwork", MB_YESNO | MB_ICONQUESTION);bool isASM = (fileType == IDYES);OPENFILENAMEA ofn;char szFile[260] = {0};ZeroMemory(&ofn, sizeof(ofn));ofn.lStructSize = sizeof(ofn);ofn.lpstrFile = szFile;ofn.nMaxFile = sizeof(szFile);ofn.lpstrFilter = isASM ? "ASM Files (*.asm)\0*.asm\0All Files (*.*)\0*.*\0" :"IMG Files (*.img)\0*.img\0All Files (*.*)\0*.*\0";ofn.nFilterIndex = 1;ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;if (!GetOpenFileNameA(&ofn)) return;if (!InputBox("输入虚拟机名称", vmNameInput, sizeof(vmNameInput))) return;vmConfigs[vmNameInput] = {vmNameInput, szFile, isASM ? "ASM" : "IMG"};SaveConfig();
}void DisassembleImg(const string& imgPath, const string& asmPath) {string cmd = "cmd /c \"\"" + GetCurrentDirectoryPath() + "\\ndisasm.exe\" \"" + imgPath + "\" > \"" + asmPath + "\"\"";WinExec(cmd.c_str(), SW_HIDE);
}void ProcessAsm(const string& asmPath, const string& finalAsmPath) {string cmd = "cmd /c \"\"" + GetCurrentDirectoryPath() + "\\toasm.exe\" \"" + asmPath + "\" \"" + finalAsmPath + "\"\"";WinExec(cmd.c_str(), SW_HIDE);
}void OpenVMProcess() {LoadConfig();cleardevice();settextcolor(BLACK);outtextxy(50, 50, "选择虚拟机:");int y = 100;for (auto& entry : vmConfigs) {std::string text = entry.first + " (" + entry.second.filePath + ")";outtextxy(100, y, const_cast<char*>(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& entry : vmConfigs) {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();advance(it, choice - 1);string selectedPath = it->second.filePath;string tempAsmPath = "temp.asm";string finalAsmPath = "final.asm";if (it->second.fileType == "IMG") {DisassembleImg(selectedPath, tempAsmPath);ProcessAsm(tempAsmPath, finalAsmPath);}else {finalAsmPath = selectedPath;}VM(finalAsmPath);}
}void SetVMProcess() {LoadConfig();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, "方式    : .IMG/.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;unordered_map<string, size_t> labels;
size_t current_line = 0;
size_t new_current_line;
vector<string> program_lines;vector<unsigned char> memory(0x10000, 0);mutex fileMutex;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 string& details = "") {//cerr << "ERROR: ";switch (error) {case InstructionError::INVALID_OPCODE: MessageBox(GetHWnd(), "无效的操作码", "运行时错误", MB_ICONERROR); break;case InstructionError::INVALID_OPERAND: MessageBox(GetHWnd(), "无效的操作数", "运行时错误", MB_ICONERROR); break;case InstructionError::LABEL_NOT_FOUND: MessageBox(GetHWnd(), "标签未找到", "运行时错误", MB_ICONERROR); break;case InstructionError::UNKNOWN_INTERRUPT: MessageBox(GetHWnd(), "未知的中断号", "运行时错误", MB_ICONERROR); break;case InstructionError::OTHER_ERROR: MessageBox(GetHWnd(), "未知错误", "运行时错误", MB_ICONERROR); break;}if (!details.empty()) cerr << " - " << details;cerr << endl;
}int parseImmediate(const string& immediateStr) {string result;bool inQuote = false;char quoteChar = '\0';for (size_t i = 0; i < immediateStr.size(); ++i) {char c = immediateStr[i];if (c == '\'' || c == '"') {if (!inQuote) {inQuote = true;quoteChar = c;} else if (c == quoteChar) {inQuote = false;}} else if (!inQuote && isspace(c)) {continue;}result += c;}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) {return stoi(result.substr(2), nullptr, 16);}else if (result.back() == 'h') {return stoi(result.substr(0, result.length() - 1), nullptr, 16);}else {return stoi(result);}
}int parseImmediate1(const string& immediateStr) {string processed = immediateStr;// 移除跳转修饰符(near/short/far)vector<string> modifiers = {"near ", "short ", "far "};for (const auto& mod : modifiers) {size_t pos = processed.find(mod);if (pos != string::npos) {processed.erase(pos, mod.length());break;}}// 处理段:偏移格式(仅取偏移部分)size_t colon = processed.find(':');if (colon != string::npos) {processed = processed.substr(colon + 1);}// 处理返回指令的立即数(ret 4 -> 解析4)size_t space = processed.find(' ');if (space != string::npos) {processed = processed.substr(0, space);}// 处理引号字符('A' -> 65)if (processed.length() == 3 && processed[0] == '\'' && processed[2] == '\'') {return static_cast<int>(processed[1]);}// 处理十六进制格式if (processed.find("0x") == 0) {return stoi(processed.substr(2), nullptr, 16);}// 处理h结尾的十六进制if (!processed.empty() && processed.back() == 'h') {return stoi(processed.substr(0, processed.length()-1), nullptr, 16);}// 处理二进制格式(新增支持)if (processed.find("0b") == 0) {return stoi(processed.substr(2), nullptr, 2);}// 处理符号(+/-)bool negative = false;if (!processed.empty()) {if (processed[0] == '+') {processed = processed.substr(1);} else if (processed[0] == '-') {negative = true;processed = processed.substr(1);}}// 最终数值转换try {int value = stoi(processed);return negative ? -value : value;} catch (...) {//throw invalid_argument("无法解析的立即数: " + immediateStr);MessageBox(GetHWnd(), ("无法解析的立即数: " + immediateStr).c_str(), "运行时错误", MB_ICONERROR);}
}unordered_map<string, unsigned char*> createRegister8BitMap() {return {{"al", &al}, {"ah", &ah}, {"bl", &bl}, {"bh", &bh},{"cl", &cl}, {"ch", &ch}, {"dl", &dl}, {"dh", &dh},{"si", &si}};
}unordered_map<string, unsigned short*> createRegister16BitMap() {return {{"ax", &ax}, {"bx", &bx}, {"cx", &cx}, {"dx", &dx},{"sp", &sp}, {"bp", &bp}};
}void UpdateTextPosition() {textX += CHAR_WIDTH;if (textX > 620) {textX = 0;textY += LINE_HEIGHT;}if (textY + LINE_HEIGHT > 480) {cleardevice();textX = 0;textY = 0;}
}void MovInstruction(const string& line) {string processedLine = line;replace(processedLine.begin(), processedLine.end(), ',', ' ');istringstream iss(processedLine);string opcode, dest, src;iss >> opcode >> dest >> src;auto reg8 = createRegister8BitMap();auto reg16 = createRegister16BitMap();auto parseOperand = [&](const 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);}
}void AddInstruction(const string& line) {string processedLine = line;replace(processedLine.begin(), processedLine.end(), ',', ' ');istringstream iss(processedLine);string opcode, dest, src;iss >> opcode >> dest >> src;auto reg8 = createRegister8BitMap();auto reg16 = createRegister16BitMap();auto parseOperand = [&](const 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));
}void SubInstruction(const string& line) {string processedLine = line;replace(processedLine.begin(), processedLine.end(), ',', ' ');istringstream iss(processedLine);string opcode, dest, src;iss >> opcode >> dest >> src;auto reg8 = createRegister8BitMap();auto reg16 = createRegister16BitMap();auto parseOperand = [&](const 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));
}void IncInstruction(const string& line) {istringstream iss(line);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 string& line) {string processedLine = line;replace(processedLine.begin(), processedLine.end(), ',', ' ');istringstream iss(processedLine);string opcode, op1, op2;iss >> opcode >> op1 >> op2;auto reg8 = createRegister8BitMap();auto reg16 = createRegister16BitMap();auto parseOperand = [&](const 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 string& line) {istringstream iss(line);string opcode, modifier, operand;iss >> opcode >> modifier;// 处理跳转修饰符(short/near)if (modifier == "short" || modifier == "near" || modifier == "nearptr") {iss >> operand;} else {operand = modifier;}// 优先尝试标签跳转if (labels.count(operand)) {new_current_line = labels[operand];return;}// 尝试解析为数值跳转try {int offset = parseImmediate(operand);// 计算相对于下一条指令的偏移new_current_line = current_line + 1 + offset;} catch (...) {printError(InstructionError::LABEL_NOT_FOUND, "JMP指令中的目标未找到: " + operand);}
}void JeInstruction(const string& line) {istringstream iss(line);string opcode, modifier, operand;iss >> opcode >> modifier;if (modifier == "short" || modifier == "near" || modifier == "nearptr") {iss >> operand;} else {operand = modifier;}if (ZF) {if (labels.count(operand)) {new_current_line = labels[operand];} else {try {int offset = parseImmediate(operand);new_current_line = current_line + 1 + offset;} catch (...) {printError(InstructionError::LABEL_NOT_FOUND, "JE指令中的目标未找到: " + operand);}}} else {new_current_line = current_line + 1;}
}void JneInstruction(const string& line) {istringstream iss(line);string opcode, modifier, operand;iss >> opcode >> modifier;if (modifier == "short" || modifier == "near" || modifier == "nearptr") {iss >> operand;} else {operand = modifier;}if (!ZF) {if (labels.count(operand)) {new_current_line = labels[operand];} else {try {int offset = parseImmediate(operand);new_current_line = current_line + 1 + offset;} catch (...) {printError(InstructionError::LABEL_NOT_FOUND, "JNE指令中的目标未找到: " + operand);}}} else {new_current_line = current_line + 1;}
}void CallInstruction(const string& line) {istringstream iss(line);string opcode, modifier, operand;iss >> opcode;  // 读取call// 读取剩余部分作为操作数getline(iss, operand);operand = operand.substr(operand.find_first_not_of(" \t"), operand.find_last_not_of(" \t")+1);// 处理修饰符(如far)size_t space = operand.find(' ');if (space != string::npos) {operand = operand.substr(space+1);}// 压入返回地址sp -= 2;memory[sp] = (current_line + 1) & 0xFF;memory[sp + 1] = ((current_line + 1) >> 8) & 0xFF;try {int offset = parseImmediate1(operand);new_current_line = current_line + 1 + offset;} catch (...) {if (labels.count(operand)) {new_current_line = labels[operand];  // 修正拼写错误} else {// 使用图形界面提示错误MessageBox(GetHWnd(), ("CALL目标未找到: " + operand).c_str(), "VM错误", MB_ICONERROR);}}
}// 处理ret指令(支持立即数参数)
void RetInstruction(const string& line) {istringstream iss(line);string opcode, operand;iss >> opcode;  // 读取ret// 读取返回地址unsigned short return_addr = memory[sp] | (memory[sp + 1] << 8);sp += 2;// 处理带参数的ret(ret 4)if (iss >> operand) {int adjust = parseImmediate1(operand);sp += adjust;}new_current_line = return_addr;
}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 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 = false;
}void PreprocessLabels() {for (size_t i = 0; i < program_lines.size(); ++i) {std::string line = program_lines[i];std::istringstream iss(line);std::string address;if (iss >> address) {// 去除地址中的冒号address.erase(std::remove(address.begin(), address.end(), ':'), address.end());labels[address] = i;}size_t colonPos = line.find(':');if (colonPos!= std::string::npos) {std::string label = line.substr(0, colonPos);labels[label] = i;program_lines[i] = line.substr(colonPos + 1);//std::cout << "Label found: " << label << " at line " << i << std::endl;}}
}void IntInstruction(const std::string& line) {std::string processedLine = line;std::replace(processedLine.begin(), processedLine.end(), ',', ' ');std::istringstream iss(processedLine);std::string opcode, interrupt;iss >> opcode >> interrupt;BYTE keyState[256];if (interrupt == "0x10" || interrupt == "10h") {if (ah == 0x0E) {if (!graphicsInitialized) {initgraph(640, 480);HWND hwnd = GetHWnd();SetWindowPos(hwnd, HWND_TOP, 100, 100, 0, 0, SWP_NOSIZE);setbkcolor(BLACK);cleardevice();settextcolor(CYAN);settextstyle(16, 0, _T("Courier New Bold"));graphicsInitialized = true;outtextxy(textX, 0, "  VMwork BIOS (PCI)");outtextxy(textX, 16, "  This VGA/VBE BIOS is released under the GNU LGPL");settextcolor(RGB(192, 192, 192));}// 处理特殊字符if (al == 0x0D) {outtextxy(textX, textY, " ");textY += LINE_HEIGHT;}else if (al == 0x0A) {outtextxy(textX, textY, " ");textX = 0;}else {char str[2] = { static_cast<char>(al) };outtextxy(textX, textY, " ");outtextxy(textX, textY, str);UpdateTextPosition();outtextxy(textX, textY, "|");}}if (ah == 0x02 && bh == 0) {textX = 0;textY = 0;}if (ax == 0x0600 && bx == 0x0700 && cx == 0 && dx == 0x184f) {setfillcolor(BLACK);bar(0, 0, 640, 480);}}else if (interrupt == "0x16" || interrupt == "16h") {if (ah == 0) {bool consoleAllocated = false;if (!consoleAllocated) {  // 确保只创建一次控制台AllocConsole();freopen("CONIN$", "r", stdin);freopen("CONOUT$", "w", stdout);system("title VMwork控制和调试终端(在此输入键盘事件):");consoleAllocated = true;}INPUT_RECORD inputRec;DWORD eventsRead;while (true) {if (ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &inputRec, 1, &eventsRead)) {if (inputRec.EventType == KEY_EVENT && inputRec.Event.KeyEvent.bKeyDown) {// 使用系统API转换字符BYTE keyState[256];GetKeyboardState(keyState);WORD charCode = 0;ToAscii(inputRec.Event.KeyEvent.wVirtualKeyCode,inputRec.Event.KeyEvent.wVirtualScanCode,keyState,&charCode,0);al = LOBYTE(charCode);  // 低字节是ASCII码if (LOBYTE(charCode) == '\n') {al = 0x0D;}break;}}Sleep(10);}}
}else {printError(InstructionError::UNKNOWN_INTERRUPT, "警告:未知的中断号: " + interrupt);}
}void OrgInstruction(const std::string& line) {std::string processedLine = line;std::replace(processedLine.begin(), processedLine.end(), ',', ' ');std::istringstream iss(processedLine);std::string opcode, interrupt;iss >> opcode >> interrupt;if (interrupt == "0x7c00" || interrupt == "0x7C00") {org = 0x7c00;} else {printError(InstructionError::INVALID_OPERAND, "ORG指令的操作数无效: " + interrupt);}
}void TimesInstruction(const std::string& line) {std::string processedLine = line;std::replace(processedLine.begin(), processedLine.end(), ',', ' ');std::istringstream iss(processedLine);std::string opcode, interrupt;iss >> opcode >> interrupt;if (interrupt == "510-($-$$) db 0" || interrupt == "510-($-$$)") {end_times = 1;} else {printError(InstructionError::INVALID_OPERAND, "TIMES指令的操作数无效: " + interrupt);}
}void DwInstruction(const std::string& line) {std::string processedLine = line;std::replace(processedLine.begin(), processedLine.end(), ',', ' ');std::istringstream iss(processedLine);std::string opcode, interrupt;iss >> opcode >> interrupt;if (interrupt == "0xAA55" || interrupt == "0xaa55") {end_AA55 = 1;} else {printError(InstructionError::INVALID_OPERAND, "DW指令的操作数无效: " + interrupt);}
}void VM(const std::string& asmPath) {HWND hWnd = initgraph(640, 480, SHOWCONSOLE);SetWindowText(hWnd, "VMwork 虚拟机运行中");setbkcolor(BLACK);cleardevice();// 显示加载动画settextcolor(WHITE);settextstyle(24, 0, "宋体");outtextxy(50, 200, "正在启动虚拟机...");for (int i = 0; i < 10; ++i) {setfillcolor(HSVtoRGB(i*36, 1, 1));solidcircle(100 + i*50, 300, 15);Sleep(100);}cleardevice();std::ifstream file(asmPath);if (!file.is_open()) {std::cerr << "无法打开文件: " << asmPath << std::endl;return;}std::string line;while (std::getline(file, line)) {size_t commentPos = line.find(';');if (commentPos!= std::string::npos) {line = line.substr(0, commentPos);}// 去除行首尾的空白字符while (!line.empty() && std::isspace(line.front())) {line.erase(line.begin());}while (!line.empty() && std::isspace(line.back())) {line.erase(line.length() - 1);}if (!line.empty()) {program_lines.push_back(line);}}file.close();for (auto& progLine : program_lines) {for (size_t i = 0; i < progLine.size(); ++i) {if (i < progLine.size() - 2 && progLine[i] == '\'' && progLine[i + 1] ==' ' && progLine[i + 2] == '\'') {progLine[i] = static_cast<char>(0x20);progLine.erase(i + 1, 2);  // 移除后面的空格和单引号}if (i < progLine.size() - 2 && progLine[i] == '\'' && progLine[i + 1] ==':' && progLine[i + 2] == '\'') {progLine[i] = '3';progLine[i + 1] = 'A';progLine[i + 2] = 'h';}if (i < progLine.size() - 2 && progLine[i] == '\'' && progLine[i + 1] ==',' && progLine[i + 2] == '\'') {progLine[i] = '2';progLine[i + 1] = 'C';progLine[i + 2] = 'h';}if (i < progLine.size() - 2 && progLine[i] == '\'' && progLine[i + 1] =='_' && progLine[i + 2] == '\'') {progLine[i] = '5';progLine[i + 1] = 'F';progLine[i + 2] = 'h';}}}PreprocessLabels();// 重置指令指针和新的指令指针new_current_line = current_line;while (current_line < program_lines.size()) {std::istringstream iss(program_lines[current_line]);std::string opcode;iss >> opcode;if (opcode == "mov") MovInstruction(program_lines[current_line]);else if (opcode == "int") IntInstruction(program_lines[current_line]);else if (opcode == "org") OrgInstruction(program_lines[current_line]);else if (opcode == "times") TimesInstruction(program_lines[current_line]);else if (opcode == "dw") DwInstruction(program_lines[current_line]);else if (opcode == "cmp") CmpInstruction(program_lines[current_line]);else if (opcode == "jmp") {std::string label;iss >> label;// 处理相对跳转地址表示法,假设这里的相对跳转是相对于当前行号(根据实际情况调整)if (label.find("0x") == 0) {try {size_t targetAddress = std::stoi(label.substr(2), nullptr, 16);// 如果找到地址标签,更新当前行号if (labels.count(label)) {new_current_line = labels[label];} else {// 处理相对地址size_t relativeAddress = targetAddress - (current_line - labels.begin()->second);new_current_line = current_line + relativeAddress;}} catch (const std::invalid_argument& e) {printError(InstructionError::LABEL_NOT_FOUND, "JMP指令中的非法地址标签: " + label);} catch (const std::out_of_range& e) {printError(InstructionError::LABEL_NOT_FOUND, "JMP指令中的地址标签超出范围: " + label);}} else {JmpInstruction(program_lines[current_line]);}}else if (opcode == "je" || opcode == "jz") JeInstruction(program_lines[current_line]);else if (opcode == "jne" || opcode == "jnz") JneInstruction(program_lines[current_line]);else if (opcode == "push") PushInstruction(program_lines[current_line]);else if (opcode == "pop") PopInstruction(program_lines[current_line]);else if (opcode == "xor") XorInstruction(program_lines[current_line]);else if (opcode == "call") CallInstruction(program_lines[current_line]);else if (opcode == "add") AddInstruction(program_lines[current_line]);else if (opcode == "sub") SubInstruction(program_lines[current_line]);else if (opcode == "inc") IncInstruction(program_lines[current_line]);else if (opcode == "hlt") break;if (opcode == "jmp" || opcode == "je" || opcode == "jne") {current_line = new_current_line;}else {current_line++;}new_current_line = current_line + 1; }if (graphicsInitialized) {_getch();//closegraph();}settextcolor(LIGHTGRAY);outtextxy(100, 200, "虚拟机已安全停止");outtextxy(100, 240, "点击任意键返回管理器");FlushMouseMsgBuffer();while (!MouseHit()) Sleep(100);closegraph();
}int main() {if (GetSystemMetrics(SM_CLEANBOOT) != 0) {MessageBox(NULL, "系统处于安全模式,无法启动虚拟机", "启动错误", MB_ICONSTOP);return 1;}// 设置当前目录if (!SetCurrentDirectoryA(GetCurrentDirectoryPath().c_str())) {MessageBox(NULL, "无法设置工作目录", "路径错误", MB_ICONERROR);return 1;}// 设置当前工作目录SetCurrentDirectoryA(GetCurrentDirectoryPath().c_str());// 初始化图形界面(直接初始化)initgraph(WIDTH, HEIGHT);HWND hWnd = GetHWnd();SetWindowText(hWnd, "VMwork 虚拟机管理器");ShowWindow(hWnd, SW_SHOWNORMAL);// 检查必要组件if (!PathFileExistsA("ndisasm.exe") || !PathFileExistsA("toasm.exe")) {MessageBox(hWnd, "缺少必要组件:ndisasm.exe 或 toasm.exe", "启动错误", MB_ICONERROR);return 1;}// 加载配置try {LoadConfig();} catch (...) {ShowErrorDialog("配置文件加载失败");}// 主循环MainLoop();// 保存配置SaveConfig();closegraph();return 0;
}

这样就可以让用户选择img和asm了

为程序加一个ico

ico.rc

1 ICON "VMwork.ico" 

toasm.py

import re
import sys
import chardetdef process_files(input_file_path, output_file_path):# 探测原始文件的编码with open(input_file_path, 'rb') as f:result = chardet.detect(f.read())encoding = result['encoding']pattern = re.compile(r'^([0-9A-Fa-f]{8})\s+([0-9A-Fa-f ]+)\s+(.*)$')with open(input_file_path, 'r', encoding=encoding) as input_file, open(output_file_path, 'w',encoding='utf - 8') as output_file:for line in input_file:line = line.rstrip()if match := pattern.match(line):addr_str, _, instr = match.groups()addr = int(addr_str, 16)output_file.write(f"0x{addr:x}:\n")output_file.write(f"{instr}\n")else:output_file.write(line + "\n")if __name__ == "__main__":if len(sys.argv)!= 3:print("Usage: python script_name.py input_file output_file")sys.exit(1)input_file_path = sys.argv[1]output_file_path = sys.argv[2]process_files(input_file_path, output_file_path)

 

 

写一个makefile

all:make icomake toasmcopy .\dist\toasm.exe .\make VMwork
VMwork:g++ -o VMwork main.cpp ico.res -std=c++11 -leasyx -lcomdlg32 -lshlwapi -lmsimg32 -mwindows -static-libgcc -static-libstdc++
ico:windres -O coff -o ico.res ico.rc
toasm:Pyinstaller -F toasm.py

这样就可以编译整个项目:

make

顺带写一个README.md

###(c) 2025 Lin Honghan# VMwork Virtual Machine Manager## 📖 中文说明### 项目简介
VMwork 是一款基于Windows的虚拟机模拟器,提供图形化界面管理,支持运行汇编程序(.asm)和软盘镜像(.img)。模拟BIOS中断调用,实现基本的显示和输入功能。### 主要功能
- 🖥️ 图形界面管理虚拟机配置
- ⚙️ 支持汇编源码直接运行
- 💾 可加载/反编译.img软盘镜像
- ⌨️ 模拟BIOS键盘中断(INT 16h)
- 📺 模拟文本模式显示(INT 10h)
- 🔄 历史配置自动保存
- 🎨 彩色控制台输出支持### 运行要求
- Windows 7+ (或Linux)
- C/C++ 运行时库
- 管理员权限(部分功能需要)### 安装使用
1. 下载最新Release包
2. 解压到英文路径(避免空格)
3. 确保包含以下文件:- `VMwork.exe`- `ndisasm.exe`- `toasm.exe`
4. 双击运行`VMwork.exe`### 使用说明
1. **新建虚拟机**  - 选择.asm或.img文件- 输入虚拟机名称- 自动保存配置2. **运行虚拟机**  - 从列表选择配置- 进入全屏模拟模式- 按任意键返回管理器3. **键盘输入**  - 专用控制台窗口接收输入- 支持Shift/Caps Lock状态- Esc键退出程序### 注意事项
⚠️ 系统安全模式下不可用  
⚠️ 路径不要包含中文或空格  
⚠️ 杀毒软件可能误报(添加信任)  
⚠️ 需要保留同目录工具程序### 代码结构
main.cpp
├── GUI/ # 图形界面模块├── VM/ # 虚拟机核心│ ├── BIOS/ # 中断模拟│ └── Parser/ # 指令解析├── config/ # 配置管理└── tools/ # 反编译工具### 问题反馈
提交Issue至[项目仓库](https://github.com/linhhanpy/VMwork)  
或联系:lhh_88888888@qq.com---## 📖 English Documentation### Project Overview
VMwork is a Windows-based virtual machine emulator with GUI management. Supports running assembly programs (.asm) and floppy disk images (.img), emulating BIOS interrupts for basic display and input operations.### Key Features
- 🖥️ Graphical VM Configuration Management
- ⚙️ Direct Assembly Source Execution
- 💾 .IMG Floppy Image Loading/Disassembly
- ⌨️ BIOS Keyboard Interrupt Simulation (INT 16h)
- 📺 Text Mode Display Emulation (INT 10h)
- 🔄 Automatic Configuration Saving
- 🎨 Color Console Output Support### System Requirements
- Windows 7+ (or Linux)
- C/C++ Redistributable
- Administrator Privileges (for certain features)### Installation
1. Download latest Release package
2. Extract to English path (no spaces)
3. Verify required files:- `VMwork.exe`- `ndisasm.exe`- `toasm.exe`
4. Double-click `VMwork.exe`### Quick Start
1. **Create VM**  - Select .asm/.img file- Name your VM- Config auto-saves2. **Run VM**  - Select from config list- Enter full emulation mode- Press any key to return3. **Keyboard Input**  - Dedicated console window- Supports Shift/Caps Lock states- Esc to exit program### Important Notes
⚠️ Not compatible with Safe Mode  
⚠️ Use ASCII-only paths  
⚠️ Add exclusion in antivirus  
⚠️ Keep tool files in same directory### Code Structure
main.cpp├── GUI/ # Graphical Interface├── VM/ # VM Core│ ├── BIOS/ # Interrupt Emulation│ └── Parser/ # Instruction Parsing├── config/ # Configuration└── tools/ # Disassembly Tools

放几张效果图

 

 

 

此时的目录

 

相关文章:

自制虚拟机(C/C++)(三、做成标准GUI Windows软件,扩展指令集,直接支持img软盘)

开源地址:VMwork 要使终端不弹出&#xff0c; #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") 还要实现jmp near 0x01类似的 本次的main.cpp #include <graphics.h> #include <conio.h> #include <windows.h> #includ…...

算法题(56):旋转链表

审题&#xff1a; 我们需要根据k的大小把链表向右移动对应次数&#xff0c;并返回移动后的链表的头结点指针 思路&#xff1a; 根据提示中的数据大小我们发现&#xff1a;k的值可以远大于节点数。 也就是说我们对链表的操作存在周期&#xff0c;如果k%len0&#xff0c;说明我们…...

解决PyG安装中torch-sparse安装失败问题:详细指南

1 问题描述 最近在学习GNN&#xff0c;需要使用PyTorch Geometric&#xff08;PyG&#xff09;库。在安装PyG的过程中&#xff0c;遇到了torch-sparse安装失败的问题&#xff0c;错误提示为&#xff1a; ERROR: Failed building wheel for torch-sparse本文将详细记录问题的解…...

如何创建折叠式Title

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了SliverGrid组件相关的内容&#xff0c;本章回中将介绍SliverAppBar组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 我们在本章回中介绍的SliverAppBar和普通的AppBar类似&#xff0c;它们的…...

go-zero学习笔记(三)

利用goctl生成rpc服务 编写proto文件 // 声明 proto 使用的语法版本 syntax "proto3";// proto 包名 package demoRpc;// golang 包名(可选) option go_package "./demo";// 如需为 .proto 文件添加注释&#xff0c;请使用 C/C 样式的 // 和 /* ... */…...

Wildcard工具详解:从入门到精通

1. Wildcard基础知识 什么是Wildcard&#xff1f; Wildcard&#xff08;通配符&#xff09;是一种用于匹配文件名或字符串的特殊字符。它允许用户使用简单的符号来表示复杂的匹配规则&#xff0c;从而快速定位目标文件或数据。 常见的Wildcard符号 *&#xff1a;匹配任意数量…...

冰蝎v3.0 beta7来啦

我用了一台kali&#xff0c;一台centos&#xff0c;一台windows&#xff0c;做了一个文件上传和一个反弹shell实验&#xff0c;载荷是AES加密的&#xff0c;终于感受到了对加密流量的无可奈何~ kali&#xff08;php8.1&#xff09;centos&#xff08;php7.1&#xff09;window…...

React中使用箭头函数定义事件处理程序

React中使用箭头函数定义事件处理程序 为什么使用箭头函数&#xff1f;1. 传递动态参数2. 避免闭包问题3. 确保每个方块的事件处理程序是独立的4. 代码可读性和维护性 示例代码总结 在React开发中&#xff0c;处理事件是一个常见的任务。特别是当我们需要传递动态参数时&#x…...

记忆化搜索和动态规划 --最长回文子串为例

记忆化搜索 记忆化搜索是一种优化递归算法的方法&#xff0c;通过将已经计算过的子问题的结果存储起来&#xff08;通常使用哈希表或数组&#xff09;&#xff0c;避免重复计算相同的子问题。 本质上是通过缓存中间结果来减少计算的重复性。 动态规划 动态规划是通过将问题分…...

Tree Compass( Codeforces Round 934 (Div. 2) )

Tree Compass&#xff08; Codeforces Round 934 (Div. 2) &#xff09; You are given a tree with n n n vertices numbered 1 , 2 , … , n 1, 2, \ldots, n 1,2,…,n. Initially, all vertices are colored white. You can perform the following two-step operation: …...

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.17 掩码数组:缺失值处理的优雅方案

2.17 掩码数组&#xff1a;缺失值处理的优雅方案 目录 #mermaid-svg-12vjJJbyudPnkYBO {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-12vjJJbyudPnkYBO .error-icon{fill:#552222;}#mermaid-svg-12vjJJbyudPnkYBO…...

PHP 常用函数2025.02

PHP implode() 函数 语法 implode(separator,array) 参数描述separator可选。规定数组元素之间放置的内容。默认是 ""&#xff08;空字符串&#xff09;。array必需。要组合为字符串的数组。 技术细节 返回值&#xff1a;返回一个由数组元素组合成的字符串。PHP 版…...

react中如何获取dom元素

实现代码 const inputRef useRef(null) inputRef.current.focus()...

【C++】继承(下)

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解C的继承&#xff08;下&#xff09;&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 5.继承与友元6.继承与静态成员7.复杂的菱形继承及菱形虚拟继承8.继…...

C语言实现字符串排序:从代码到原理深度解析

在编程的世界里&#xff0c;字符串处理是一项基础且重要的技能。今天&#xff0c;我们通过分析一段C语言代码来深入了解如何对字符串进行排序。 一、代码呈现 #include <stdio.h> #include <string.h> int main() { char s[1001]; scanf("%s", s); int…...

Vue3的el-table-column下拉输入实时查询API数据选择的实现方法

由于本人对el-table-column有下拉输入选择的要求&#xff0c;根据网上搜索的资料及本人优化&#xff0c;推出我比较满意的方法&#xff0c;供各位读者参考使用。 效果图 el-table-column写法 <el-table-columnlabel"货品编号"align"center"prop"…...

【数据结构】_链表经典算法OJ:复杂链表的复制

目录 1. 题目链接及描述 2. 解题思路 3. 程序 1. 题目链接及描述 题目链接&#xff1a;138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;…...

Vue 图片引用方式详解:静态资源与动态路径访问

目录 前言1. 引用 public/ 目录2. assets/ 目录3. 远程服务器4. Vue Router 动态访问5. 总结6. 扩展&#xff08;图片不显示&#xff09; 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 在 Vue 开发中&#x…...

chatGPT写的网页版贪吃蛇小游戏

chatGPT写的网页版贪吃蛇小游戏 前言网页版贪吃蛇小游戏 前言 之前无聊&#xff0c;让ChatGPT写了一段基于html语言的贪吃蛇小游戏代码 网页版贪吃蛇小游戏 将以下内容复制到记事本&#xff0c;重命名为xxx.html即可打开浏览器游玩 这里是一个使用HTML、CSS和JavaScript编写…...

Python量化交易助手:xtquant的安装与应用

Python量化交易助手&#xff1a;xtquant的安装与应用 技术背景和应用场景 在量化交易领域&#xff0c;Python因其强大的库支持和灵活性成为了许多开发者的首选语言。其中&#xff0c;xtquant 是迅投官方开发的一个Python包&#xff0c;专门用于与miniqmt通信&#xff0c;实现…...

前缀和算法

文章目录 算法总览题目1371.每个元音包含偶数次的最长子字符串 算法总览 题目 1371.每个元音包含偶数次的最长子字符串 1371.每个元音包含偶数次的最长子字符串 参考博主的讲解 思路分析&#xff1a;就是得使用前缀和记录情况&#xff0c;dp[i][j]表示s[0] 到s[i] 中&…...

Qt常用控件 输入类控件

文章目录 1.QLineEdit1.1 常用属性1.2 常用信号1.3 例子1&#xff0c;录入用户信息1.4 例子2&#xff0c;正则验证手机号1.5 例子3&#xff0c;验证输入的密码1.6 例子4&#xff0c;显示密码 2. QTextEdit2.1 常用属性2.2 常用信号2.3 例子1&#xff0c;获取输入框的内容2.4 例…...

《最小阻力之路》关于愿景的理解和思考

一、愿景的形成机制 1. 愿景的三层来源 来源层级形成机制案例潜在偏差风险① 本能冲动层对快感/痛苦的即时反应"想暴富"源于缺钱焦虑易被短期情绪劫持② 社会镜像层内化外界标准&#xff08;家庭/社会/文化&#xff09;"必须考研"因家人期待混淆他人需求…...

Ubuntu 22.04系统安装部署Kubernetes v1.29.13集群

Ubuntu 22.04系统安装部署Kubernetes v1.29.13集群 简介Kubernetes 的工作流程概述Kubernetes v1.29.13 版本Ubuntu 22.04 系统安装部署 Kubernetes v1.29.13 集群 1 环境准备1.1 集群IP规划1.2 初始化步骤&#xff08;各个节点都需执行&#xff09;1.2.1 主机名与IP地址解析1.…...

虚幻基础17:动画层接口

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 animation layer interface animation layer interface 动画层接口&#xff1a;动画图表的集。仅有名字。 添加到动画蓝图中&#xff0c;由动画蓝图实现动画图表。...

无人机PX4飞控 | PX4源码添加自定义uORB消息并保存到日志

PX4源码添加自定义uORB消息并保存到日志 0 前言 PX4的内部通信机制主要依赖于uORB&#xff08;Micro Object Request Broker&#xff09;&#xff0c;这是一种跨进程的通信机制&#xff0c;一种轻量级的中间件&#xff0c;用于在PX4飞控系统的各个模块之间进行高效的数据交换…...

HTMLCSS :下雪了

这段代码创建了一个动态的雪花飘落加载动画&#xff0c;通过 CSS 技术实现了雪花的下落和消失效果&#xff0c;为页面添加了视觉吸引力和动态感。 大家复制代码时&#xff0c;可能会因格式转换出现错乱&#xff0c;导致样式失效。建议先少量复制代码进行测试&#xff0c;若未能…...

如何处理 Typecho Joe 主题被抄袭或盗版的问题

在开源社区中&#xff0c;版权保护是一个非常重要的话题。如果你发现自己的主题&#xff08;如 Joe 主题&#xff09;被其他主题&#xff08;如子比主题&#xff09;抄袭或盗版&#xff0c;你可以采取以下措施来维护自己的权益。 一、确认侵权行为 在采取任何行动之前&#xf…...

利用Vue和javascript分别编写一个“Hello World”的定时更新

目录 一、利用Vue编写一个“Hello World”的定时更新&#xff08;1&#xff09;vue编码在Html文件中&#xff08;2&#xff09;vue编码在js文件中 二、利用javascript编写一个“Hello World”的定时更新 一、利用Vue编写一个“Hello World”的定时更新 &#xff08;1&#xff…...

volatile变量需要减少读取次数吗

问题说明 本人在前期读Netty源码时看到这样一段源码和注释&#xff1a; private boolean invokeHandler() {// Store in local variable to reduce volatile reads.int handlerState this.handlerState;return handlerState ADD_COMPLETE || (!ordered && handlerS…...