提要
本文所提汇编器为笔者学校课程《软件设计与实践B》中小组内的个人负责项目,供大家参考
第一步:龙芯32位基础整数指令集划分
声明:以下划分方式为笔者结合龙芯官方手册的自行划分,若有不合理处请告知笔者
指令类型 | 指令名 |
---|---|
3R | “add.w”,“sub.w”,“slt”,“sltu”,“nor”,“and”,“or”,“xor”,“sll.w”,“srl.w”,“sra.w”,“mul.w”,“mulh.w”,“mulh.wu”,“div.w”,“mod.w”,“div.wu”,“mod.wu”,“break”,“syscall” |
2R | “rdcntid.w”,“rdcntvl.w”,“rdcntvh.w” |
2RI8 | “slli.w”,“srli.w”,“srai.w” |
2RI12 | “slti”,“sltui”,“addi.w”,“andi”,“nop”,“ori”,“xori”,“ld.b”,“ld.h”,“ld.w”,“st.b”,“st.h”,“st.w”,“ld.bu”,“ld.hu”,“preld” |
2RI14 | “ll.w”,“sc.w” |
2RI16 | “jirl”,“b”,“bl”,“beq”,“bne”,“blt”,“bge”,“bltu”,“bgeu” |
1RI20 | “lu12i.w”,“pcaddu12i” |
BAR | “dbar”,“ibar” |
指令详情请见龙芯官方手册
第二步:UI界面开发
采用Qt来做UI开发,一方面是得益于Qt能在可视化界面就把大量重复的定义初始化窗口控件给做了,另一方面是考虑到后期反馈体感优化能够使用代码进行,且Qt基于C++,不会像Python一样到处调包,配环境就配个半天,而且使用C++这类偏向系统层面的语言更能体现出编程者的代码水平。
不过Qt开发方面国内资源稀缺,如果碰到一些想使用的类或是函数,就基本只能上Qt官网去一个个地查找
第三步:汇编代码翻译过程
- 首先我们可以通过Qt提供的PlainTextEdit控件(或是TextEdit控件)来获得用户的及时输入数据,那么问题就转为:如何根据用户的输入来进行汇编翻译呢?
为简单起见,我们不妨假设用户的输入内容均是正确的汇编代码(错误检测机制暂且不谈),那么每条汇编指令都会占用一行,我们就需要使用C++里的vector机制来进行逐行处理并保存结果,Qt提供的数据类型中有一个QString,此变量类型将会称为本汇编器的核心数据类型,它既能够像字符串一样进行增删改查,又能够通过Qt自带的功能函数转为int型或是ascii字符等等,且大部分Qt窗口控件的输出参数类型也要求是QString类型,所以我们不妨将每一行的输入内容都转为QString类型的字符串,然后推入向量中(C++的向量就是一个特别好用的“容器”,类似于C语言中结构体数组,且无需定义大小) - 其次,我们来分析一条汇编指令的构成,例如:
add.w $r1,$r1,$r2
这条指令中,add.w就是指令名,$r1和$r2就是操作数,且是寄存器类型的操作数(另外还有立即数类型的操作数),我们不妨用一种字符串处理手段.split(" ")来将指令切分(虽然严格来说C++没有split方法,但Qt提供的QString包含了这种便利的方法,学过Python的同学应该对split方法非常熟悉,没学过的建议百度一下),由于标准格式中,指令名和操作数之间一定存在空格的,所以我们可以放心大胆地操作,这样我们就得到了指令名,然后又由于格式要求操作数之间要用逗号间隔,这就又给了我们操作的空间,将分隔符从空格换成逗号,对剩余内容再次分割,就能得到各操作数 - 最后就是对照翻译的问题了,2中得到的指令名和若干操作数如何翻译成对应的机器码呢?学过计算机组成原理的同学或是有项目经历的同学应该对LUT(LookUp-Table)的思想不陌生,由于指令名的总量和名称总是固定的,寄存器类型的操作数名称也是固定的,所以我们可以用一些字符串数组来存储这些名称,然后将2中得到的字符串挨个比对即可
- 至此,一条指令的分析就完成了,接下来就是翻译成16进制机器码问题,可以自行实现2进制字符串转16进制字符串的方法,然后现将字符串指令转成2进制,再转成16进制。
结尾
第一部分就到这里结束吧,详细代码项目可通过gitee仓库获取,仓库地址,内容属作者原创,只供学习免费使用,其余用途请联系作者