#include #include #include #include #include #include "asm.h" #include "defines.h" #include "main.ext" #include "structs.h" #include "externs.h" #include "asm.pro" ///////////////////////////////////////////////////////////////////////////// void assemble() { clrscr(); gotoxy(30,8); printf("\nEnter Source filename"); //gets(SrcFile); strcpy(SrcFile, "source.asm"); if(access(SrcFile, EXIST) == 0 ) passone(SrcFile); } ///////////////////////////////////////////////////////////////////////////// FILE * In_Ptr, * Out_Ptr; UWORD passone(UBYTE * input_filename) { UBYTE output_filename[MAX_FILENAME]; UBYTE more_input; UBYTE line[MAX_LINE]; UBYTE * line_ptr; UBYTE instruction_number; UBYTE * nl_loc; UBYTE error; UBYTE pseudo_status; memset(output_filename, NULL, sizeof(output_filename) ); memset(SymTabPtr, 0, sizeof(MAX_INSTRUCTIONS * sizeof(Instruction) ) ); // allocated in main() memset(line, NULL, sizeof(line) ); strcpy(output_filename, "passone.out"); if( openfiles(input_filename, output_filename) != ERROR) { // Inits instruction_number = 0; SymTabPtr[instruction_number].lctr = LOC_CTR_START; error = FALSE; more_input = TRUE; while( !feof(In_Ptr) && (more_input) && (!error) ) { memset(line, NULL, sizeof(line) ); fgets(line, sizeof(line),In_Ptr); // read in line from input file line_ptr = line; swapchars(line_ptr, TAB, SPACE); // replace tabs with spaces if(*line_ptr != NEWLINE) { nl_loc = strchr(line_ptr, NEWLINE); if(nl_loc) { *nl_loc = NULL; // replace newline with NULL } if(save_for_pass_two(line_ptr) == LINE_IS_NOT_COMMENT) { check_for_symbol(&line_ptr,SymTabPtr->symbol); if(extract_opcode(&line_ptr, &SymTabPtr->opcode ) == OK) { calc_instruction_length(&line_ptr,SymTabPtr); if( instruction_number ) SymTabPtr->lctr = ( (SymTabPtr - 1)->lctr + ( (SymTabPtr - 1)->instr_len) ); } else if( (pseudo_status = check_for_pseudo_op(&line_ptr, SymTabPtr)) == HALT ) more_input = FALSE; else if( pseudo_status != OK ) error = TRUE; } SymTabPtr++; instruction_number++; } } // end while } else return(ERROR); fclose(Out_Ptr); return(OK); } ///////////////////////////////////////////////////////////////////////////// UBYTE openfiles(UBYTE * in_file, UBYTE * out_file) { if ((In_Ptr = fopen(in_file, "rt")) == NULL) { printf("\nError Opening Input file %s", in_file); pause(); return(ERROR); } else { if ((Out_Ptr = fopen(out_file, "wt")) == NULL) { printf("\nError Opening PassOne Output file %s", out_file); pause(); return(ERROR); } } return(OK); } ///////////////////////////////////////////////////////////////////////////// UBYTE save_for_pass_two(UBYTE * current_line) { UBYTE * symbol_loc; get_next_symbol(¤t_line); if( (symbol_loc = strchr(current_line, SYMBOL_TERM)) ) { // strip off symbol, it's in the Symbol Table current_line = symbol_loc; get_next_symbol(¤t_line); } if( !check_for_comment(current_line) ) { // is this line a comment ? fprintf(Out_Ptr,"%s\n", current_line); // no, then write to output file for passtwo() fflush(Out_Ptr); return(LINE_IS_NOT_COMMENT); } else return(LINE_IS_COMMENT); } ///////////////////////////////////////////////////////////////////////////// UBYTE check_for_comment(UBYTE * line) { UBYTE offset = 0; while( *(line+offset) == SPACE) // find the first character that is NOT a space offset++; if( *(line+offset) == COMMENT_CHAR) // check to see if it is a comment line or not return(LINE_IS_COMMENT); else { line = (line+offset); // move ptr to first NON space character return(LINE_IS_NOT_COMMENT); } } ///////////////////////////////////////////////////////////////////////////// void check_for_symbol(UBYTE * * line, UBYTE * symbol_ptr) { UBYTE x; UBYTE * symbol; get_next_symbol(line); // move ptr to first NON space character strcpy(Temp, *line); if(*line != NULL ) { strupr(*line); if( (symbol = strchr(Temp, SYMBOL_TERM)) != NULL) { *symbol = NULL; // now we can treat it as a string strcpy(symbol_ptr, Temp); // put symbol into symbol table *line = strchr(*line, SYMBOL_TERM); get_next_symbol(line); } } } ///////////////////////////////////////////////////////////////////////////// // Find the first text word in a line so we can identify it as a symbol or opcode later void get_next_symbol(UBYTE * * line) { *line = strchr(*line, SPACE); if(*line != NULL) { while( ( **line == SPACE) && (*line != NULL) && ( **line != NEWLINE) ) (*line)++; } } ///////////////////////////////////////////////////////////////////////////// void swapchars(UBYTE * line, UBYTE before, UBYTE after) { UBYTE x = 0; while( (*line != NULL) && (*line != NEWLINE) && (x++ < MAX_LINE) ) { if(*line == before) // if tab *line = after; /// replace with space line++; } } ///////////////////////////////////////////////////////////////////////////// UBYTE extract_opcode(UBYTE * * line, UBYTE * opcode) { if( check_for_opcode(line, opcode) == OK ) { return(OK); } else return(ILLEGAL_OPCODE); } ///////////////////////////////////////////////////////////////////////////// UBYTE check_for_opcode(UBYTE * *line, UBYTE * opcode_ptr) { UBYTE x; for(x=0; x < MAX_OPCODES; x++) { if( strstr(*line, Opcodes[x].name) ) { *opcode_ptr = Opcodes[x].val; get_next_symbol( line); return(OK); } } return(ERROR); } ///////////////////////////////////////////////////////////////////////////// void calc_instruction_length(UBYTE * * line, Instruction * inst) { switch(inst->opcode) { case HLT : inst->instr_len = ONE_BYTE; break; case LOD : case ADD : if( strchr(*line, IMMEDIATE_MODE) != NULL) { inst->instr_len = MODE1_LENGTH; } else { inst->instr_len = MODE0_LENGTH; } break; case STO : inst->instr_len = MODE0_LENGTH; break; case OUT : inst->instr_len = NO_MODE_LENGTH; break; case CALL : inst->instr_len = MODE0_LENGTH; break; case JZE : inst->instr_len = MODE0_LENGTH; break; case JMP : inst->instr_len = MODE0_LENGTH; break; case RET : inst->instr_len = ONE_BYTE; break; default : inst->instr_len = ILLEGAL_INSTRUCTION; break; } } ///////////////////////////////////////////////////////////////////////////// UBYTE check_for_pseudo_op(UBYTE * * line, Instruction * inst) { Instruction * ptr; ptr = inst; ptr --; // point to last instruction's location so we can use it to determine the // value for this Pseudo Op if( strstr( *line, "DC") ) { get_next_symbol(line); // move ptr to first NON space character inst->value = atoi(*line); inst->lctr += ( (ptr->lctr) + 2 ); inst->pseudo = DC; } else if( strstr( *line, "DS") ) { get_next_symbol(line); // move ptr to first NON space character inst->value = atoi(*line); inst->lctr += ( (ptr->lctr) + inst->value ); inst->pseudo = DS; } else if( strstr( *line, "END") ) { get_next_symbol(line); inst->pseudo = END; return(HALT); } else return(ERROR); return(OK); } ///////////////////////////////////////////////////////////////////////////// UBYTE get_reg_num(UBYTE * * line) { UBYTE register_num; if(**line == 'R') { (*line)++; // when we enter this function, line should point to the first operand if( ( (**line) >= R0) && ( (**line) <= R3) ) { register_num = ( (**line) - ASCII_TO_DEC); skip_over_comma(line); // move pointer to second operand return( register_num ); } } return(ILLEGAL_REGISTER); } ///////////////////////////////////////////////////////////////////////////// void skip_over_comma(UBYTE * * line) { while(strchr(*line, COMMA) != NULL) (*line)++; } ///////////////////////////////////////////////////////////////////////////// UBYTE check_for_immediate_mode(UBYTE * * line, Instruction * inst) { if( (inst->opcode == LOD) || (inst->opcode == ADD) ) { // immediate mode is only valid for LOD/ADD if(strchr(*line, IMMEDIATE_MODE) ) return(TRUE); } return(FALSE); } ///////////////////////////////////////////////////////////////////////////// UWORD passtwo() { return(1); } /////////////////////////////////////////////////////////////////////////////