系統程式上機練習題,這個程式主要是仿組譯器的製作,當然這個簡單太多了。程式是這個樣子的,如果我們再筆記本上輸入組合語言的程式碼,經由這個程式會自動幫我們轉成機器看得懂的目的碼。
因為我是在考試前一天趕出來的,所以程式碼並沒有寫得很好,可能可以寫得再精簡一點,不過最近考試很多沒什麼時間可以改。
abc.txt的內容如下:
copy start 1000
first stl retaddr
cloop sub data1
lda length
comp zero
beq cloop
data1 byte 55 66
length byte 7
byte 99
zero byte 0
retaddr byte 0 0 0
copy start 1000
first stl retaddr
cloop sub data1
lda length
comp zero
beq cloop
data1 byte 55 66
length byte 7
byte 99
zero byte 0
retaddr byte 0 0 0
程式碼大致上如下:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <cstdlib>#include <iostream>
typedef struct _sym {int line, count,address;char item[10][20];struct _sym *next;} SymbolTable;SymbolTable *phead,*ptr,*pNew;/*產生新空間*/struct _sym *creat(int line){SymbolTable *New;// 宣告一個節點指標New = (SymbolTable *)malloc(sizeof(SymbolTable)); // 指標指向一個新的結構記憶體New->line = line;New->next= NULL;return (New); // 傳回New指標}/*反轉單項鏈結副程式*/struct _sym *invert(SymbolTable *phead){SymbolTable *middle,*trail;middle=NULL;while(phead){trail=middle;middle=phead;phead=phead->next;middle->next=trail;}return middle;}/*利用找相對應的字做文字檔案的搬移動作*/typedef struct _opcode{char opname[10];char *code;} operation;operation op[10] = {{"add","18"},{"sub","1c"},{"stl","14"},{"lda","00"},{"comp","28"},{"beq","10"}};
void begin_parsing(FILE *fp){int i;for (i=1; !feof(fp); i++){char buffer[200];fgets(buffer,200,fp);if(i==1){//用來存開始的指標phead = creat(i);ptr = phead;}else{pNew = creat(i);ptr->next= pNew;ptr = pNew;}
int j=0;char *pch;pch = strtok (buffer," ,.\t\n");while (pch != NULL){//將字串寫入strcpy(ptr->item[j],pch);pch = strtok(NULL, " ,.\t\n");j++;}ptr->count=j;}
}
int main(int argc, char *argv[]){FILE *fp,*fp1;fp=fopen("abc.txt", "r");fp1=fopen("cde.txt","w");fclose(fp1);begin_parsing(fp);fclose(fp);
printf("Praising .....\n");printf("ln\t(addr)\t(ct):\tfield1\tfield2\tfield3\t\t\top\n");
/********************************排版******************************/int addcount=0,cal;ptr=phead;char *pch1;while(phead != NULL)// 直到phead== NULL時跳出{int m=0,i,n=0;for(i=phead->count;i>0;i--){m++;n++;//判斷有沒有字}
if (0==strcmp(phead->item[1],"start"))//比較字串是否為start{sscanf(phead->item[2],"%x",&addcount);phead->address=addcount;goto next;}
phead->address=addcount;if (0==strcmp(phead->item[1],"byte"))//比較字串是否為bytem=m-2;addcount+=m;//加上位址next:if(n==0)//假如遇到沒有字的,則指向下個指標{phead=phead->next;continue;}int num;char a[1]={0};for(num=0;num<6;num++){//如果第一個字為指令時if(0==strcmp(phead->item[0],op[num].opname)){cal=phead->count;for(cal;cal>0;cal--)strcpy(phead->item[cal],phead->item[cal-1]);pch1=&a[0];strcpy(phead->item[0],pch1);phead->count++;n=phead->count;addcount++;}}if(0==strcmp(phead->item[0],"byte")){//假如第一個字是BYTE時cal=phead->count;for(cal;cal>0;cal--)strcpy(phead->item[cal],phead->item[cal-1]);pch1=&a[0];strcpy(phead->item[0],pch1);phead->count++;n=phead->count;addcount--;}phead->count=n;cal=phead->line;phead=phead->next;//指向下個指標}
/*******************做文字替換**************************/phead = ptr;int i=0,sav;char *pch;while(phead != NULL){
pch=phead->item[2];sav=phead->line;//存放現在所在行數,以供等等回來用int addresschange=0;//用來存放等等如果找到一樣的字的address值phead = ptr;for(i=0;i<cal;i++)//找相同的字{if(0==strcmp(pch,phead->item[0])){addresschange=phead->address;break;}phead=phead->next;
}if(addresschange==0)//0表示沒找到一樣的字{phead = ptr;for(i=1;i<sav+1;i++){phead=phead->next;}if(phead->count==0&&phead->line<cal+1){//判斷下一行文字是不是空的字串phead=phead->next;//如果是空字串則在往下一個指標指向continue;}else if(phead->line>cal)//如果已經找到最後一行了,則可以跳出準備開始印出break;}else{//表示addresschange有值,也就是有找到相同的文字phead=ptr;for(i=1;i<sav;i++)//回到原來位置{phead=phead->next;}sprintf(pch,"%x",addresschange);//將值先放到pch中strcpy(phead->item[2],pch);//再把值丟給item
}addresschange=0;//將addresschange清空,以便下次繼續找尋phead=phead->next;//指向下個指標
}
/*********************印出********************/int m,n,num;phead = ptr;for(i=0;i<cal;i++) {printf("%2d\t",phead->line);printf("(%x)\t",phead->address);printf("(%d)\t",phead->count);
m=0;for(i=phead->count;i>0;i--)//將字串印出{printf("%s\t",phead->item[m]);m++;}//另外如果要印出運算碼則用以下程式for(num=0;num<6;num++){if(0==strcmp(phead->item[1],op[num].opname)){if(m==4)printf("\t%s%s",op[num].code,phead->item[2]);else if(m==5)printf("%s%s",op[num].code,phead->item[2]);else if(m==3)printf("\t\t%s%s",op[num].code,phead->item[2]);}}if(0==strcmp(phead->item[1],"byte")){if(m==4)printf("\t%s%s",phead->item[2],phead->item[3]);else if(m==5)printf("%s%s%s",phead->item[2],phead->item[3],phead->item[4]);else if(m==3)printf("\t\t%s%s",op[num].opname,phead->item[2]);}//
printf("\n");phead=phead->next;if(phead->count==0&&phead->line<cal)//避免印到空的字串phead=phead->next;if(phead->line>cal)break;}
printf("\n");system("PAUSE");return 0;}
沒有留言:
張貼留言
俗話說
凡走過必留下痕跡,凡住過必留下鄰居
凡爬過必留下樓梯,凡來過必留下IP
看過文章之後歡迎留下您寶貴的意見喔!