예제 #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 memory.
    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 */
    char buf[BUF_SIZE];
    uint32_t input_line = 0, byte_offset = 0;
    int ret_code = 0;


     // Read lines and add to instructions
    while(fgets(buf, BUF_SIZE, input)) {
        input_line++;

        // Ignore comments
        skip_comment(buf);

        // Scan for the instruction name
    	char* token = strtok(buf, IGNORE_CHARS);

        // Scan for arguments
        char* args[MAX_ARGS];
        int num_args = 0;

    	// Checks to see if there were any errors when writing instructions
        unsigned int lines_written = write_pass_one(output, token, args, num_args);
        if (lines_written == 0) {
            raise_inst_error(input_line, token, args, num_args);
            ret_code = -1;
        } 
        byte_offset += lines_written * 4;
    }       
    return -1;
}
예제 #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) {
    //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;
    }
}
예제 #3
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;
}