📄 hmdlg.cpp
字号:
cds = lookupcmd(cmds); //查询汇编指令表
opcode = (MC_opcodes) cds;
// 如果没有查找到相应地汇编指令并且这个符号后面紧跟着":",那么就是地址标号地定义
if (cds == MAXINSTUCTION && words[strlen(words) - 1] == ':')
tks = LABEL; // 确定为地址标号的定义
// 如果没有查找到相应地汇编指令并且这个符号后面没有紧跟着":",那么就是地址标号的引用
else if (cds == MAXINSTUCTION && words[strlen(words) - 1] != ':')
tks = REFLABEL; //确定为地址标号的引用
else
tks = ASMCODE; // 确定为汇编指令
} else if (isdigit(ch)) { // 数字的处理:数字开头后跟0~9的有限序列
do {
cmds[i] = ch;
i++;
ch = toupper(getc(src));
} while (ch > ' ' && isdigit(ch) && !feof(src));
tks = NUM; //确定为数字
cmds[i] = 0;
strcpy(words, cmds);
} else if (ch == ';') { //单行注释:以';'起始至行尾的任意字符序列
do {
ch = toupper(getc(src));
} while (ch != 0x0a && !feof(src));
strcpy(words, "CMNT");
opcode = (MC_opcodes) - 99;
tks = CMNT; //识别为注释字符序列
} else { //不可识别的字符的处理
cmds[i] = ch;
i++;
cmds[i] = 0;
strcpy(words, cmds);
tks = UNKNOWN; //不可识别的字符
}
return tks; //返回类别标志
}
/*lookupcmd()
查询汇编指令表,返回对应的机器指令,机器指令隐含为指令数组的下标
*/
MC_bytes CHMDlg::lookupcmd(char *cmd)
{
int i = 0;
while (i < MAXINSTUCTION && strcmp(getmns(i), cmd))
i++;
return (MC_bytes) i;
}
/*
symtablen()
取得符号表的长度
*/
int CHMDlg::symtablen()
{
int i = 0;
for (i = 0; i < SYMTABLEN && strcmp(symtabhdr[i].symname, "???????"); i++)
;
return i;
}
const int ESC = 1;
// 将X执行加1操作,并保持其值在0~255范围内,因为CPU字长为8位
inline void increment(MC_bytes & x)
{
x = (x + 257) % 256;
}
// 将X执行减1操作,并保持其值在0~255范围内,因为CPU字长为8位
inline void decrement(MC_bytes & x)
{
x = (x + 255) % 256;
}
// 对str所指向的汇编助记符查指令表,
// 对正确的指令形式返回其所对应的机器码,对于错误的指令返回MC_bad(255)
MC_bytes CHMDlg::opcoded(char *str)
{
for (int i = 0; str[i]; i++)
str[i] = toupper(str[i]);
MC_bytes l = MC_nop;
while (l <= MAXINSTUCTION && strcmp(str, mnemonics[l]))
l++;
if (l <= MAXINSTUCTION)
return l;
else
return MC_bad;
}
// 以16进制形式输出CPU的256字节内存单元的内容
void CHMDlg::listcode(char *srcname)
{
MC_bytes nextbyte = 0, tnb;
char filename[256];
newsuffix(srcname, "map", filename);
if (*filename == '\0')
return;
FILE *listfile = fopen(filename, "w");
if (listfile == NULL)
listfile = stdout;
for (int i = 1; i <= 16; i++) {
fprintf(listfile, "%02X(%03d) ", (i - 1) * 16, (i - 1) * 16);
tnb = nextbyte;
int j;
for (j = 1; j <= 16; j++) {
fprintf(listfile, "%02X %s", mem[nextbyte],
(j == 8) ? " " : "");
increment(nextbyte);
}
fprintf(listfile, " ");
nextbyte = tnb;
for (j = 1; j <= 16; j++) {
fprintf(listfile, "%c",
(mem[nextbyte] < 0x20) ? '.' : mem[nextbyte]);
increment(nextbyte);
}
putc('\n', listfile);
}
if (listfile != stdout)
fclose(listfile);
}
// 输出程序运行时错误
void CHMDlg::runtime_error(MC_bytes pcnow)
{
switch (ps)
{
case badop:
//fprintf(stdout, "Illegal opcode");
m_show_edit+="\r\n错误的指令:";
break;
case nodata:
//fprintf(stdout, "No more data");
m_show_edit+="\r\n指令数据不足:";
break;
case baddata:
fprintf(stdout, "Invalid data");
m_show_edit+="\r\n存在非法数据:";
break;
}
//fprintf(stdout, " at %d\n", pcnow);
itoa(pcnow,shh,10);
m_show_edit+=shh;
showr();
//printf ("\nRuntime error happend, dumping memory to runtime.err.map ...\n");
m_show_edit+="\r\n运行时出错,释放内存!";
listcode("runtime.err.dump"); //dump runtime error to runtime.err.map file
}
// 根据寄存器的值设定标志器P和Z的状态
inline void CHMDlg::setflags(MC_bytes MC_register)
{
cpu.z = (MC_register == 0);
cpu.p = (MC_register <= 127);
}
//计算变址地址 X+B
inline MC_bytes CHMDlg::index(void)
{
return ((mem[cpu.pc] + cpu.x) % 256);
}
//从data文件读入一字符,并检测是否为中断字符
void CHMDlg::readchar(char &ch, status & ps)
{
ins.m_input="";
ins.m_kind="字符";
while(ins.m_input=="")
ins.DoModal();
temp=new char[ins.m_input.GetLength() +1];
strcpy(temp,ins.m_input);
ch=temp[0];
if (ch== ESC)
ps = finished;
if (ch < ' ')
ch = ' ';
}
// 将ch内的16进制数转换为数值
int hexdigit(char ch)
{
char tpch;
tpch = ch;
// 将大于10的字母转换为相应的数字
if (isalpha(ch) && (tpch | 0x20 >= 'a' && tpch | 0x20 <= 'f'))
return (ch + 10 - 'a');
if (isdigit(ch))
return (ch - '0');
else
return (0);
}
// 以指定的进制从data文件读入一个数字 格式{+|-}?{digit}*
int CHMDlg::getnumber(int base, status &ps)
{
bool negative = false;
char ch;
int num = 0;
ins.m_input="";
switch(base){
case 2:
ins.m_kind="二进制数";
break;
case 10:
ins.m_kind="十进制数";
break;
case 16:
ins.m_kind="十六进制数";
break;
}
while(ins.m_input=="")
{
ins.DoModal();
}
temp=new char[ins.m_input.GetLength() +1];
strcpy(temp,ins.m_input);
int i=-1;
do {
ch=temp[++i];
} while (!(ch > ' ' || ps != running)&&i<=ins.m_input.GetLength());
if (ps == running) {
if (i>=ins.m_input.GetLength())
ps = nodata;
else {
switch (ch)
{
case '-':
negative = true;
ch=temp[++i];
break;
case '+':
negative = false;
ch=temp[++i];
break;
}
if (!isxdigit(ch))
ps = baddata;
else {
while (isxdigit(ch) && ps == running) {
if (hexdigit(ch) < base && num <= (maxint - hexdigit(ch)) / base)
num = base * num + hexdigit(ch);
else
ps = baddata;
ch=temp[++i];
}
}
}
if (negative)
num = -num;
if (num > 0)
return num % 256;
else
return (256 - abs(num) % 256) % 256; //负数以2的补码的形式表示返回
}
return 0;
}
//对虚拟机执行汇编后的机器指令程序的主体函数
void CHMDlg::execute()
{
MC_bytes pcnow; // 程序计数器的先前值
MC_bytes carry; // 保存进位位的状态
MC_bytes number=0;
cpu.ir = mem[cpu.pc]; // 从内存中取指令送入指令寄存器
pcnow = cpu.pc; // 保存PC的先前值
increment(cpu.pc); // PC指向下一条将要执行的指令地址
//if (tracing)
//trace(pcnow); //若调试,输出全部cpu内部寄存器值
switch (cpu.ir)
{ //根据指令值,转入相应的处理
case MC_nop:
break; //空操作,直接返回
case MC_clra: //累加器A清0
cpu.a = 0;
break;
case MC_clrc: //进位标志器 C 清0
cpu.c = false;
break;
case MC_clrx: //变址寄存器 x 清0
cpu.x = 0;
break;
case MC_cmc: //进位标志器 C 取反
cpu.c = !cpu.c;
break;
case MC_inc: //累加器A自增1,影响标志器
increment(cpu.a);
setflags(cpu.a);
break;
case MC_dec: //累加器A自减1,影响标志器
decrement(cpu.a);
setflags(cpu.a);
break;
case MC_incx: //变址寄存器 x 自增1,影响标志器
increment(cpu.x);
setflags(cpu.x);
break;
case MC_decx: //变址寄存器 x 自减1,影响标志器
decrement(cpu.x);
setflags(cpu.x);
break;
case MC_tax: //累加器A内容送入变址寄存器 x
cpu.x = cpu.a;
break;
case MC_ini: //从输入读一10进制数送累加器A,影响标志器
cpu.a = getnumber(10, ps);
setflags(cpu.a);
break;
case MC_inb: //从输入读一2进制数送累加器A,影响标志器
cpu.a = getnumber(2, ps);
setflags(cpu.a);
break;
case MC_inh: //从输入读一16进制数送累加器A,影响标志器
cpu.a = getnumber(16, ps);
setflags(cpu.a);
break;
case MC_ina: //从输入读一ascii字符送累加器A,影响标志器
char ascii;
readchar(ascii, ps);
cpu.a = ascii;
setflags(cpu.a);
break;
case MC_oti: //以10进形式输出累加器A的内容
if (cpu.a < 128)
itoa(cpu.a,bits,10);
else itoa(cpu.a - 256,bits,10);
m_out+=bits;
UpdateData(false);
break;
case MC_oth: //以16进形式输出累加器A的内容
itoa(cpu.a,bits,16);
m_out+=bits;
UpdateData(false);
break;
case MC_otc: //以无符号10进数形式输出累加器A的内容
if(cpu.a>=0)
itoa(cpu.a,bits,10);
else
itoa(0-cpu.a,bits,10);
m_out+=bits;
UpdateData(false);
break;
case MC_otb: //以无符号2进制形式输出累加器A的内容
itb(cpu.a);
m_out+=bits;
UpdateData(false);
break;
case MC_ota: //以ascii字符形式输出累加器A的内容
m_out+=cpu.a;
UpdateData(false);
break;
case MC_push: //压栈操作:堆栈指针SP减1,累加器A的内容压入栈顶。
decrement(cpu.sp);
mem[cpu.sp] = cpu.a;
break;
case MC_pop: //出栈操作:栈顶的内容送入A,堆栈指针SP增1,影响标志器
cpu.a = mem[cpu.sp];
cpu.ar=cpu.sp;
increment(cpu.sp);
setflags(cpu.a);
break;
case MC_shl: //累加器A的各位顺次左移1位,最高位移入进位标志C,影响标志器
cpu.c = (cpu.a * 2 > 255);
cpu.a = cpu.a * 2 % 256;
setflags(cpu.a);
break;
case MC_shr: //累加器A的各位顺次右移1位,最低位移入进位标志C,影响标志器
cpu.c = cpu.a & 1;
cpu.a /= 2;
setflags(cpu.a);
break;
case MC_ret: //子程序调用返回,将栈顶保存的返回地址送PC,退栈
cpu.pc = mem[cpu.sp];
cpu.ar=cpu.sp;
increment(cpu.sp);
break;
case MC_halt: //停机
ps = finished;
break;
case MC_lda:
//双字节指令,格式:LDA B,其第二字节为一个内存地址,
//将位于B地址单元中的内容送入A累加器.
//实现时以当前PC所指内存中的数值为地址偏移,将其所指的内存中的内容送入A
cpu.a = mem[mem[cpu.pc]];
cpu.ar=mem[cpu.pc];
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_ldx:
//将X+B所指的内存单元的内容送入A,即:A=[X+B]
cpu.a = mem[index()];
cpu.ar=index();
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_ldi: //A=ImmB
cpu.a = mem[cpu.pc];
cpu.ar=cpu.pc;
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_lsp: //SP=[ImmB]
cpu.sp = mem[mem[cpu.pc]];
cpu.ar= mem[cpu.pc];
increment(cpu.pc);
break;
case MC_lspi: //SP=ImmB
cpu.sp = mem[cpu.pc];
cpu.ar=cpu.pc;
increment(cpu.pc);
break;
case MC_sta: //[ImmB]=A
mem[mem[cpu.pc]] = cpu.a;
increment(cpu.pc);
break;
case MC_stx: //[X+B]=A
mem[index()] = cpu.a;
increment(cpu.pc);
break;
case MC_add: //A=A+[ImmB]
cpu.c = (cpu.a + mem[mem[cpu.pc]] > 255);
cpu.a = (cpu.a + mem[mem[cpu.pc]]) % 256; //限定数值的大小为8bit
cpu.ar= mem[cpu.pc];
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_adx: //A=A+[X+ImmB]
cpu.c = (cpu.a + mem[index()] > 255);
cpu.a = (cpu.a + mem[index()]) % 256;
cpu.ar=index();
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_adi: //A=A+ImmB
cpu.c = (cpu.a + mem[cpu.pc] > 255);
cpu.a = (cpu.a + mem[cpu.pc]) % 256;
cpu.ar=cpu.pc;
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_adc: //A=A+C+[ImmB]
carry = cpu.c;
cpu.c = (cpu.a + mem[mem[cpu.pc]] + carry > 255);
cpu.a = (cpu.a + mem[mem[cpu.pc]] + carry) % 256;
cpu.ar= mem[cpu.pc];
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_acx: //A=A+C+[X+ImmB]
carry = cpu.c;
cpu.c = (cpu.a + mem[index()] + carry > 255);
cpu.a = (cpu.a + mem[index()] + carry) % 256;
cpu.ar= index();
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_aci: //A=A+C+ImmB
carry = cpu.c;
cpu.c = (cpu.a + mem[cpu.pc] + carry > 255);
cpu.a = (cpu.a + mem[cpu.pc] + carry) % 256;
increment(cpu.pc);
cpu.ar=cpu.pc;
setflags(cpu.a);
break;
case MC_sub: //A=A-[ImmB]
cpu.c = (cpu.a < mem[mem[cpu.pc]]);
cpu.a = (cpu.a - mem[mem[cpu.pc]] + 256) % 256;
cpu.ar= mem[cpu.pc];
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_sbx: //A=A-[X+ImmB]
cpu.c = (cpu.a < mem[index()]);
cpu.a = (cpu.a - mem[index()] + 256) % 256;
cpu.ar=index();
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_sbi: //A=A-ImmB
cpu.c = (cpu.a < mem[cpu.pc]);
cpu.a = (cpu.a - mem[cpu.pc] + 256) % 256;
cpu.ar=cpu.pc;
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_sbc: //A=A-C-[ImmB]
carry = cpu.c;
cpu.c = (cpu.a < mem[mem[cpu.pc]] + carry);
cpu.a = (cpu.a - mem[mem[cpu.pc]] - carry + 256) % 256;
cpu.ar= mem[cpu.pc];
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_scx: //A=A-C-[X+ImmB]
carry = cpu.c;
cpu.c = (cpu.a < mem[index()] + carry);
cpu.a = (cpu.a - mem[index()] - carry + 256) % 256;
cpu.ar= index();
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_sci: //A=A-C-ImmB
carry = cpu.c;
cpu.c = (cpu.a < mem[cpu.pc] + carry);
cpu.a = (cpu.a - mem[cpu.pc] - carry + 256) % 256;
cpu.ar=cpu.pc;
increment(cpu.pc);
setflags(cpu.a);
break;
case MC_cmp: //A与B所指单元的内容进行比较,影响标志位
cpu.c = (cpu.a < mem[mem[cpu.pc]]);
setflags((cpu.a - mem[mem[cpu.pc]] + 256) % 256);
cpu.ar= mem[cpu.pc];
increment(cpu.pc);
break;
case MC_cpx: //A与 X+ImmB 所指单元的内容进行比较,影响标志位
cpu.c = (cpu.a < mem[index()]);
setflags((cpu.a - mem[index()] + 256) % 256);
cpu.ar=index();
increment(cpu.pc);
break;
case MC_cpi: //A与ImmB进行比较,影响标志位
cpu.c = (cpu.a < mem[cpu.pc]);
cpu.ar=cpu.pc;
setflags((cpu.a - mem[cpu.pc] + 256) % 256);
increment(cpu.pc);
break;
case MC_ana: //A与[ImmB]进行位与,影响标志位
cpu.a &= mem[mem[cpu.pc]];
cpu.ar= mem[cpu.pc];
increment(cpu.pc);
setflags(cpu.a);
cpu.c = false;
break;
case MC_anx: //A与[X+ImmB]进行位与,影响标志位
cpu.a &= mem[index()];
cpu.ar=index();
increment(cpu.pc);
setflags(cpu.a);
cpu.c = false;
break;
case MC_ani: //A与ImmB进行位与,影响标志位
cpu.a &= mem[cpu.pc];
cpu.ar=cpu.pc;
increment(cpu.pc);
setflags(cpu.a);
cpu.c = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -