MIPS汇编

来源:互联网 发布:09外设淘宝店地址 编辑:程序博客网 时间:2024/05/01 13:06
按:这是计算机组成课程第五周的作业。请各位多多评论。

要求

用C或JAVA编写程序,将MIPS汇编指令转换为机器码,并以二进制方式存盘,以作为随后反汇编的输入及CPU模拟器的执行程序。实现如下的指令:R类型(ADD、SUB、SLT)、LW、SW、BEQ、J。         

能处理的指令格式

(只是为了写程序的时候处理起来不太麻烦而做的规定)

l  每行一条指令。(不能多条或没有)

l  指令名,变量名,行名等都不能用大写字母,只能用小写和数字。

l  BEQ和J支持直接输入要跳转的行的位置(标准mips采用的),也可以输入该行的名称(小写字母开头)。

l  被跳转行的名称应以小写字母开头(若以数字开头会认为是跳转的行数)。

l  被跳转行的头部应顶格写名称,紧跟冒号,再空至少一个空格。

l  每行指令后空开至少一个空格后可写注释(是否有#其实无关紧要)。

下面是合格的(可以正确汇编的)指令:

lw   $t0,8($s4) #dfstes1: lw  $t1 , 0 ( $s1 )#fsfs add $t0, $t0,  $t1 #fefsftest2: sw  $t0, 12  ( $s4)   #fgsdgsub $k0  ,$a1,$a2  #grewgresslt $s0,  $s2,$s1   #fdsgsbeq $k0,$k1,   tes1 #fgsgsd j   test2 #regfsbeq $k0,$k1, 12345 #fdsgsdfsdgfadd $s1,$s2,$s3sub $s1,$s2,$s3#gfsgfdgsslt $s1,$s2,$s3lw $s1,20($s2)  #ddsfgrwadhello: lw $s1,-20($s2)sw $s1,20($s2)sw $s1,-20($s2) #fdsgsdgdfsbeq $s0,$s1,25j 250beq $s0,$s1,forfor: j hello #rgegdsgfds

使用方法

将符合上述规范的指令放在assembly.txt文件中,运行本程序,就能生成用十六进制表示指令的“binary.txt”文件,和二进制文件“binary”。

实例分析

我与ZW同学交换了自己的测试数据,拿对方的汇编指令在自己的程序上跑,比对二进制结果是否相同。经过数次的debug,终于能基本保证正确。

对于上面的输入,输出binary.txt的结果是这样的:

8e8800088e2900001094020ae88000ca6d022251802a137afffa8000003137a303925388202538822253882a8e5100148e51ffecae510014ae51ffec1230001980000fa12300000800000d

经过分析比对,发现结果是正确的。

设计思路

两遍读取,第一遍将有名称的行的信息放入链表中,第二遍根据指令做具体的操作。观察发现指令的格式大约有三种,而这三种又由更为基本的两种变量(寄存器,立即数)构成。其中立即数有可能是直接用数字表示的(有正负),也可能是用行的名称代替的(需要在链表中找到对应的行)。具体见下程序框图。

程序框图


图表 1       程序框图

Source Code

#include<stdio.h>#include<stdlib.h>#include<string.h>char operation[6];char operands[100];char ch;unsigned long instruction;unsigned long reg[3];long imm;long count;int i;int p;int type;struct list{char name[10];int position;struct list *next;}*head, *tail, *temp;void getreg(){while(operands[p]!='$'){p++;}switch(operands[++p]){case 'z':{reg[i]=0;break;}case 'a':{if(operands[++p]=='t')reg[i]=1;else reg[i]=operands[p]-'0'+4;break;}case 'v':{reg[i]=operands[++p]-'0'+2;break;}case 't':{if(operands[++p]<='7')reg[i]=operands[p]-'0'+8;else reg[i]=operands[p]-'0'+16;break;}case 's':{if(operands[++p]=='p')reg[i]=29;else reg[i]=operands[p]-'0'+16;break;}case 'k':{reg[i]=operands[++p]-'0'+26;break;}case 'g':{reg[i]=28;break;}case 'f':{reg[i]=30;break;}case 'r':{reg[i]=31;break;}}}void regregreg(){p=0;for(i=0;i<3;i++){getreg();}}void getimm(){while(operands[p]==' ')p++;//以(小写)字母开头就找同名的行的行号,其他视作直接读数字 if(operands[p]>='a'&&operands[p]<='z'){char tt[100];int t=0;while(operands[p]!=' '&&operands[p]!='\n')tt[t++]=operands[p++];tt[t]='\0';temp=head->next;while(temp!=NULL){if(!strcmp(temp->name,tt)){imm=temp->position;break;}elsetemp=temp->next;}type=0;}else{int flag=1;imm=0;while(operands[p]>='0'&&operands[p]<='9'||operands[p]=='-'){if(operands[p]=='-')flag=-1;elseimm=imm*10+operands[p]-'0';p++;}imm=imm*flag;type=1;}}void regimmreg(){p=0;for(i=0;i<3;i++){if(i!=1)getreg();else{while(operands[p++]!=',');getimm();}}}void regregimm(){p=0;for(i=0;i<3;i++){if(i!=2)getreg();else{while(operands[p++]!=',');getimm();}}}int main(void){FILE *fp = fopen("assembly.txt","r");FILE *fbi = fopen("binary","wb");FILE *ftext = fopen("binary.txt","w");if(!fp){printf("ERROR!!!\n");return 0;}head = malloc(sizeof(struct list));strcpy(head->name,"");head->position = 0;head->next = NULL;tail = head;count = 0;//":"后必须要有空格 while(fscanf(fp,"%s",operation)!=EOF){if(operation[strlen(operation)-1]==':'){operation[strlen(operation)-1]='\0';temp = malloc(sizeof(struct list));strcpy(temp->name,operation);temp->position = count;temp->next = NULL;tail->next = temp;tail = tail->next;}do{if(fscanf(fp,"%c",&ch)==EOF)break;}while(ch!='\n');count++;}fseek(fp , 0, SEEK_SET);count=0;while(fscanf(fp,"%s",operation)!=EOF){if(operation[strlen(operation)-1]==':')fscanf(fp,"%s",operation); //fscanf(fp,"%s",operands);fgets(operands,100,fp);//printf("{%s:%s}",operation,operands);if(!strcmp(operation,"add")){regregreg();instruction=0x00000020|(reg[1]<<21)|(reg[2]<<16)|(reg[0]<<11);}else if(!strcmp(operation,"sub")){regregreg();instruction=0x00000022|(reg[1]<<21)|(reg[2]<<16)|(reg[0]<<11);}else if(!strcmp(operation,"slt")){regregreg();instruction=0x0000002A|(reg[1]<<21)|(reg[2]<<16)|(reg[0]<<11);}else if(!strcmp(operation,"lw")){regimmreg();instruction=0x8C000000|(reg[2]<<21)|(reg[0]<<16);instruction=instruction|(((unsigned long)imm)<<16>>16);}else if(!strcmp(operation,"sw")){regimmreg();instruction=0xAC000000|(reg[2]<<21)|(reg[0]<<16);instruction=instruction|(((unsigned long)imm)<<16>>16);}else if(!strcmp(operation,"beq")){regregimm();instruction=0x10000000|(reg[1]<<21)|(reg[0]<<16);if(type==1)instruction=instruction|(((unsigned long)imm)<<16>>16);else if(type==0){//printf("(%x %x %x)",imm,count,(imm-count-1));instruction=instruction|(((unsigned long)(imm-count-1))<<16>>16);}}else if(!strcmp(operation,"j")){p=0;getimm();instruction=0x08000000|(((unsigned long)imm)<<6>>6);}else{printf("ERROR!!!\n");return 0;}fwrite(&instruction,4,1,fbi);fprintf(ftext,"%x\n",instruction);printf("%x\n",instruction);count++;}return 0;} 
0 0
原创粉丝点击