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

📄 hmdlg.cpp

📁 本软件实现了汇编语言级虚拟机的模拟
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// HMDlg.cpp : implementation file
//

#include "stdafx.h"
#include "HM.h"
#include "HMDlg.h"
#include "misc.h"
#include "INS.h"
#include "EDIT.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
char* temp;
char* xh;
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();
    
// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHMDlg dialog

CHMDlg::CHMDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CHMDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CHMDlg)
	m_ac = _T("00000000");
	m_ar = _T("00000000");
	m_c = 0;
	m_doc = _T("");
	m_ir = _T("00000000");
	m_length = 0;
	m_p = 0;
	m_pc = _T("00000000");
	m_z = 0;
	m_show_edit = _T("");
	m_out = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CHMDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CHMDlg)
	DDX_Control(pDX, IDC_LIST2, m_list);
	DDX_Text(pDX, IDC_ac, m_ac);
	DDX_Text(pDX, IDC_ar, m_ar);
	DDX_Text(pDX, IDC_C, m_c);
	DDX_Text(pDX, IDC_DOC, m_doc);
	DDX_Text(pDX, IDC_ir, m_ir);
	DDX_Text(pDX, IDC_LENGTH, m_length);
	DDX_Text(pDX, IDC_P, m_p);
	DDX_Text(pDX, IDC_pc, m_pc);
	DDX_Text(pDX, IDC_Z, m_z);
	DDX_Text(pDX, IDC_show_edit, m_show_edit);
	DDX_Text(pDX, IDC_OUT, m_out);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CHMDlg, CDialog)
	//{{AFX_MSG_MAP(CHMDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BEGIN, OnBegin)
	ON_BN_CLICKED(IDC_OPEN, OnOpen)
	ON_BN_CLICKED(IDC_NEXT, OnNext)
	ON_BN_CLICKED(IDC_CALLDOS, OnCalldos)
	ON_COMMAND(ID_OPENS, OnOpens)
	ON_COMMAND(ID_OWNER, OnOwner)
	ON_COMMAND(ID_EDIT, OnEdit)
	ON_COMMAND(ID_HELP, OnHelp)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHMDlg message handlers

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

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	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);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	CheckRadioButton(IDC_CONTINUE,IDC_ODD,IDC_CONTINUE);
	CheckRadioButton(IDC_TRACE,IDC_COMMON,IDC_TRACE);
	UpdateData(false);
    m_list.InsertColumn(0,"地址",LVCFMT_CENTER,40);
	m_list.InsertColumn(1,"内容",LVCFMT_CENTER,60);
	CString tmp_str;
	char string2[9];
	for(int i=0;i<256;i++)
	{
		//写入列表
	itx(i,string2);
	tmp_str=string2;
	m_list.InsertItem(i,tmp_str);
	itx(0,string2);
    tmp_str=string2;
	m_list.SetItemText(i,1,tmp_str);
	}
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CHMDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CHMDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		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;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CHMDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}
void CHMDlg::itb(int a)
{
	int number=a; 
    int loop;
	for (loop=7; loop>=0; loop--) 
	{ 
		bits[loop] = (number % 2)+'0'; 
		number /= 2; 
	}
	bits[8]='\0'; 
}
void CHMDlg::AS(char *sourcename, bool &opening) 
{ 
    int i; 
	opening=true;
    strcpy(srcfile, sourcename); 
    src = fopen(sourcename, "r"); 
    if (src == NULL) { 
    opening=false; 
    } 
    //符号表内的符号名全部初始为 '????????' 
	if(opening)
    for (i = 0; i < SYMTABLEN; i++) 
strcpy(symtabhdr[i].symname, "???????"); 
} 

/**************************************************** 
 * 汇编器的析构函数~AS: 关闭源文件 
 *****************************************************/ 
void CHMDlg::AAS() 
{ 
    if (src) { 
fclose(src); 
    } 
    src = NULL; 
} 

/***************************************************** 
  assemble 
  汇编函数 
  2遍扫描源程序,构造符号表,汇编成机器指令 
****************************************************/ 
bool CHMDlg::assemble(bool & errors) 
{ 
    char word1[9];
	MC_bytes lc = 0; // 地址计数器 
    MC_bytes op; 
    int number; 
	int i;
    tokentype tokencat; // 记号类别 
    int labelidx; // 标号在符号表内的序号 
    char words[10]; 
    char tpwords[15]; 
    MC_opcodes opcode; 
    int errpass1 = 0; 

    m_show_edit+="\r\n进行第1遍扫描……\r\n"; 
    mksymtab(errpass1); // 进行第1遍扫描,以建立标号的符号表 
    fclose(src); 
    src = NULL; // 关闭输入流,完成第1遍扫描,准备第2遍扫描 
    if (errpass1 > 0) { 
    m_show_edit+="\r\n第一次扫描错误个数: ";
    itoa(errpass1,word1,10); 
    m_show_edit+=word1;
     return false;
    } 
	m_show_edit+="\r\n第一遍扫描完成!";
    m_show_edit+="\r\n进行第2遍扫描……\r\n"; 
   src = fopen(srcfile, "r"); // 重新打开输入流,以进行第2遍扫描 
    if (src == NULL) { 
	m_show_edit+="\r\n不能打开文档";
       return false; 
    } 

    for (i = 0; i <= MEMSIZE - 1; i++) // 将处理机的内存初始为无效代码 MC_bad 
mem[i] = MC_bad; 
    lc = 0; // 地址计数器清0 
    errors = false; // errors保存在第2遍扫描过程的错误状态 

    /* 
  开始第2遍扫描,结合第1遍扫描生成的符号表,将输入的汇编源程序汇编成机器指令, 
  将其存入到Machine的mem中 
*/ 
    while (!feof(src)) { 
tokencat = lex(words, opcode); //读入一个单词,取得单词的类别及相关信息
/*#ifdef DEBUG 
printf("(%2d) %d %-8s\n", opcode != MAXINSTUCTION ? opcode : -1, 
   tokencat, words); 
#endif */
switch (tokencat) { 
case ASMCODE: //汇编指令处理 
            // 为什么在这里还要查询汇编指令。不是已经在lex中的opcode得到了吗? 
	op=opcoded(words); // 查询汇编指令代表的机器指令 
if (op == MC_bad) // 不识别的汇编指令,设置错误标志 
{ 
m_show_edit+="\r\n";
 m_show_edit+=words;
 m_show_edit+="不识别的汇编指令:";
	 itoa(lc,word1,10); 
	 m_show_edit+=word1;
errors = true; 
} 
mem[lc] = op; // 存储机器指令到机器的内存中 
lc = (lc + 1) % MEMSIZE; // 地址计数器增1 
break; 
case REFLABEL: //地址标号的引用处理 
strcpy(tpwords, words); 
strcat(tpwords, ":"); //将地址标号转变成其定义的形式 
//查询符号表,是否已经有该符号,返回在符号表的位置 
labelidx = seeklabel(tpwords, 1); 
if (labelidx == -1) { 
m_show_edit+="\r\n";
m_show_edit+=words;
m_show_edit+="未定义该标号,引用错误:", 
itoa( lc,word1,10); 
 m_show_edit+=word1;
return false; //未定义该标号,引用错误! 
} else { 
/*#ifdef DEBUG 
//显示标号所代表的内存地址...    
printf("REFLBL %d %d %s\n", lc, 
   symtabhdr[labelidx].symaddr, words); 
#endif */
//取得该符号所代表的内存地址,存到机器的内存中 
mem[lc] = symtabhdr[labelidx].symaddr; 
lc = (lc + 1) % MEMSIZE; // 地址计数器增1 
} 
break; 
case NUM: //数值处理:仅可为1个字节宽度 
number = atoi(words); 
if (number >= 0) // convert to proper byte value 
mem[lc] = number % 256; 
else 
mem[lc] = (256 - abs(number) % 256) % 256; 
lc = (lc + 1) % 256; // 地址计数器增1 
break; 
} 
    } 

    binlen = lc; //最终的汇编后的二进制的代码总长度 
  //  printf("Binary assembled: %d bytes.\n", lc); 
   m_length=lc;
    // dump binary file for reference  
    char binfile[256]; 
    FILE *bin; 
    newsuffix(srcfile, "lst", binfile); 

    bin = fopen(binfile, "w"); 
    if (bin == NULL) { 
m_show_edit+="\r\nBinary file ignored."; 
    } else { 
for (i = 0; i < binlen; i++) 
if (strcmp(getmns(mem[i]), "???") 
&& getmnxlen(mem[i]) == 2) { 
fprintf(bin, " %02X  %02X%02X      %-4s %02X\n", i, 
mem[i], mem[i + 1], 
getmns(mem[i]), 
mem[i + 1]); 
i++; 
} else 
fprintf(bin, " %02X  %02X        %-4s\n", i, mem[i], 
getmns(mem[i])); 
    } 
    fclose(bin); 
	return true;
} 


/* 
  mksymtab() 
  构造符号表,建立符号地址与内存地址的对应表, 
  同时将对符号地址的引用情况以链表的形式表示出来 
*/ 
void CHMDlg::mksymtab(int &err) 
{ 
    char words[10]; 
    char tpwords[15]; 
    int labelidx; 
    int tokencnt = 0; //记号的个数 
    int symcnt = 0; 
    MC_opcodes opcode; 
    refnode *refs, *refsa, *newnode; 
    tokentype tokencat; 

    while (!feof(src)) { 
tokencat = lex(words, opcode); //读入一个单词,取得单词的类别及相关信息 
if (tokencat != CMNT) // 注释信息,直接跳过 
tokencnt++; 
else 
continue; 

switch (tokencat) { 
case LABEL: //新定义的标号,将其加入符号表     
if (seeklabel(words, 0) == -1) { 
strcpy(symtabhdr[symcnt].symname, words); 
symtabhdr[symcnt].symaddr = tokencnt - symtablen(); 
symtabhdr[symcnt].firstref = NULL; 
symcnt++; 
} else if (seeklabel(words, 0) == -2) { 
//标号重复定义错误 
err++; 
} 
break; 
case REFLABEL: 
//标号地址的引用处理 
strcpy(tpwords, words); 
strcat(tpwords, ":"); 

labelidx = seeklabel(tpwords, 1); 
if (labelidx == -1) { 
#ifdef DEBUG 
//向前引用,暂且输出一个警告信息,待进一步向前扫描才确定其是否定义 
printf 
("Pass1 warning: label not defined by now: '%s:' , addr:%2d, ignored!\n", 
 words, tokencnt); 
#endif 
; 
} else { 
// 向后引用情况,则将该引用的地址加入单链表 
newnode = new refnode; 
newnode->refsymaddr = tokencnt - 1; 
newnode->nextref = NULL; 
if (symtabhdr[labelidx].firstref == NULL) { 
symtabhdr[labelidx].firstref = newnode; 
} else { 
refs = symtabhdr[labelidx].firstref; 
refsa = refs; 
while (refs != NULL) { 
refsa = refs; 
refs = refs->nextref; 
} 
refsa->nextref = newnode; 
} 
} 
break; 
case UNKNOWN: //不可识别的符号,输出错误信息 
#ifdef DEBUG 

printf("Pass1 Warning: Unknown token: %d %s(%d)\n", tokencat, 
   words, tokencnt); 
//err++;        
#endif 

break; 
} 
#ifdef DEBUG 
printf("(%2d) %d %-8s(%d)\n", 
   opcode != MAXINSTUCTION ? opcode : -1, tokencat, words, 
   tokencnt); 
#endif 
    } 
#ifdef DEBUG 

    //输出所建立的符号表 
    printf("\n<<<< Symbol table constructed >>>>\n"); 
    for (int i = 0; i < symcnt; i++) { 
printf("%s %d %x -> ", symtabhdr[i].symname, symtabhdr[i].symaddr, 
   symtabhdr[i].firstref); 
if (symtabhdr[i].firstref != NULL) { 
refs = symtabhdr[i].firstref; 
while (refs != NULL) { 
printf("%d %x -> ", refs->refsymaddr, refs->nextref); 
refs = refs->nextref; 
} 
printf("\n"); 
} 
printf("\n"); 
    } 
    printf("<<<< Symbol table above >>>>\n"); 
    //符号表建立完成 
#endif 
} 

/* 
  seeklabel() 
  查询符号表,确定符号存在与否 
  purpose=0 是否对于符号进行了重复定义,进行错误提示 
  purpose=1 是否已经有该符号,以便进行引用填充 
*/ 
int CHMDlg::seeklabel(char *lbl, int purpose) 
{ 
    int i = 0; 

    for (i = 0; i < SYMTABLEN && strcmp(symtabhdr[i].symname, lbl); i++) 
; 
    if (i < SYMTABLEN && !purpose) { 
printf("label '%s' multiple defined ,location:%d\n", lbl, 
   symtabhdr[i].symaddr); 
return -2; //标号重复定义 
    } else if (i < SYMTABLEN && purpose == 1) { 
return i; //返回标号在符号表中的下标 
    } else { 
return -1; //无此标号 
    } 
} 

/* 
  lex:词法分析 
  逐字符读取输入流,以空格为分隔标记,将输入流的字符组合成单词, 
  给主调函数返回当前所读得的词法记号的类型并将单词符号串存入 
  words数组中,同时查机器的指令表,将该单词对应的机器指令存入 
  opcode返回主调函数。  
*/ 
tokentype CHMDlg::lex(char *words, MC_opcodes & opcode) 
{ 
    char cmds[20]; 
    char ch; 
    MC_bytes cds; 
    tokentype tks; 
    int i = 0; 

    cmds[0] = 0; 

    ch = toupper(getc(src)); 

//凡是ASCII不大于0X20(空格)的字符都规定为空格 
    while (ch <= ' ' && !feof(src)) //跳过所有的ASCII值为00~0x20的字符 
ch = toupper(getc(src)); 

    if (isalpha(ch)) { //地址标号/汇编指令:字母开头字母及数字的有限序列 
do { 
cmds[i] = ch; 
i++; 
ch = toupper(getc(src)); 
} while (ch > ' ' && (isalpha(ch) || isdigit(ch)) && !feof(src)); 

if (ch == ':') { // 若尾随有":",则为地址标号的定义,应将其保留 
cmds[i] = ch; 
i++; 
} 
//查询汇编指令表,以确定是否为汇编指令还是地址标号的定义及引用 
cmds[i] = 0; 
strcpy(words, cmds); 

⌨️ 快捷键说明

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