My Microprocessor class instructor gave us an assignment and said: Write an Assembler in C. - My beloved ProfessorSo it seemed a little bit illogical to me.If I'm not wrong Assembly Language is the first step from Machine Code to the journey of higher level languages. I mean C is higher level language than Assembly. So what is the point of writing an Assembler in C? What were they doing in the past while the absence of C language? Were they writing Assembler in Machine Code? It doesn't make sense to me writing a machine code translator for a low level language in a higher level language.Let's say we have created a brand new microprocessor architecture that there is not even a C compiler for that architecture. Will our Assembler that written in C be able simulate the new architecture? I mean will it be useless or not?By the way I'm aware that GNU Assembler and Netwide Assembler have been written in C. I am also wondering why they are written in C?Lastly this is the example source code for a simple assembler that our Professor gave to us:// to compile, gcc assembler.c -o assembler// No error check is provided.// Variable names cannot start with 0-9.// hexadecimals are twos complement.// first address of the code section is zero, data section follows the code section.//fout tables are formed: jump table, ldi table, label table and variable table.#include <stdio.h>#include <stdlib.h>#include <string.h>//Converts a hexadecimal string to integer.int hex2int( char* hex)  {    int result=0;    while ((*hex)!='\0')    {        if (('0'<=(*hex))&&((*hex)<='9'))            result = result*16 + (*hex) -'0';        else if (('a'<=(*hex))&&((*hex)<='f'))            result = result*16 + (*hex) -'a'+10;        else if (('A'<=(*hex))&&((*hex)<='F'))            result = result*16 + (*hex) -'A'+10;         hex++;    }    return(result);}main(){       FILE *fp;        char line[100];        char *token = NULL;    char *op1, *op2, *op3, *label;    char ch;    int  chch;    int program[1000];    int counter=0;  //holds the address of the machine code instruction// A label is a symbol which mark a location in a program. In the example // program above, the string lpp, loop and lp1 are labels.    struct label      {        int location;        char *label;    };    struct label labeltable[50]; //there can be 50 labels at most in our programs    int nooflabels = 0; //number of labels encountered during assembly.// Jump instructions cannot be assembled readily because we may not know the value of // the label when we encountered a jump instruction. This happens if the label used by// that jump instruction appear below that jump instruction. This is the situation // with the label loop in the example program above. Hence, the location of jump // instructions must be stored.    struct jumpinstruction       {        int location;        char *label;    };    struct jumpinstruction jumptable[100]; //There can be at most 100 jumps    int noofjumps=0;  //number of jumps encountered during assembly.    // The list of variables in .data section and their locations.    struct variable    {        int location;        char *name;    };    struct variable variabletable[50]; //There can be 50 varables at most.    int noofvariables = 0;//Variables and labels are used by ldi instructions.//The memory for the variables are traditionally allocated at the end of the code section.//Hence their addresses are not known when we assemble a ldi instruction. Also, the value of //a label may not be known when we encounter a ldi instruction which uses that label.//Hence, the location of the ldi instructions must be kept, and these instructions must be //modified when we discover the address of the label or variable that it uses.    struct ldiinstruction       {        int location;        char *name;    };    struct ldiinstruction lditable[100];    int noofldis=0;    fp = fopen(name_of_program,r);    if (fp != NULL)    {        while(fgets(line,sizeof line,fp)!= NULL)  //skip till .code section        {            token=strtok(line,\n\t\r );            if (strcmp(token,.code)==0 )                break;        }         while(fgets(line,sizeof line,fp)!= NULL)        {            token=strtok(line,\n\t\r );  //get the instruction mnemonic or label//========================================   FIRST PASS  ======================================================            while (token)            {                if (strcmp(token,ldi)==0)        //---------------LDI INSTRUCTION--------------------                {                    op1 = strtok(NULL,\n\t\r );                                //get the 1st operand of ldi, which is the register that ldi loads                    op2 = strtok(NULL,\n\t\r );                                //get the 2nd operand of ldi, which is the data that is to be loaded                    program[counter]=0x1000+hex2int(op1);                        //generate the first 16-bit of the ldi instruction                    counter++;                                                   //move to the second 16-bit of the ldi instruction                    if ((op2[0]=='0')&&(op2[1]=='x'))                            //if the 2nd operand is twos complement hexadecimal                        program[counter]=hex2int(op2+2)&0xffff;              //convert it to integer and form the second 16-bit                     else if ((  (op2[0])=='-') || ((op2[0]>='0')&&(op2[0]<='9')))       //if the 2nd operand is decimal                         program[counter]=atoi(op2)&0xffff;                         //convert it to integer and form the second 16-bit                     else                                                           //if the second operand is not decimal or hexadecimal, it is a laber or a variable.                    {                                                               //in this case, the 2nd 16-bits of the ldi instruction cannot be generated.                        lditable[noofldis].location = counter;                 //record the location of this 2nd 16-bit                          op1=(char*)malloc(sizeof(op2));                         //and the name of the label/variable that it must contain                        strcpy(op1,op2);                                        //in the lditable array.                        lditable[noofldis].name = op1;                        noofldis++;                                                                 }                           counter++;                                                     //skip to the next memory location                 }                                                       else if (strcmp(token,ld)==0)      //------------LD INSTRUCTION---------------------                         {                    op1 = strtok(NULL,\n\t\r );                //get the 1st operand of ld, which is the destination register                    op2 = strtok(NULL,\n\t\r );                //get the 2nd operand of ld, which is the source register                    ch = (op1[0]-48)| ((op2[0]-48) << 3);        //form bits 11-0 of machine code. 48 is ASCII value of '0'                    program[counter]=0x2000+((ch)&0x00ff);       //form the instruction and write it to memory                    counter++;                                   //skip to the next empty location in memory                }                else if (strcmp(token,st)==0) //-------------ST INSTRUCTION--------------------                {                    //to be added                }                else if (strcmp(token,jz)==0) //------------- CONDITIONAL JUMP ------------------                {                    //to be added                }                else if (strcmp(token,jmp)==0)  //-------------- JUMP -----------------------------                {                    op1 = strtok(NULL,\n\t\r );           //read the label                    jumptable[noofjumps].location = counter;    //write the jz instruction's location into the jumptable                     op2=(char*)malloc(sizeof(op1));         //allocate space for the label                                      strcpy(op2,op1);                //copy the label into the allocated space                    jumptable[noofjumps].label=op2;         //point to the label from the jumptable                    noofjumps++;                    //skip to the next empty location in jumptable                    program[counter]=0x5000;            //write the incomplete instruction (just opcode) to memory                    counter++;                  //skip to the next empty location in memory.                }                               else if (strcmp(token,add)==0) //----------------- ADD -------------------------------                {                    op1 = strtok(NULL,\n\t\r );                        op2 = strtok(NULL,\n\t\r );                    op3 = strtok(NULL,\n\t\r );                    chch = (op1[0]-48)| ((op2[0]-48)<<3)|((op3[0]-48)<<6);                      program[counter]=0x7000+((chch)&0x00ff);                     counter++;                 }                else if (strcmp(token,sub)==0)                {                    //to be added                }                else if (strcmp(token,and)==0)                {                    //to be added                }                else if (strcmp(token,or)==0)                {                    //to be added                }                else if (strcmp(token,xor)==0)                {                    //to be added                }                                       else if (strcmp(token,not)==0)                {                    op1 = strtok(NULL,\n\t\r );                    op2 = strtok(NULL,\n\t\r );                    ch = (op1[0]-48)| ((op2[0]-48)<<3);                    program[counter]=0x7500+((ch)&0x00ff);                      counter++;                }                else if (strcmp(token,mov)==0)                {                    //to be added                }                else if (strcmp(token,inc)==0)                {                    op1 = strtok(NULL,\n\t\r );                    ch = (op1[0]-48)| ((op1[0]-48)<<3);                    program[counter]=0x7700+((ch)&0x00ff);                      counter++;                }                else if (strcmp(token,dec)==0)                {                                    //to be added                }                else //------WHAT IS ENCOUNTERED IS NOT AN INSTRUCTION BUT A LABEL. UPDATE THE LABEL TABLE--------                {                    labeltable[nooflabels].location = counter;  //buraya bir counter koy. error check                    op1=(char*)malloc(sizeof(token));                    strcpy(op1,token);                    labeltable[nooflabels].label=op1;                    nooflabels++;                }                 token = strtok(NULL,,\n\t\r );              }        }//================================= SECOND PASS ==============================                //supply the address fields of the jump and jz instructions from the         int i,j;                 for (i=0; i<noofjumps;i++)                                                                   //for all jump/jz instructions        {            j=0;            while ( strcmp(jumptable[i].label , labeltable[j].label) != 0 )             //if the label for this jump/jz does not match with the                 j++;                                                                // jth label in the labeltable, check the next label..            program[jumptable[i].location] +=(labeltable[j].location-jumptable[i].location-1)&0x0fff;       //copy the jump address into memory.        }                                                                     // search for the start of the .data segment        rewind(fp);          while(fgets(line,sizeof line,fp)!= NULL)  //skip till .data, if no .data, also ok.        {            token=strtok(line,\n\t\r );            if (strcmp(token,.data)==0 )                break;        }                // process the .data segment and generate the variabletable[] array.        int dataarea=0;        while(fgets(line,sizeof line,fp)!= NULL)        {            token=strtok(line,\n\t\r );            if (strcmp(token,.code)==0 )  //go till the .code segment                break;            else if (token[strlen(token)-1]==':')            {                               token[strlen(token)-1]='\0';  //will not cause memory leak, as we do not do malloc                variabletable[noofvariables].location=counter+dataarea;                op1=(char*)malloc(sizeof(token));                strcpy(op1,token);                variabletable[noofvariables].name=op1;                token = strtok(NULL,,\n\t\r );                if (token==NULL)                    program[counter+dataarea]=0;                else if (strcmp(token, .space)==0)                {                    token=strtok(NULL,\n\t\r );                    dataarea+=atoi(token);                }                else if((token[0]=='0')&&(token[1]=='x'))                     program[counter+dataarea]=hex2int(token+2)&0xffff;                 else if ((  (token[0])=='-') || ('0'<=(token[0])&&(token[0]<='9'))  )                    program[counter+dataarea]=atoi(token)&0xffff;                  noofvariables++;                dataarea++;            }        }// supply the address fields for the ldi instructions from the variable table        for( i=0; i<noofldis;i++)        {            j=0;            while ((j<noofvariables)&&( strcmp( lditable[i].name , variabletable[j].name)!=0 ))                j++;            if (j<noofvariables)                program[lditable[i].location] = variabletable[j].location;                      } // supply the address fields for the ldi instructions from the label table        for( i=0; i<noofldis;i++)        {            j=0;            while ((j<nooflabels)&&( strcmp( lditable[i].name , labeltable[j].label)!=0 ))                j++;            if (j<nooflabels){                program[lditable[i].location] = (labeltable[j].location)&0x0fff;                printf(%d %d %d\n, i, j, (labeltable[j].location));               }                   } //display the resulting tables        printf(LABEL TABLE\n);        for (i=0;i<nooflabels;i++)            printf(%d %s\n, labeltable[i].location, labeltable[i].label);         printf(\n);        printf(JUMP TABLE\n);        for (i=0;i<noofjumps;i++)            printf(%d %s\n, jumptable[i].location, jumptable[i].label);           printf(\n);        printf(VARIABLE TABLE\n);        for (i=0;i<noofvariables;i++)            printf(%d %s\n, variabletable[i].location, variabletable[i].name);            printf(\n);        printf(LDI INSTRUCTIONS\n);        for (i=0;i<noofldis;i++)            printf(%d %s\n, lditable[i].location, lditable[i].name);          printf(\n);        fclose(fp);        fp = fopen(RAM,w);        fprintf(fp,v2.0 raw\n);        for (i=0;i<counter+dataarea;i++)            fprintf(fp,%04x\n,program[i]);    }   }
Write an Assembler in C. Why writing a machine code translator for a low level language in a higher level language?
c;compiler;assembly;machine code
People have written assemblers in machine code. They've also written then in assembly language--often a subset of the language they translate themselves, so they start with a simple bootstrap version of the assembler, then add features to it as they need them for the assembler itself.However, none of this is particularly a necessity. In the end, an assembler is a (usually fairly) simple translation program. It takes in a file in one (text) format, and writes out a file in another (usually an object file format). The fact that the text that's input represents machine instructions in a textual format and the result represents the same instructions in binary format doesn't make much difference to the language that's used to implement the assembler--in fact, even higher languages than C such as SNOBOL and Python can work quite nicely--I (fairly) recently worked on an assembler written in Python, and it worked pretty well for the job.As far as how you bootstrap things initially: typically on another machine that has decent development tools and such. If you're developing new hardware, you usually start by writing a simulator (or at least emulator) for the new machine anyway, so at first you're building and running the code on some host system in any case.