您现在的位置是:首页 >技术杂谈 >自制虚拟机(C/C++)(三、做成标准GUI Windows软件,扩展指令集,直接支持img软盘)网站首页技术杂谈
自制虚拟机(C/C++)(三、做成标准GUI Windows软件,扩展指令集,直接支持img软盘)
简介用c++制作windows xp 虚拟机
开源地址: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) *.img All Files (*.*) *.* ";
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语法?
[否]则以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) *.asm All Files (*.*) *.* " :
"IMG Files (*.img) *.img All Files (*.*) *.* ";
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 = '