基于Qt实现的简单CPU模拟器

邱丑丑

发布日期: 2019-07-01 11:42:11 浏览量: 312
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

一、设计内容

简单CPU模拟器的设计与实现

二、设计要求

  • 可以读取TXT格式的文件(文件内容为汇编指令)在界面中显示

  • 可以将TXT文件中的汇编指令(规定格式)进行编译,显示在界面中

  • 根据编译后的内容,执行相关操作,结果显示在界面中

  • 对相关操作进行描述输出在界面中

三、设计过程

3.1 开发环境的选择

要实现界面的设计需要GUI编程,由于对visual c++的不熟悉,故选择了支持C++ 的Qt。

Qt 是一个1991年由Qt Company开发的跨平台C++应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。

3.2 UI的布局和设计

结合设计要求方案,需要几个按键分别实现 读取文件,编译文件,生成TXT文件,运行 等操作。 同时需要几个文本显示区,用来显示相关内容。 以及在设计过程中给User的一些提示等。

根据以上分析,设计了一个ui界面:

完成了初步的搭建后,进行相关的布局,布局在Qt可以通过代码实现或者直接手动操作,这里我选择了后者,通过在合适位置加入VerticalSpacer和HorizontalSpacer (垂直和水平弹簧),最后按Ctrl + G,实现栅格布局。

同时为了方便使用,需要添加相关的提示,这里我选择了使用QLineEdit控件和QLabel控件,通过添加代码实现内容的显示。

代码部分

在构造函数中书写相关内容。

构造函数

  1. Widget::Widget(QWidget *parent) :
  2. QWidget(parent),
  3. ui(new Ui::Widget){}

内容举例

ui->label->setText(“注意:按完 [编译生成TXT] 后,再按 [运行]”);

3.3 读取文件的实现

课设过程要求对文件进行读取操作。因此要实现按键按下后对文件的选择,以及读取。

通过向槽函数中写入相关操作,实现操作与按键的关联,从UI中选择相应的Push_button,右键选择转到槽函数,选择的信号click()。

  1. void Widget::on_buttonRead_clicked();//槽函数的声明部分

槽函数内部代码具体思路:

  1. QString str = QFileDialog::getOpenFileName(this,"选择要打开的txt文本","../","fileName(*.txt)"); //获取文件路径
  2. QFile file(str); //创建文件对象,关联路径
  3. file.open(QIODevice::ReadOnly) //打开文件
  4. QByteArray array = file.readAll(); //读取文件内容
  5. ui->textEdit->setText(QString(array)); //将内容设置到UI的TextEdit中显示

文件打开

文件内容读取

3.4 编译过程的实现

根据文件内容,将其中的汇编指令编译成相关的二进制数。分析后发现这是对字符串的处理。
我的思路是,一次读取文件的一行,对字符串进行拆分,拆分过程中用到的函数为:

  1. left() //从字符串左边获取参数长度的子串
  2. right() //从字符串右边获取参数长度的子串
  3. mid() //从字符串的某一位置(第一个参数)开始获取参数长度(第二个参数)的子串

除去拆分字符串,还要进行字符串匹配,匹配相关的关键字,这里使用:

  1. contains() //根据括号中是否有相关内容,返回一个bool值

同时还需要将具体的数字转换为需要的二进制数字,这里使用:

  1. //进制转换函数
  2. QString::number(str_behind.toInt(&ok,10),2)
  3. //将字符串中内容转换为10进制整型
  4. str_behind.toInt(&ok,10)
  5. //替换函数
  6. replace()
  7. //字符串组合后输出
  8. QString final_Str = "1001 0010" + binaryStr + Str_x + "\n";

注:这里的代码写在与Push_button相关联的槽函数中

3.5 编译生成TXT

这一步是为了运行过程中读取内容所设置的,String一行一行读取的相关函数未找到,于是想到了将内容写入一个文本文件中,点击运行按钮后读取文件内容。

这一步的关键操作是创建文件,同时写入内容。

代码实现:(由于这一部分简短且有代表性,我将全部代码展示出来并解释)

  1. void Widget::on_CreatTxtButton_clicked()
  2. {
  3. //创建一个文件并写入TxtEdit_2中的内容
  4. QFile file2("PYP的编译后文件.txt");
  5. if(file2.exists())
  6. {
  7. file2.open(QIODevice::WriteOnly);
  8. QString str = ui->textEdit_2->toPlainText();
  9. file2.write(str.toUtf8());
  10. }
  11. else
  12. {
  13. file2.open(QIODevice::WriteOnly);
  14. QString str = ui->textEdit_2->toPlainText();
  15. file2.write(str.toUtf8());
  16. }
  17. file2.close();
  18. }

这里的打开方式为QIODevice::WriteOnly,这种打开方式下,如果文件不存在会创建一个,这也是我们的目的所在——-创建一个文件。

通过toPlainText()函数实现获取编译后显示在UI界面中的textEdit_2的文本。将其通过write函数写入创建的TXT文件中。

3.6 运行

这是最核心的一部分。主要方面有,对字符串的处理,相关指令的理解与执行,运行结果的组包输出(更直观的看到运行效果)。

3.6.1 对字符串的处理

这部分更多的是借鉴编译过程的方法和技巧,同过拆分字符串,使用相关的函数来实现替换,进制转换,数据类型转换等。

这里我选择一个Ldi指令的运行来说明一下,结合注释看代码。

  1. //确定是否为Ldi指令
  2. if(str.left(5).contains("1110"))
  3. {
  4. bool ok;
  5. //截取关键的内容,注意MID()方法的参数,截取寄存器名字,截取数值
  6. QString numstr = str.mid(5,4) + str.mid(15,4);
  7. QString RegisterStr = str.mid(10,4);
  8. //通过for语句遍历是哪一个寄存器
  9. for(int i=0;i<16;i++)
  10. {
  11. if(i == RegisterStr.toInt(&ok,2))
  12. {
  13. int result = Rarray[i].theNumberInRegister = numstr.toInt(&ok,2);
  14. //用于组包的字符串
  15. QString Str_combination;
  16. //组包
  17. Str_combination = QString("寄存器 R%1 被装入值:").arg(i);
  18. Str_combination = timeStr + " " + Str_combination + QString::number(result,16).toUpper() + "\n"+ "\n";
  19. qDebug()<< Str_combination;
  20. //整合到最终的输出字符串中,设置为文本
  21. Final_Str += Str_combination;
  22. ui->textEdit_3->setText(Final_Str);
  23. }
  24. }
  25. }

3.6.2 对指令的理解与执行

这次使用到的指令有:

  • Add Rd, Rr 加法指令

  • Sub Rd, Rr减法指令

  • Mul Rd, Rr无符号乘法指令

  • RJMP K 无条件相对跳转指令

  • BRMI K 有条件相对跳转指令

  • Mov Rd, Rr数据传送指令

  • LdiRd, K载入立即数指令

  • LdRd, X装载指令

  • StX, Rr 存储指令

  • Nop空操作指令

几个运算指令中需要注意的是Mul无符号乘法指令,这个指令执行后,将相乘的两个寄存器的内容的高8位存储到R1中,低8位存储到R0中,这个在操作过程中需要特别注意。

RJMP和BRMI指令要根据K对应的十进制数字进行相应的PC增加,增加后,对应于PC的全局变量要实现增加。

Ld,St指令的执行类似于存储器间接寻址,是将一个存储器中的数作为一个地址,去讲这个地址对应的存储器的内容进行装载。

3.6.3 运行结果的组包和输出

这里在6.1中的代码中可以看到相关的操作,我举出所用的函数:

  1. QString i; // current file's number
  2. QString total; // number of files to process
  3. QString fileName; // current file's name
  4. QString status = QString("Processing file %1 of %2: %3").arg(i).arg(total).arg(fileName);
  5. First, arg(i) replaces %1. Then arg(total) replaces %2. Finally, arg(fileName) replaces %3.

这是Qt帮助文档的内容,十分直观,通过设置’%1’,’%2’等,让arg()函数中的内容去替换,有点类似C语言中的Printf()函数,使用它可以让内容更直观的动态的现实出来。

3.7 最终结果的显示

所有指令运行完毕后,要有一个最终结果,显示每个寄存器中的值。

首先展示一下,我的寄存器的数据结构:

在寄存器类中,包含两个关键成员,寄存器名字和寄存器中的数。

  1. int register_Name; //寄存器的名字
  2. int theNumberInRegister; //寄存器中存储的内容

同时在Widget.h的头文件中,声明关键的成员变量,一个寄存器数组,一个间接寻址寄存器数,间接寻址寄存器数组的索引。

  1. //创建一个Register类的对象数组
  2. Register Rarray[16];
  3. //创建一个Register类的对象数组,用于间接寻址产生的问题
  4. Register RegisterIndirect[5];
  5. //记录间接寻址使用的寄存器的索引
  6. static int indexOfRegisterIndirect;

通过遍历两个数组来实现内容的显示。

举例代码:

  1. for(int i=0;i<16;i++)
  2. {
  3. 16).toUpper();
  4. Str_over += QString("R%1:").arg(i) +
  5. QString::number(Rarray[i].theNumberInRegister,16).toUpper() + "\n";
  6. ui->textEdit_4->setText(Str_over);
  7. }

遍历每一个寄存器,输出其中的值,同时进行相关的进制,大小写转换,最后输出到TextEdit_4中。

3.8 生成相关的EXE和库文件

在没有Qt的电脑上,相关的EXE文件是运行不了的。这里的解决方法是:

使用Release模式运行程序,生成相关的EXE文件,将EXE文件,放到一个单独的文件夹中,使用Qt自己的命令提示符,进入EXE文件的所在的目录中,执行指令windeployqt + exe文件名字,自动加入相关的库文件到此文件夹中。

四、设计中遇到的问题和解决方案

4.1 问题

  • 如何搭建一个界面

  • 如何截取字符串

  • 如何替换字符串

  • 如何读取文件

  • 如何写入文件

  • 对指令的理解

  • 运行过程的现实

  • 最终结果的展示

  • 可执行程序在别的电脑上的运行

4.2 解决方案

看视频学习Qt的使用,同时多练习多敲,结合Qt的帮助文档。分析字符串的位置,相关截取函数的查找,对应函数的使用方法。不断的敲代码,不断的调试,多做记录。与同学讨论,咨询指令的具体执行过程,加深对指令的理解。

五、设计感触

通过这次的计算机原理课程设计,我遇到了很多问题,大的,小的都有。代码从最初的起步到慢慢增加,再到发现有大的问题,推倒重来。经验在不断的积累,为最后的实现打下了基础。

同时,我对计算机原理寄存器部分的理解,相关指令的理解,有了加深,对我所学编程的语言有了更深刻的认识。

除了在相关学科上有了学习与进步,我在做课设的过程中,更体会到了坚持的重要性,学习,生活都会出现困难,我们应客观认识到这个现实,认识到人的学习,发展的客观过程是有阶段性的。认清自我,帮助自己更好的学习,发展。

最后,很开心参加这次课程设计,我会在今后的学习生活中,不断的积累自己的知识,提升自己的个人能力。

上传的附件 cloud_download 计算机原理课设.7z ( 14.32mb, 5次下载 )
error_outline 下载需要10点积分

发送私信

精品资源尽在此

61
文章数
0
评论数
最近文章
eject