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

上传人:laozhun 文档编号:2384736 上传时间:2023-02-17 格式:DOC 页数:55 大小:269.50KB
返回 下载 相关 举报
C语言课程设计模拟器和汇编程序的设计.doc_第1页
第1页 / 共55页
C语言课程设计模拟器和汇编程序的设计.doc_第2页
第2页 / 共55页
C语言课程设计模拟器和汇编程序的设计.doc_第3页
第3页 / 共55页
C语言课程设计模拟器和汇编程序的设计.doc_第4页
第4页 / 共55页
C语言课程设计模拟器和汇编程序的设计.doc_第5页
第5页 / 共55页
点击查看更多>>
资源描述

《C语言课程设计模拟器和汇编程序的设计.doc》由会员分享,可在线阅读,更多相关《C语言课程设计模拟器和汇编程序的设计.doc(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 instruction! n, a_line);

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号