Exemple #1
0
/* First pass of the assembler. You should implement pass_two() first.

   This function should read each line, strip all comments, scan for labels,
   and pass instructions to write_pass_one(). The input file may or may not
   be valid. Here are some guidelines:

    1. Only one label may be present per line. It must be the first token present.
        Once you see a label, regardless of whether it is a valid label or invalid
        label, treat the NEXT token as the beginning of an instruction.
    2. If the first token is not a label, treat it as the name of an instruction.
    3. Everything after the instruction name should be treated as arguments to
        that instruction. If there are more than MAX_ARGS arguments, call
        raise_extra_arg_error() and pass in the first extra argument. Do not 
        write that instruction to the output file (eg. don't call write_pass_one())
    4. Only one instruction should be present per line. You do not need to do 
        anything extra to detect this - it should be handled by guideline 3. 
    5. A line containing only a label is valid. The address of the label should
        be the byte offset of the next instruction, regardless of whether there
        is a next instruction or not.

   Just like in pass_two(), if the function encounters an error it should NOT
   exit, but process the entire file and return -1. If no errors were encountered, 
   it should return 0.
 */
int pass_one(FILE* input, FILE* output, SymbolTable* symtbl) {
    //my own: setting the buffer and putting the input into it
    char buf[BUF_SIZE];
    fgets(buf, BUF_SIZE, input);

    //my own: lines start at 1, and the byte offset at 0
    uint32_t byte_offset = 0;
    int line_number = 1;

    //my own: tokenize by lines first
    strtok(buf, "\n");
    while (strcmp(buf, "") == 0) {
	line_number++;
	strtok(buf, "\n");
    }
    int errored = 0;
    while (buf != NULL) {
	skip_comment(buf); //myown: gets rid of comments for every line
	//my own: tokenize now by the args in each line
	char* args[50];
	int num_args = 0;
	//my own: set it to 50, because... whos stupid enough to put in 50 args in MIPS... only idiots
	//my own: just have to do this because if the num_args > args size, GG. NO FIT.
	strtok(buf, " :,\n"); //myown: all the delimiters that could in MIPScode " :, and an new line"
	num_args = sizeof(args)/sizeof(args[0]);
	if (num_args > MAX_ARGS) {
	    raise_extra_arg_error(line_number, args[1]);
	    errored++;
	}
	int label1 = add_if_label(line_number, args[0], byte_offset, symtbl);
	int label2 = add_if_label(line_number, args[1], byte_offset, symtbl);
	if (label1 == -1) {
	    errored++;
	    line_number++;
	    strtok(buf, "\n");
	} else if (label2 == 1) {
	    raise_extra_arg_error(line_number, args[1]);
	    errored++;
	    line_number++;
	    strtok(buf, "\n");
	} else if (label1 == 0) { //Myown:It's not a label. Treat like a reg instruction
	    //Myown: pass in instructions into write_pass_one
	    write_pass_one(output, args[0], args, num_args);
	    byte_offset += 4;
	} else if (label1 == 1) {
	    //My own: Adding label to the symbol table
	    add_to_table(symtbl, args[0], byte_offset);
	    byte_offset += 4;
	}
	line_number++;
	strtok(buf, "\n");
    }
    if (errored > 0) {
	return -1;
    } else {
	return 0;
    }
}
Exemple #2
0
/* First pass of the assembler. You should implement pass_two() first.

   This function should read each line, strip all comments, scan for labels,
   and pass instructions to write_pass_one(). The input file may or may not
   be valid. Here are some guidelines:

    1. Only one label may be present per line. It must be the first token present.
        Once you see a label, regardless of whether it is a valid label or invalid
        label, treat the NEXT token as the beginning of an instruction.
    2. If the first token is not a label, treat it as the name of an instruction.
    3. Everything after the instruction name should be treated as arguments to
        that instruction. If there are more than MAX_ARGS arguments, call
        raise_extra_arg_error() and pass in the first extra argument. Do not 
        write that instruction to the output file (eg. don't call write_pass_one())
    4. Only one instruction should be present per line. You do not need to do 
        anything extra to detect this - it should be handled by guideline 3. 
    5. A line containing only a label is valid. The address of the label should
        be the byte offset of the next instruction, regardless of whether there
        is a next instruction or not.

   Just like in pass_two(), if the function encounters an error it should NOT
   exit, but process the entire file and return -1. If no errors were encountered, 
   it should return 0.
 */
int pass_one(FILE* input, FILE* output, SymbolTable* symtbl) {
	/* YOUR CODE HERE */
	int err = 0;
	char buf[BUF_SIZE];

	uint32_t line_no = 0;
	uint32_t addr = 0;       // label addr

	while(fgets(buf, BUF_SIZE, input) != NULL) {

		line_no++;

		// strip comments
		skip_comment(buf);

		if(strlen(buf) == 0) continue;

		char* args[MAX_ARGS];
		int num_args = 0;
		char nbuf[BUF_SIZE];    // buf for line with no label
		char instr[BUF_SIZE];   // instruction string
		char label[BUF_SIZE];   // label string
		instr[0] = '\0';
		label[0] = '\0';

		strcpy(nbuf, buf);
		char * pch;
		pch = strtok (buf, IGNORE_CHARS);   // buf is clobbered

		if(pch == NULL) continue;

		strcpy(label, pch);   // first pch maybe  label

		int res = add_if_label(line_no,  label, addr, symtbl);
		printf("Label1: %s\n", label);
		if( res  == 0) {
			label[0] = '\0';
		}
		else {

			if(res == -1)  {
				err = -2;
				raise_label_error(line_no,  label);
			}


			char* tmp = strstr(nbuf, label);
			strcpy(nbuf, tmp + strlen(label) + 1);
			printf("Label2: %s\n", label);
		}

		printf("nbuf (for instruction) : %s\n", nbuf);

		pch = strtok (nbuf, IGNORE_CHARS);

		if(pch != NULL) {

			strcpy(instr, pch);   // first is instruction string

			pch = strtok (NULL, IGNORE_CHARS);

			while (pch != NULL) { // following is arguments
				args[num_args++] = strdup(pch);
				pch = strtok (NULL, IGNORE_CHARS);
				if(num_args > MAX_ARGS ) {
					raise_extra_arg_error(line_no, args[num_args]);
					err = -3;
					break;
				}
			}

#if 0
			printf("instr: %s\n", instr);

			printf("num_args: %d\n", num_args);

			printf("args:\n");

			for(int i = 0; i < num_args; i++)
				printf("\t %s", args[i]);

			printf("addr: %d\n", addr);
#endif

			if(err != -3) {

				int num_instr = write_pass_one(output, instr,  args, num_args);

				addr += 4 * num_instr;
				printf("addr: %d\n", addr);

				if( num_instr == 0)  {
					raise_inst_error(line_no, instr, args, num_args);
					err = -1;
				}
			}

			// free memeory in args

			for(int i = 0; i < num_args; i++)
				free(args[i]);

		}

	}

	return  err < 0 ? -1 : 0;
}