📄 hmdlg.cpp
字号:
// 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 + -