C语言课程设计模拟器和汇编程序的设计

上传人:痛*** 文档编号:144839062 上传时间:2022-08-28 格式:DOC 页数:55 大小:269.50KB
收藏 版权申诉 举报 下载
C语言课程设计模拟器和汇编程序的设计_第1页
第1页 / 共55页
C语言课程设计模拟器和汇编程序的设计_第2页
第2页 / 共55页
C语言课程设计模拟器和汇编程序的设计_第3页
第3页 / 共55页
资源描述:

《C语言课程设计模拟器和汇编程序的设计》由会员分享,可在线阅读,更多相关《C语言课程设计模拟器和汇编程序的设计(55页珍藏版)》请在装配图网上搜索。

1、华中科技大学计算机科学与技术学院C语言课程设计报告 题目:模拟器和汇编程序的设计专 业:计算机科学与技术班 级:学 号:姓 名:成 绩:指导教师:李开完成日期: 2012年 10 月 15 日目 录一、系统需求分析1二、总体设计6三、数据结构设计7四、详细设计9五、系统实现13六、运行测试与结果分析42七、总结44八、参考文献45九、指导教师评语46一、系统需求分析Simulator and Assembler1. 用C语言编制汇编程序,将此简单计算机的汇编源程序翻译成目标代码,即机器码。为了测试所编制汇编程序的正确性,需用以上介绍的指令集编写两个汇编源程序,汇编源程序的功能要求为: 求1+2

2、+3+100,并输出运算结果。 求将” Simulator and Assembler”拷贝复制到新串并输出运算结果。串并输出运算结果。其中,32条指令以及伪指令和它们的功能如下:(1) 停机指令:HLT功能:终止程序运行。(2) 无条件转移指令:JMP label功能:将控制转移至标号label处,执行标号label后的指令。(3) 比较运算转移指令:CJMP label功能:如果程序状态字中比较标志位c的值为1(即关系运算的结果为真),则将控制转移至标号label处,执行标号label后的指令;否则,顺序往下执行。(4) 溢出转移指令:OJMP功能:如果程序状态字中比较标志位o的值为1(即

3、算术运算的结果发生溢出),则将控制转移至标号label处,执行标号label后的指令;否则,顺序往下执行。(5) 调用子程序指令:CALL label功能:将通用寄存器AG、程序状态字PSW、程序计数器PC中的值保存到ES,然后调用以标号label开始的子程序,将控制转移至标号label处,执行标号label后的指令。(6) 子程序返回指令:RET功能:将ES中保存的通用寄存器AZ、程序状态字PSW和程序字数器PC的值恢复,控制转移到子程序被调用的地方,执行调用指令的下一条指令。(7) 入栈指令:PUSH reg0功能:将通用寄存器reg0的值压入堆栈SS,reg0可以是AG和Z八个通用寄存器

4、之一。(8) 出栈指令:POP reg0功能:从堆栈SS中将数据出栈到寄存器reg0,reg0可以是AG七个通用寄存器之一,但不能是通用寄存器Z。(9) 取字节数据指令:LOADB reg0 symbol功能:从字节数据或字节数据块symbol中取一个字节的数据存入寄存器reg0,所取的字节数据在数据块symbol中的位置由寄存器G的值决定。用C的语法可将此指令的功能描述为: reg0 = symbolG例如,假设用伪指令定义了以下字节数据块num: BYTE num10 = 5,3,2,8,6,9,1,7,4,0如果要将字节数据块num中第5个单元的值(即下标为4的元素)取到寄存器C,指令如

5、下: LOADI G 5 LOADB C num后面的指令LOADW、STOREB和STOREW在操作上与此指令类似。(10) 取双字节数据指令:LOADW reg0 symbol功能:从双字节数据或双字节数据块symbol中取一个双字节的数据存入寄存器reg0,所取的双字节数据在数据块symbol中的位置由寄存器G的值决定。(11) 存字节数据指令:STOREB reg0 symbol功能:将寄存器reg0的值存入字节数据或字节数据块symbol中的某个单元,存入单元的位置由寄存器G的值决定。用C的语法可将此指令的功能描述为: symbolG = reg0(12) 存双字节数据指令:STOR

6、EW reg0 symbol功能:将寄存器reg0的值存入双字节数据或双字节数据块symbol中的某个单元,存入单元的位置由寄存器G的值决定。(13) 取立即数指令:LOADI reg0 immediate功能:将指令中的立即数immediate存入寄存器reg0。立即数被当作16位有符号数,超出16位的高位部分被截掉。例如: LOADI B 65535寄存器B的值为-1。 LOADI B 65537寄存器B的值为1。(14) 空操作指令:NOP功能:不执行任何操作,但耗用一个指令执行周期。(15) 控制台输入指令:IN reg0 0功能:从输入端口(即键盘输入缓冲区)取一个字符数据,存入寄存

7、器reg0。(16) 控制台输出指令:OUT reg0 15功能:将寄存器reg0的低字节作为字符数据输出到输出端口(即显示器)。(17) 加运算指令:ADD reg0 reg1 reg2功能:将寄存器reg1的值加上reg2的值,结果存入寄存器reg0。如果结果超过16位有符号数的表示范围,将发生溢出,使程序状态字的溢出标志位o置为1;如果未发生溢出,则使程序状态字的溢出标志位o置为0。(18) 加立即数指令:ADDI reg0 immediate功能:将寄存器reg0的值加上立即数immediate,结果仍存入寄存器reg0。如果结果超过16位有符号数的表示范围,将发生溢出,使程序状态字的

8、溢出标志位o置为1;如果未发生溢出,则使程序状态字的溢出标志位o置为0。(19) 减运算指令:SUB reg0 reg1 reg2功能:将寄存器reg1的值减去reg2的值,结果存入寄存器reg0。如果结果超过16位有符号数的表示范围,将发生溢出,使程序状态字的溢出标志位o置为1;如果未发生溢出,则使程序状态字的溢出标志位o置为0。(20) 减立即数指令:SUBI reg0 immediate功能:将寄存器reg0的值减去立即数immediate,结果仍存入寄存器reg0。如果结果超过16位有符号数的表示范围,将发生溢出,使程序状态字的溢出标志位o置为1;如果未发生溢出,则使程序状态字的溢出标

9、志位o置为0。(21) 乘运算指令:MUL reg0 reg1 reg2功能:将寄存器reg1的值乘以reg2的值,结果存入寄存器reg0。如果结果超过16位有符号数的表示范围,将发生溢出,使程序状态字的溢出标志位o置为1;如果未发生溢出,则使程序状态字的溢出标志位o置为0。(22) 除运算指令:DIV reg0 reg1 reg2功能:将寄存器reg1的值除以reg2的值,结果存入寄存器reg0,这里进行的是整数除运算。如果寄存器reg2的值为零,将发生除零错。(23) 按位与运算指令:AND reg0 reg1 reg2功能:将寄存器reg1的值与reg2的值进行按位与运算,结果存入寄存器

10、reg0。(24) 按位或运算指令:OR reg0 reg1 reg2功能:将寄存器reg1的值与reg2的值进行按位或运算,结果存入寄存器reg0。(25) 按位异或运算指令:NOR reg0 reg1 reg2功能:将寄存器reg1的值与reg2的值进行按位异或(按位加)运算,结果存入寄存器reg0。(26) 按位取反运算指令:NOTB reg0 reg1功能:将寄存器reg1的值按位取反后,结果存入寄存器reg0。(27) 算术左移运算指令:SAL reg0 reg1 reg2功能:将寄存器reg1的值算术左移reg2位,结果存入寄存器reg0。在进行算术左移时,低位空位用0填充。(28

11、) 算术右移运算指令:SAR reg0 reg1 reg2功能:将寄存器reg1的值算术右移reg2位,结果存入寄存器reg0。在进行算术右移时,高位空位用符号位填充。(29) 相等关系运算指令:EQU reg0 reg1功能:将两个寄存器reg0和reg1的值进行相等比较关系运算:reg0 = reg1,关系运算的结果为逻辑真或逻辑假,存入程序状态字中的比较标志位c。(30) 小于关系运算指令:LT reg0 reg1功能:将两个寄存器reg0和reg1的值进行小于关系运算:reg0 reg1,关系运算的结果为逻辑真或逻辑假,存入程序状态字中的比较标志位c。(31) 小于等于关系运算指令:L

12、TE reg0 reg1功能:将两个寄存器reg0和reg1的值进行小于等于关系运算:reg0 27) & 0x0F;通用寄存器用unsigned short数组来模拟;每条指令的功能用一个无参整型函数来实现,再定义一个函数指针数组ops,将32个函数的入口地址保存到数组ops中,数组下标与函数所对应指令操作码一致,这样,从指令中解码得到指令操作码后,就可以用如下表达式调用指令功能的实现函数,模拟指令的执行。(*opsOPCODE)();接下来进行下一轮循环,直到执行函数HLT退出循环。下面是模拟器程序的流程图:开始 SS = (short *)PC; PC-; DS = (char *)PC

13、 - *PC; ES = (struct Extra *)(MEM + mem_size - sizeof(struct Extra);打开文件Y文件到结尾?N关闭文件取出代码PC指向第一条指令加载到内存PC+;CS = PC;N函数返回值为1?Y取指:将PC指示的指令加载到指令寄存器IRPC指向下一条执行指令解码并执行指令令结束五、系统实现两个汇编程序源码:累加: #1加到100LOADIA100# 循环的上界设为100LOADIB1# 将循环次数存入寄存器B中LOADIC0# 将和数存入寄存器C中LOADID10# 用于转换时的除数LOADIE1000# 将和数转换成字符的除数LOADIF

14、0# 用于提取个位,十位等的数字LOADIG0# 用于转换时的减数loop:ADDCCB# 计算D = C + BADDIB1# 将B的值增加1LTEBA# B = A?CJMPloop# 若B = A 为真,则跳到loop处loop2: DIVFCE# F = C / EADDIF48# 将数字转化为数字字符OUTF15# 输出FSUBIF48# 将数字字符转化为数字MULGFE# G = F * ESUBCCG# C = C - GDIVEED# E = E / DLOADIA0# A = A - 100LTEEA# E 0CJMPloop2# 若E 0 为真,则跳到loop2处HLT#

15、结束拷贝字符串:#拷贝字符串BYTEstr24 = Simulator and AssemblerBYTEs24LOADIA19LOADIB0LOADIC0LOADID0LOADIE0LOADIG0# 将数组下限设为0SUBIG4loop: LOADBBstrSTOREBBsLOADBCsADDDGEADDID48OUTC15ADDIG1LTGACJMPloopHLT编译程序源码:#include #include #include #include #define MAX_LEN 150#define INSTRS_COUNT (sizeof(g_instrs_name)/sizeof(g_

16、instrs_name0)#define INSTR_SYM HLT,JMP,CJMP,OJMP,CALL,RET,PUSH,POP,LOADB, LOADW,STOREB,STOREW,LOADI,NOP,IN,OUT,ADD, ADDI,SUB,SUBI,MUL,DIV,AND,OR,NOR,NOTB, SAL,SAR,EQU,LT,LTE,NOTC,BYTE,WORD const char *g_instrs_name = INSTR_SYM; /*定义存放指令记号的数组*/const char instr_format33 = 12222133444451667575777778778

17、881;int GetInstrCode(const char *op_sym); /*由指令助记符得到指令代码*/unsigned long TransToCode(char *instr_line, int instr_num); /*指令的译码*/int GetRegNum(char *instr_line, char *reg_name); /*由寄存器名对应到代码*/typedef struct tab int addr; /*标号偏移量*/ char str20; /*标号名称*/ struct tab *next;TAB;typedef struct byte_word int

18、type; /*类型*/ char name8; /*变量名*/ int num; /*数组长度*/ long dat65; /*数据*/ struct byte_word *next;BYTE_WORD;TAB *head1 = NULL;BYTE_WORD *head2 = NULL;int main(int argc, char *argv) char a_lineMAX_LEN; char op_sym8; int op_num; int s = 0, k = 0, m = 0, j = 0, p = 0, q = 0; char num5; char dat5050; unsigne

19、d long str4; char *pcPos; FILE *pfIn, *pfOut; head1 = (struct tab *)malloc(sizeof(struct tab); TAB *p1 = head1; head2 = (struct byte_word *)malloc(sizeof(struct byte_word); BYTE_WORD *p2 = head2, *temp, *tail = head2; int n; if (argc 3) /*检查命令行参数数目*/ printf(ERROR:no enough command line arguments!n);

20、 return 0; if (pfIn = fopen(argv1, r) = NULL) /*打开源代码文件*/ printf(ERROR:cannot open file %s for reading!n, argv1); return 0; if (pfOut = fopen(argv2, w) = NULL) /*打开目标代码文件*/ printf(ERROR:cannot open file %s for writing!n, argv2); return 0; while (!feof(pfIn) /*处理标号和伪指令*/ fgets(a_line, MAX_LEN, pfIn);

21、 /*从源文件中取出一条指令*/ if (pcPos = strchr(a_line, #) != NULL) *pcPos = 0; n = sscanf(a_line, %s, op_sym); /*从指令中取指令助记符*/ if(n addr = s; /*记录标号的行数*/ sscanf(a_line, %:, p1-str); /*将冒号为止的字符串存入str中*/ p1-next = (struct tab *)malloc(sizeof(struct tab); p1 = p1-next; if (strcmp(BYTE, op_sym) = 0) | (strcmp(WORD,

22、 op_sym) = 0) /*处理变量*/ if(strcmp(BYTE, op_sym) = 0) p2-type = 1; else p2-type = 2; sscanf(a_line, %*s%s, p2-name); /*存变量名*/ while(p2-namek != 0) /*去掉字符串中方括号的部分*/ if(p2-namek = ) p2-namek = 0; k+; k = 0; if(strchr(a_line, ) != NULL) sscanf(a_line, %*%0-9, num); p2-num = atoi(num); /*将num转化为整数*/ for(m

23、 = 0; m num; m+) p2-datm = 0; m = 0; if(strchr(a_line, =) != NULL) while (a_linej != ) & (a_linej != ) j+; if(a_linej = ) while(a_line+j != ) p2-datm+ = a_linej; else while (a_line+j != ) if (isdigit(a_linej) /*如果是数字*/ datpm+ = a_linej; else if (a_linej = ,) p+; m = 0; for (j = 0; j datj = atoi(datj

24、); else for(m = 0; m num; m+) p2-datm = 0; else if(strchr(a_line, =) != NULL) sscanf(a_line, %*=%s, dat0); p2-dat0 = atoi(dat0); p2-num = 1; else p2-num = 1; k = 0; m = 0; p = 0; q = 0; p2-next = (struct byte_word *)malloc(sizeof(struct byte_word); p2 = p2-next; continue; s+; /*行数加1*/ free(p1); free

25、(p2); p1 = NULL; p2 = NULL; s = 0; fclose(pfIn); fclose(pfOut); pfIn = fopen(argv1, r); pfOut = fopen(argv2, w); while (!feof(pfIn) /*第二次扫描*/ fgets(a_line, MAX_LEN, pfIn); if (pcPos = strchr(a_line, #) != NULL) *pcPos = 0; n = sscanf(a_line, %s, op_sym); if (n 33) printf(ERROR: %s is a invalid instr

26、uction! n, a_line); exit(-1); fprintf(pfOut,0x%08lxn,TransToCode(a_line, op_num); s+; for (p2 = head2, k = 0, m = 0; (p2 != NULL) & (p2-num 0) & (p2-num next) if(p2-type = 1) for(s = 0, j = 0; s num; s+) strj = p2-dats; /*目的将数据倒序输出*/ j+; if(j = 4) fprintf(pfOut, 0x%02lx%02lx%02lx%02lxn, str3, str2,

27、str1, str0); j = 0; k+; switch(j) case 1: fprintf(pfOut, 0x%08lxn, str0); break; case 2: fprintf(pfOut, 0x%04lx%04lxn, str1, str0); break; case 3: fprintf(pfOut, 0x00%02lx%02lx%02lxn, str2, str1, str0); break; case 4: fprintf(pfOut, 0x%02lx%02lx%02lx%02lxn, str3, str2, str1, str0); break; if(p2-type

28、 = 2) for(s = 0, j = 0; s num; s+) strj = p2-dats; j+; if(j = 2) fprintf(pfOut, 0x%04lx%04lx4n, str1, str0); k += 2; switch(j) case 1: fprintf(pfOut, 0x%08lxn, str0); break; case 2: fprintf(pfOut, 0x%04lx%04lxn, str1, str0); break; fprintf(pfOut, 0x%08lxn, k); fclose(pfIn); fclose(pfOut); return 1;i

29、nt GetInstrCode(const char *op_sym) int i; for (i = 0; i INSTRS_COUNT; i+) if(strcmp(g_instrs_namei, op_sym) = 0) break; return i;unsigned long TransToCode(char *instr_line, int instr_num) unsigned long op_code; unsigned long arg1, arg2, arg3; unsigned long instr_code = 0ul; char op_sym8, reg08, reg

30、18, reg28; unsigned long addr; int immed, port; int n; char a50; switch (instr_formatinstr_num) case 1: /*第一种指令格式(HLT、RET、NOP、NOTC)的译码*/ op_code = instr_num; instr_code = op_code 27; break; case 2: /*第二种指令格式(JMP、CJMP、OJMP、CALL)的译码*/ n = sscanf(instr_line, %s%s, op_sym, a); if (n 2) printf(ERROR:bad

31、instruction format!n); exit(-1); addr = SearchTab(a) * 4; op_code = GetInstrCode(op_sym); instr_code = (op_code 27) | (addr & 0x00ffffff); break; case 3: /*第三种格式指令(PUSH、POP)的译码*/ n = sscanf(instr_line, %s %s, op_sym, reg0); if (n 2) printf(ERROR:bad instruction format!n); exit(-1); op_code = GetInst

32、rCode(op_sym); arg1 = GetRegNum(instr_line, reg0); instr_code = (op_code 27) | (arg1 24); break; case 4: /*第四种格式指令(LOARB、LOADW、STOREB、STOREW)的译码*/ n = sscanf(instr_line, %s %s %s, op_sym, reg0, &a); if (n 3) printf(ERROR:bad instruction format!n); exit(-1); addr = Search_BYTE_WORD(a); op_code = GetI

33、nstrCode(op_sym); arg1 = GetRegNum(instr_line, reg0); instr_code = (op_code 27) | (arg1 24) | (addr & 0x00ffffff); break; case 5: /*第五种格式指令(LOADI、ADDI、SUBI)的译码*/ n = sscanf(instr_line, %s %s %i, op_sym, reg0, &immed); if (n 3) printf(ERROR:bad instruction format!n); exit(-1); op_code = GetInstrCode(

34、op_sym); arg1 = GetRegNum(instr_line, reg0); instr_code = (op_code 27) | (arg1 24) | (immed & 0x0000ffff); break; case 6: /*第六种格式指令(IN、OUT)的译码*/ n = sscanf(instr_line, %s %s %i, op_sym, reg0, &port); if (n 3) printf(ERROR:bad instruction format!n); exit(-1); op_code = GetInstrCode(op_sym); arg1 = GetRegNum(instr_line, reg0); instr_code = (op_code 27) | (arg1 24) | (port & 0x0000ffff); break; case 7: /*第七种格式指令(ADD、SUB、MUL、DIV、AND、OR、NOR、SAL、SAR)的译码*/ n = sscanf(instr_line, %s%s%s%s, op_sym, reg0, reg1, reg2);

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!