The following functions are provided for your benefit. Feel free
to use them if you want. You are not required to use any of this code. It
is provided to help you brush up on your C skills and to prevent you from spending a lot of effort writing a
parser for your assembler.
To use the code provided below you need to include the following files in your code:
#include <stdio.h> /* standard input/output library */ #include <stdlib.h> /* Standard C Library */ #include <string.h> /* String operations library */ #include <ctype.h> /* Library for useful character operations */
Convert a string into a number
Hex numbers must be in the form "x3000", and decimal numbers must be
in the form "#30"
int toNum( char * pStr ) { char lBuf[10]; int lNum, lNeg = 0; if( *pStr == '#' ) /* decimal */ return atoi( pStr + 1 ); else if( *pStr++ == 'x' || *pStr++ == 'X' ) /* hex */ { if( *pStr == '-' ) /* hex is negative */ { lNeg = 1; pStr++; } sprintf( lBuf, "0x%s", pStr ); /* convert hex into decimal */ sscanf( lBuf, "%i", &lNum ); if( lNeg ) lNum = -lNum; return lNum; } else { printf( "Error: unknown constant, %s\n", pStr); exit( 3 ); } }
Another function to convert a string into a number
int toNum(char * pStr) { if (*pStr == '#') return strtol(pStr + 1, NULL, 10); else if (*pStr == 'x' || *pStr == 'X') { if (*pStr + 1 == '-') return -strtol(pStr + 2, NULL, 16); else return strtol(pStr + 1, NULL, 16); } else { printf("Error: unknown constant, %s\n", pStr); exit(3); } }
Take a line of the input file and parse it into corresponding
fields. Note that you need to write the isOpcode(char*) function which
determines whether a string of characters is a valid opcode.
#define MAX_LINE_LENGTH 255 enum { DONE, OK, EMPTY_LINE }; int readAndParse( FILE * pInfile, char * pLine, char ** pLabel, char ** pOpcode, char ** pArg1, char ** pArg2, char ** pArg3, char ** pArg4 ) { char * lRet, * lPtr; int i; if( !fgets( pLine, MAX_LINE_LENGTH, pInfile ) ) return( DONE ); for( i = 0; i < strlen( pLine ); i++ ) pLine[i] = tolower( pLine[i] ); /* convert entire line to lowercase */ *pLabel = *pOpcode = *pArg1 = *pArg2 = *pArg3 = *pArg4 = pLine + strlen(pLine); /* ignore the comments */ lPtr = pLine; while( *lPtr != ';' && *lPtr != '\0' && *lPtr != '\n' ) lPtr++; *lPtr = '\0'; if( !(lPtr = strtok( pLine, "\t\n ," ) ) ) return( EMPTY_LINE ); if( isOpcode( lPtr ) == -1 && lPtr[0] != '.' ) /* found a label */ { *pLabel = lPtr; if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK ); } *pOpcode = lPtr; if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK ); *pArg1 = lPtr; if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK ); *pArg2 = lPtr; if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK ); *pArg3 = lPtr; if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK ); *pArg4 = lPtr; return( OK ); } /* Note: MAX_LINE_LENGTH, OK, EMPTY_LINE, and DONE are defined values */ To call readAndParse, you would use the following:
func() { char lLine[MAX_LINE_LENGTH + 1], *lLabel, *lOpcode, *lArg1, *lArg2, *lArg3, *lArg4; int lRet; FILE * lInfile; lInfile = fopen( "data.in", "r" ); /* open the input file */ do { lRet = readAndParse( lInfile, lLine, &lLabel, &lOpcode, &lArg1, &lArg2, &lArg3, &lArg4 ); if( lRet != DONE && lRet != EMPTY_LINE ) { ... } } while( lRet != DONE ); }
To write to your output file, you can use the following:FILE * pOutfile; pOutfile = fopen( "data.out", "w" ); ... fprintf( pOutfile, "0x%0.4X\n", lInstr ); /* where lInstr is declared as an int */