⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simplecpudlg.cpp

📁 一个简易的CPU模拟程序
💻 CPP
字号:
// SimpleCPUDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "SimpleCPU.h"
#include "SimpleCPUDlg.h"
#include ".\SimpleCPUdlg.h"
#include "EditDlg.h"
#include "SetDlg.h"
#include<stdlib.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

enum {PC,AR,ABUS,MEMORY,DBUS,DR,IR,TRAN,CONTROL,ALU,ACC};


// CSimpleCPUDlg 对话框


CSimpleCPUDlg::CSimpleCPUDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CSimpleCPUDlg::IDD, pParent)
	, IntPC(0)
	, IntAR(0)
	, IntACC(0)
	, pLastStat(NULL)
{
	SubStep=0;
	ProStart=false;
	InsStart=false;
	pauseflag=false;
	Mode=1;
	TimeDis=1000;
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_Brush.CreateSolidBrush(RGB(255,255,255));
	m_Bitmap.LoadBitmap(IDC_CPUBIT);
}

void CSimpleCPUDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDE_PC, StatPC);
	DDX_Control(pDX, IDE_AR, StatAR);
	DDX_Control(pDX, IDE_DR, StatDR);
	DDX_Control(pDX, IDE_IR, StatIR);
	DDX_Control(pDX, IDE_TRANSLATE, StatTranslate);
	DDX_Control(pDX, IDE_CONTROL, StatControl);
	DDX_Control(pDX, IDE_ALU, StatALU);
	DDX_Control(pDX, IDE_ACC, StatACC);
	DDX_Control(pDX, IDC_MEMORY, MemoryCtrl);
	DDX_Control(pDX, IDE_ABUS, StatABUS);
	DDX_Control(pDX, IDE_DBUS, StatDBUS);
}

BEGIN_MESSAGE_MAP(CSimpleCPUDlg, CDialog)
	ON_WM_SYSCOMMAND()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_NEXTSTEP, OnBnClickedNextstep)
	ON_WM_CTLCOLOR()
	ON_WM_ERASEBKGND()
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_EDITCODE, OnBnClickedEditcode)
	ON_BN_CLICKED(IDC_SET, OnBnClickedSet)
	ON_BN_CLICKED(IDC_START, OnBnClickedStart)
	ON_BN_CLICKED(IDC_PAUSE, OnBnClickedPause)
	ON_BN_CLICKED(IDC_IMFOR, OnBnClickedImfor)
END_MESSAGE_MAP()


// CSimpleCPUDlg 消息处理程序
const OPERFN CSimpleCPUDlg::SubStep1[]={
		ComPC,
		ComAR,
		ComABUS,
		ComMemory,
		ComDBUS,
		ComDR,
		ComIR,
		ComTran,
		ComControl,
		ComALU,
		ComACC
};

BOOL CSimpleCPUDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 将\“关于...\”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	MemoryCtrl.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT);
	LV_COLUMN lv;
	lv.mask=LVCF_TEXT|LVCF_FMT|LVCF_WIDTH;
	lv.pszText="地址";
	lv.fmt=LVCFMT_LEFT;
	lv.cx=50;
	MemoryCtrl.InsertColumn(0,&lv);
	lv.pszText="代码";
	lv.cx=120;
	MemoryCtrl.InsertColumn(1,&lv);
	MemoryCtrl.SetBkColor(RGB(255,255,255));
	HBITMAP hbmp;
	for(int i=0;i<6;i++)
	{
		m_button[i].LoadBitmap(IDB_BITMAP1+i);
		hbmp=(HBITMAP)m_button[i].GetSafeHandle();
		((CButton*)GetDlgItem(IDC_NEXTSTEP+i))->SetBitmap(hbmp);
	}
	return TRUE;  // 除非设置了控件的焦点,否则返回 TRUE
}

void CSimpleCPUDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	CDialog::OnSysCommand(nID, lParam);
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CSimpleCPUDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标显示。
HCURSOR CSimpleCPUDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}
void CSimpleCPUDlg::OnBnClickedNextstep()
{
	//(this->*fn[0])();
	if(!ProStart)
	{
		AfxMessageBox("程序已经运行完,请按“运行”重新运行");
		return;
	}
	if(InstructList.size()==0)
	{
		AfxMessageBox("没有程序导入,请先按“编辑代码”按钮编辑导入代码");
		ProStart=false;
		return;
	}
	if(pauseflag)OnBnClickedPause();
	SetTimer(1,TimeDis,0);
	InsStart=true;
}
void CSimpleCPUDlg::OnBnClickedEditcode()
{
	CEditDlg dlg(InstructList);
	if(dlg.DoModal()==IDOK)
	{
		InstructList=dlg.InstructList;
		LoadMemory();
		ReLoad();
		ProStart=false;
	}
}

HBRUSH CSimpleCPUDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	if(nCtlColor==CTLCOLOR_STATIC)
	{
		pDC->SetBkColor(RGB(255,255,255));
		return (HBRUSH)m_Brush;
	}
	return hbr;
}

BOOL CSimpleCPUDlg::OnEraseBkgnd(CDC* pDC)
{
	if (m_Bitmap.m_hObject!=NULL) // 对象句柄非空 
	{ 
		CDC MemDC; 
		BITMAP bm; 
		CRect Rect; 
		int x=0, y=0; 
		GetClientRect (&Rect); // 获取客户区大小 
		m_Bitmap.GetObject (sizeof (BITMAP),&bm); // 用位图上的信息 填充 BITMAP 结构的各个域 
		MemDC.CreateCompatibleDC (pDC); // 初始化内存描述对象 
		CBitmap*pOldBitmap=MemDC.SelectObject (&m_Bitmap); // 定 义一个 CBITMAP 类,并初始化为选入到设备描述对象的位图 

		pDC->BitBlt(x,y,bm.bmWidth,bm.bmHeight,&MemDC,0,0,SRCCOPY);
		MemDC.SelectObject ( pOldBitmap ); // 将位图对象选入 
		return TRUE; 
	} 
	else return CDialog::OnEraseBkgnd (pDC); 
}

void CSimpleCPUDlg::OnTimer(UINT nIDEvent)
{
	(this->*SubStep1[SubStep])();
	if(Mode==0 || Mode==1&&!InsStart|| !ProStart)	
		KillTimer(1);
	CDialog::OnTimer(nIDEvent);
}

void CSimpleCPUDlg::LoadMemory(void)
{
	MemoryCtrl.DeleteAllItems();
	int length=InstructList.size();
	CString ins;
	char num[20];
	for(int index=0;index<length;index++)
	{
		itoa(index,num,10);
		MemoryCtrl.InsertItem(index,num);
		ins=InstructList[index].instruct;
		MemoryCtrl.SetItemText(index,1,ins);
	}
}

void CSimpleCPUDlg::SetLastHide(void)
{
	if(pLastStat)
	{
		pLastStat->Show(false);
		pLastStat->Invalidate();
	}
}


void CSimpleCPUDlg::ComPC(void)
{
	char num[20];
	SetLastHide();
	if(pLastStat==&StatAR)
	{
		IntPC++;
		SubStep=ABUS;
	}
	else if(pLastStat==&StatIR)
	{
		IntPC=InstructList[IntAR].data;
		SubStep=PC;
		InsStart=false;
	}
	else 
		SubStep=AR;	
	itoa(IntPC,num,10);
	StatPC.Show();
	StatPC.SetWindowText(num);
	pLastStat=&StatPC;
}

void CSimpleCPUDlg::ComAR(void)
{
	char num[20];
	SetLastHide();
	if(pLastStat==&StatPC)
	{
		IntAR=IntPC;
		SubStep=PC;
	}
	else if(pLastStat==&StatIR)
	{
		IntAR=InstructList[IntAR].data;
		SubStep=ABUS;
	}
	itoa(IntAR,num,10);
	StatAR.Show();
	StatAR.SetWindowText(num);
	pLastStat=&StatAR;
}

void CSimpleCPUDlg::ComABUS(void)
{
	SetLastHide();
	StatABUS.Show();
	StatABUS.Invalidate();
	SubStep=MEMORY;
	pLastStat=&StatABUS;
}
void CSimpleCPUDlg::ComMemory(void)
{
	char num[20];
	CString instruct="DB ";
	SetLastHide();
	MemoryCtrl.SetFocus();
	MemoryCtrl.SetItemState(-1,0,LVIS_SELECTED);
	MemoryCtrl.SetItemState(IntAR,LVIS_SELECTED,LVIS_SELECTED );
	MemoryCtrl.EnsureVisible(IntAR,FALSE);
	if(pLastStat==&StatDBUS)
	{
		InstructList[IntAR].data=IntACC;
		itoa(IntACC,num,10);
		instruct+=num;
		InstructList[IntAR].instruct=instruct;
		MemoryCtrl.SetItemText(IntAR,1,instruct);
		SubStep=PC;
		InsStart=false;
	}
	else if(pLastStat==&StatABUS)
	{
		if(InstructList[IntAR].oper==DB
			&&InstructList[IntPC-1].oper==STA)
				SubStep=ACC;
		else SubStep=DBUS;
	}
	pLastStat=NULL;
}
void CSimpleCPUDlg::ComDBUS(void)
{
	SetLastHide();
	StatDBUS.Show();
	StatDBUS.Invalidate();
	if(pLastStat==&StatDR)SubStep=MEMORY;
	else	SubStep=DR;
	pLastStat=&StatDBUS;
}
void CSimpleCPUDlg::ComDR(void)
{
	SetLastHide();
	StatDR.Show();
	char num[20];
	if(pLastStat==&StatDBUS)
	{
		if(InstructList[IntAR].oper==DB)
			SubStep=ALU;
		else SubStep=IR;
		CString str=InstructList[IntAR].instruct;
		StatDR.SetWindowText(str);
	}
	else
	{
		SubStep=DBUS;
		itoa(IntACC,num,10);
		StatDR.SetWindowText(num);
	}
	pLastStat=&StatDR;
}

void CSimpleCPUDlg::ComIR(void)
{
	SetLastHide();
	StatIR.Show();
	if(pLastStat==&StatDR)
	{
		SubStep=TRAN;
		CString str=InstructList[IntAR].instruct;
		StatIR.SetWindowText(str);
	}
	else
	{
		if(InstructList[IntAR].oper==JMP)
			SubStep=PC;
		else SubStep=AR;
		StatIR.Invalidate();
	}
	pLastStat=&StatIR;
}

void CSimpleCPUDlg::ComTran(void)
{
	SetLastHide();
	StatTranslate.Show();
	StatTranslate.Invalidate();
	SubStep=CONTROL;
	pLastStat=&StatTranslate;
}

void CSimpleCPUDlg::ComControl(void)
{
	Instruction InsCode=InstructList[IntAR];
	if(InsCode.addr||InsCode.oper==JMP)
		SubStep=IR;
	else SubStep=ALU;
	SetLastHide();
	StatControl.Show();
	StatControl.Invalidate();
	pLastStat=&StatControl;
}

void CSimpleCPUDlg::ComALU(void)
{
	Instruction InsCode=InstructList[IntPC-1];
	SubStep=ACC;
	switch(InsCode.oper)
	{
	case ADD:
		if(InsCode.addr)
			IntACC+=InstructList[IntAR].data;
		else IntACC+=InsCode.data;
		break;
	case SUB:
		if(InsCode.addr)
			IntACC-=InstructList[IntAR].data;
		else IntACC-=InsCode.data;
		break;
	case MUL:
		if(InsCode.addr)
			IntACC*=InstructList[IntAR].data;
		else IntACC*=InsCode.data;
		break;
	case DIV:
		if(InsCode.addr)
			IntACC/=InstructList[IntAR].data;
		else IntACC/=InsCode.data;
		break;
	case LOD:
		IntACC=InstructList[IntAR].data;
		break;
	case HALT:
		ProStart=false;
		SubStep=PC;
		break;
	case NOP:
		InsStart=false;
		SubStep=PC;
		break;
	}
	SetLastHide();
	StatALU.Show();
	StatALU.Invalidate();
	pLastStat=&StatALU;
}

void CSimpleCPUDlg::ComACC(void)
{
	char num[20];
	itoa(IntACC,num,10);
	SetLastHide();
	StatACC.Show();
	StatACC.SetWindowText(num);
	if(!pLastStat)
	{
		SubStep=DR;
	}
	else 
	{
		SubStep=PC;
		InsStart=false;
	}
	pLastStat=&StatACC;
}

void CSimpleCPUDlg::OnBnClickedSet()
{
	OnBnClickedPause();
	CSetDlg dlg(Mode,TimeDis);
	dlg.DoModal();
}

void CSimpleCPUDlg::ReLoad(void)
{
	IntPC=0;
	IntAR=0;
	IntACC=0;
	StatPC.SetWindowText("PC");
	StatAR.SetWindowText("AR");
	StatDR.SetWindowText("DR");
	StatIR.SetWindowText("IR");
	StatACC.SetWindowText("ACC");
}

void CSimpleCPUDlg::OnBnClickedStart()
{
	ReLoad();
	ProStart=true;
	OnBnClickedNextstep();
}

void CSimpleCPUDlg::OnBnClickedPause()
{
	if(!ProStart)return;
	m_button[5].DeleteObject();
	if(!pauseflag)
	{
		KillTimer(1);
		m_button[5].LoadBitmap(IDB_BITMAP7);
		pauseflag=true;
	}
	else
	{
		SetTimer(1,TimeDis,0);
		m_button[5].LoadBitmap(IDB_BITMAP6);
		pauseflag=false;
	}
	HBITMAP hbmp=(HBITMAP)m_button[5].GetSafeHandle();
	((CButton*)GetDlgItem(IDC_PAUSE))->SetBitmap(hbmp);
}
void CSimpleCPUDlg::OnBnClickedImfor()
{
	ShellExecute(0,NULL,"设计报告.chm", NULL,NULL, SW_NORMAL);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -