Code:
/*==========================================================
*
* Program Purpose: To implement a two pass assembler
*
*============================================================
*
* Date Started: 8 April 2015
* Date Completed: April 2015
*
*============================================================
*
* Variable Dictionary:
*
*============================================================
*
* Input file(s): proj1b.dat
* Output file(s): proj1b.out
*
*============================================================
*
* Sample input:
* .st //start of assembly
* STRT LOD 0 R0 M10 //load the constant 10 into R0 (instr. is at offset 0)
* STO 0 R0 M8 //Store the value from R0 into location M8
* LOD 0 R1 M11 //load the constant 3 into R1
* SUB R0 R1 R0 //subtract R1 from R0 giving R0 (the result is 7)
* LOD 0 R3 M12 //load R3 with 2
* JGT 0 R0 EXIT //jump on R0 greater than 0 to exit
* STO 0 R1 M9 //otherwise store in location M9
* EXIT HLT //halt the program
* M8 .dw 0 //storage area for constants and variables
* M9 .dw 0
* M10 .dw 10
* M11 .dw 3
* M12 .dw 2
* .nd //end of assembly
*
* Sample Output:
*============================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
//function declarations
void buildSymbolTable();
void buildInstructions();
void formatOne(char* str, int offset);
void formatTwo(char* str);
int lookup(char* key);
void dataDeclaration(char* str);
void printBits(int width, int num);
void output();
//global variables
int instrOffset[50]; //instruction offsets with memory addresses
FILE *ofp;//file proj1b.dat
int main(){
printf("start");
ofp = fopen("proj1b.out", "r+");
printf("file opened");
buildSymbolTable(); //first pass
printf("SymbolTable built");
buildInstructions(); //second pass
printf("instructions built");
output();
output();
return 0;
}
void buildSymbolTable(){
//first pass through code
FILE *ifp;
FILE *ofp;
ifp = fopen("proj1b.dat", "r"); //input file TODO: change to "../instr/proj1a.dat" before submitting
ofp = fopen("symbolTable.dat", "w"); //output file
char symbolTable[50][6] = {0};
//validates file exists
if (ifp == NULL)
{
perror("../instr/proj1b.dat");
exit(0);
}
char str[100] = {0};//current line from file
int j = 0; //offset of current symbol
int i = 0;
while(fgets(str, sizeof(str), ifp) != NULL){
if(!isspace(str[0])){
for(i = 0; i < 6; i++){
if(!isspace(str[i])){
symbolTable[j][i] = str[i];
}
}
fprintf(ofp,"%-6s %d\n", symbolTable[j], j - 1);
}
j++;
}
fclose(ifp);
fclose(ofp);
}
void buildInstructions(){
FILE *ifp;
ifp = fopen("proj1b.dat", "r"); //input file TODO: change to "../instr/proj1a.dat" before submitting
//validates file(s) exists
if (ifp == NULL)
{
perror("../instr/proj1b.dat");
exit(0);
}
memset(instrOffset, -1, sizeof(instrOffset));//clear substr
int addrIndex = -1; //index of address, for addresses with memory addresses
int arrIndex = 0; //index of array
char str[100] = {0};//current line from file
char substr[4] = {0};//line from file sans label and comments
while(fgets(str, sizeof(str), ifp) != NULL){
memset(substr, 0, sizeof(substr));//clear substr
strncpy(substr, str+7, 3);//get first three chars
substr[4] = '\0';//add null terminating char
int format = -1; //0 if format 1, 1 if format 2
//Format 1
if(strcmp(substr, "LOD") == 0){
fprintf(ofp, "0000");
instrOffset[arrIndex] = addrIndex;
formatOne(str, arrIndex);
arrIndex++;
}
else if(strcmp(substr, "STO") == 0){
fprintf(ofp, "0001");
instrOffset[arrIndex] = addrIndex;
formatOne(str, arrIndex);
arrIndex++;
}
else if(strcmp(substr, "JMP") == 0){
fprintf(ofp, "1001");
instrOffset[arrIndex] = addrIndex;
formatOne(str, arrIndex);
arrIndex++;
}
else if(strcmp(substr, "JEQ") == 0){
fprintf(ofp, "1010");
instrOffset[arrIndex] = addrIndex;
formatOne(str, arrIndex);
arrIndex++;
}
else if(strcmp(substr, "JGT") == 0){
fprintf(ofp, "1011");
instrOffset[arrIndex] = addrIndex;
formatOne(str, arrIndex);
arrIndex++;
}
else if(strcmp(substr, "JLT") == 0){
fprintf(ofp, "1100");
formatOne(str, addrIndex);
instrOffset[arrIndex] = addrIndex;
arrIndex++;
}
//Format 2
else if(strcmp(substr, "ADD") == 0){
fprintf(ofp, "0010");
formatTwo(str);
}
else if(strcmp(substr, "SUB") == 0){
fprintf(ofp, "0011");
formatTwo(str);
}
else if(strcmp(substr, "MOV") == 0){
fprintf(ofp, "0100");
formatTwo(str);
}
else if(strcmp(substr, "SAX") == 0){
fprintf(ofp, "0101");
formatTwo(str);
}
else if(strcmp(substr, "SHL") == 0){
fprintf(ofp, "0110");
formatTwo(str);
}
else if(strcmp(substr, "SHR") == 0){
fprintf(ofp, "0111");
formatTwo(str);
}
else if(strcmp(substr, "NOT") == 0){
fprintf(ofp, "1000");
formatTwo(str);
}
else if(strcmp(substr, "CLR") == 0){
fprintf(ofp, "1110");
formatTwo(str);
}
else if(strcmp(substr, "HLT") == 0){
fprintf(ofp, "1111");
formatTwo(str);
}
//.dw
else if(strcmp(substr, ".dw") == 0){//.dw
dataDeclaration(str);
}
fprintf(ofp, "\n");
addrIndex++;
}
fclose(ofp);
fclose(ifp);
}
int lookup(char* key){
//looks up the location of the symbol in symbolTable.dat.
//If it is not in the file, returns -1
FILE *lookup;
lookup = fopen("symbolTable.dat", "r");
char str[100] = {0};//current line from file
char symbol[5] = {0};
char num[4] = {0};//location
int loc = -1;
while(fgets(str, sizeof(str), lookup) != NULL){
strncpy(symbol, str, 4);
symbol[5] = '\0';
if(strcmp(symbol, key) == 0){
strncpy(num, str+7, 2);//get location
num[4] = '\0';
loc = strtol(num, NULL, 10);
}
}
return loc;
}
void formatOne(char* str, int offset){
FILE *und;
und = fopen("undefinedTable.dat", "w");
char flag[2] = {0};
char reg[2] = {0};
char mem[4] = {0};
strncpy(flag, str+11, 1);//get flag
flag[1] = '\0';//add null terminating char
fprintf(ofp, "%s", flag);
strncpy(reg, str+14, 1);//get reg
reg[1] = '\0';//add null terminating char
printBits(3, strtol(reg, NULL, 10));
fprintf(ofp, "+");//indicates memory address
strncpy(mem, str+16, 4);//get mem address
mem[4] = '\0';//add null terminating char
int pos = lookup(mem);
if(pos != -1){
printBits(8, pos);
}
else{
printf("undefined: %s, pos: %d\n\n", mem, offset);
fprintf(ofp, "UUUUUUUU");
fprintf(und, "%s ", mem);
fprintf(und, "%d\n", offset);
}
fclose(und);
}
void formatTwo(char* str){
char rleft[2] = {0};
char rlmid[2] = {0};
char rrmid[2] = {0};
char rright[2] = {0};
strncpy(rleft, str+12, 1);//get rleft
rleft[1] = '\0';//add null terminating char
printBits(3, strtol(rleft, NULL, 10));
strncpy(rlmid, str+15, 1);//get rlmid
rlmid[1] = '\0';//add null terminating char
printBits(3, strtol(rlmid, NULL, 10));
strncpy(rrmid, str+18, 1);//get rrmid
rrmid[1] = '\0';//add null terminating char
printBits(3, strtol(rrmid, NULL, 10));
strncpy(rright, str+21, 1);//get rright
rright[1] = '\0';//add null terminating char
printBits(3, strtol(rright, NULL, 10));
}
void dataDeclaration(char* str){
char num[11];
strncpy(num, str+11, 10);//get flag
num[11] = '\0';//add null terminating char
printBits(16, strtol(num, NULL, 10));
}
void printBits(int width, int num){
//prints the bits of an int with width of int width (left padded with zeros) to proj1b.out
int i = 0;
for(i = width - 1; i >= 0; i--){
if(num & (1 << i)){ //checks i-th bit (starting at 0)
fprintf(ofp, "1");
}
else{
fprintf(ofp, "0");
}
}
}
void output(){
FILE *ifp;
FILE *ofp;
FILE *lookup;
FILE *und;
ifp = fopen("proj1b.dat", "r"); //input file TODO: change to "../instr/proj1a.dat" before submitting
ofp = fopen("proj1b.out", "r");
und = fopen("undefinedTable.dat", "r");
lookup = fopen("symbolTable.dat", "r"); //input file
char str[100] = {'\0'};//current line from assem file
char str2[19] = {'\0'};//current line from machine code file
int chars = 0;//number of chars to print
int j = 0;
printf("OFFSET ASM-INSTRUCTION MACHINE-INSTRUCTION\n");
while(fgets(str, sizeof(str), ifp) != NULL){
chars = 25;
//print offset
printf("%-2d (0x%02x) ", j, j);
//print assem code
int i = 0;
while(str[i] != '/' && str[i] != '\n' && i < 22){
printf("%c", str[i]);
i++;
chars--;
}
while(chars >= 0){
printf(" ");
chars--;
}
//print machine code
fgets(str2, sizeof(str2), ofp);
printf("%s", str2);
printf("\n");
j++;
}
//print symbol table
printf("\nSYMBOL TABLE:\n");
printf("SYMBOL LOCATION\n");
while(fgets(str, sizeof(str), lookup) != NULL){
printf("%s", str);
}
//print undefined table
printf("\nUNDEFINED TABLE:\n");
printf("SYMBOL LOCATION\n");
while(fgets(str, sizeof(str), und) != NULL){
printf("%s", str);
}
//print multiple table
printf("\nMULTIPLE TABLE:\n");
printf("SYMBOL LOCATION\n");
//print instruction offsets with memory addresses
printf("\nINSTRUCTION OFFSETS WITH MEMORY ADDRESSES\n");
int ind = 0;
for(ind = 0; ind < 50; ind++){
if(instrOffset[ind] != -1){
printf("%d ", instrOffset[ind]);
}
}
fclose(ofp);
fclose(ifp);
fclose(lookup);
}
Here's proj1b.dat: