"सी में एक असेंबलर लिखें" उच्च स्तर की भाषा में निम्न स्तर की भाषा के लिए मशीन कोड अनुवादक क्यों लिखा जाता है?


13

मेरे माइक्रोप्रोसेसर वर्ग प्रशिक्षक ने हमें एक असाइनमेंट दिया और कहा:

"सी में एक असेंबलर लिखें" - मेरे प्रिय प्रोफेसर

इसलिए यह मुझे थोड़ा अतार्किक लगा।

अगर मैं गलत असेंबली नहीं हूं तो भाषा मशीन कोड से उच्च स्तरीय भाषाओं की यात्रा का पहला कदम है। मेरा मतलब है कि सी असेंबली से उच्च स्तरीय भाषा है। तो सी में असेम्बलर लिखने का क्या मतलब है? C भाषा के अभाव में वे अतीत में क्या कर रहे थे? क्या वे मशीन कोड में असेंबलर लिख रहे थे?

उच्च स्तरीय भाषा में निम्न स्तर की भाषा के लिए मशीन कोड अनुवादक लिखने से मुझे कोई मतलब नहीं है।

मान लीजिए कि हमने एक नया माइक्रोप्रोसेसर आर्किटेक्चर बनाया है जो उस आर्किटेक्चर के लिए सी कंपाइलर भी नहीं है। क्या हमारा असेंबलर जो C में लिखा है, नई वास्तुकला का अनुकरण कर सकेगा? मेरा मतलब है कि यह बेकार होगा या नहीं?

वैसे मुझे पता है कि जीएनयू असेंबलर और नेटवाइड असेंबलर सी में लिखे गए हैं। मैं भी सोच रहा हूं कि उन्हें सी में क्यों लिखा गया है?

अंत में यह एक साधारण कोडांतरक के लिए उदाहरण स्रोत कोड है जो हमारे प्रोफेसर ने हमें दिया था:

// 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]);
    }   
}

2
अलगाव में कोई उपकरण मौजूद नहीं है। क्रॉस टूलचाइन्स बहुत प्रचलित हैं, खासकर छोटे आर्किटेक्चर के लिए।
लार्स विकलंड

3
एक "क्रॉस" कंपाइलर / असेंबलर लक्ष्य की तुलना में एक अलग प्रणाली पर चलता है, और लक्ष्य प्रणाली पर उपयोग के लिए उपयुक्त कलाकृतियों का उत्पादन करता है। प्राचीन काल में, आपके पास सिस्टम के बीच डेटा इंटरचेंज नहीं था, लेकिन खुद के संदर्भ में एक सिस्टम को स्क्रैच से बूट करना था। आर्किटेक्चर के लिए बहुत सारा आधुनिक विकास स्थापित प्रणालियों पर किया जाता है, सब कुछ क्रॉस-संकलन।
लार्स विकलंड

19
क्या आप सी के बजाय मशीन कोड में कोडांतरक लिखना चाहेंगे? आपके प्रोफेसर आपके लिए अच्छे हो रहे हैं।
विंस्टन इर्वर्ट

2
आप अपने सभी कोड को सर्वोत्तम संभव प्रोग्रामिंग वातावरण / भाषा में लिखने का प्रयास क्यों नहीं करेंगे? एक कोडांतरक कोई अपवाद नहीं है।
एरिक इद्दत

1
किसी विशेष दिशा में एक निश्चित "यात्रा" नहीं है।
whatsisname

जवाबों:


18

लोगों ने मशीन कोड में कोडांतरक लिखे हैं। उन्होंने तब असेंबली भाषा में भी लिखा है - अक्सर भाषा का एक सबसेट जिसे वे स्वयं अनुवाद करते हैं, इसलिए वे असेंबलर के एक सरल "बूटस्ट्रैप" संस्करण से शुरू करते हैं, फिर इसमें फीचर जोड़ते हैं क्योंकि उन्हें कोडांतरक के लिए उनकी आवश्यकता होती है।

हालाँकि, इसमें से कोई भी विशेष रूप से एक आवश्यकता नहीं है। अंत में, एक कोडांतरक एक (आमतौर पर काफी) सरल अनुवाद कार्यक्रम है। यह एक (पाठ) प्रारूप में एक फ़ाइल में लेता है, और एक फ़ाइल को दूसरे (आमतौर पर ऑब्जेक्ट फ़ाइल प्रारूप) में लिखता है।

तथ्य यह है कि जो पाठ इनपुट करता है वह एक पाठ प्रारूप में मशीन निर्देशों का प्रतिनिधित्व करता है और परिणाम द्विआधारी प्रारूप में समान निर्देशों का प्रतिनिधित्व करता है, जो कि कोडांतरक को लागू करने के लिए उपयोग की जाने वाली भाषा से बहुत अंतर नहीं करता है - वास्तव में, सी से उच्चतर भाषाएं SNOBOL और पायथन के रूप में काफी अच्छी तरह से काम कर सकते हैं - मैं (काफी) हाल ही में पायथन में लिखे एक कोडांतरक पर काम किया है, और यह काम के लिए बहुत अच्छा काम किया है।

जहाँ तक आप शुरू में चीजों को बूटस्ट्रैप कैसे करते हैं: आम तौर पर एक अन्य मशीन पर जिसमें अच्छे विकास उपकरण और ऐसे होते हैं। यदि आप नया हार्डवेयर विकसित कर रहे हैं, तो आप आमतौर पर वैसे भी नई मशीन के लिए एक सिम्युलेटर (या कम से कम एमुलेटर) लिखकर शुरू करते हैं, इसलिए सबसे पहले आप किसी भी मामले में कुछ होस्ट सिस्टम पर कोड बना रहे हैं और चला रहे हैं।


3
"यहां तक ​​कि सी से उच्चतर भाषाएं जैसे कि SNOBOL और पायथन काफी अच्छी तरह से काम कर सकते हैं" - यह एक बहुत अच्छा बिंदु है। NASM के लिए, हमने वास्तव में कभी भी C से उच्च-स्तर पर विचार नहीं किया, लेकिन वह 1995 था जब प्रदर्शन आज की तुलना में बहुत अधिक महत्वपूर्ण था और उच्च-स्तरीय भाषाएं आज की तुलना में बहुत कम उन्नत थीं। इन दिनों, यह निश्चित रूप से विकल्पों पर विचार करने लायक है।
जूल्स

1
मैंने 1980 के दशक से SNOBOL नाम नहीं सुना है।
पचमनीबॉव

मैंने एक बार हास्केल में एक कंपाइलर लिखा था। आलसी मूल्यांकन और फ़ंक्शन के जंजीरों ने उत्पन्न किए गए मशीन कोड के लिए एक पीपहोल अनुकूलक लिखने के लिए इसे सरल रूप से सरल बना दिया।
थोरबजोरन राव एंडरसन

11

आप ऐसे कनेक्शन देख रहे हैं जो मौजूद नहीं हैं।

"असेम्बलर लिखें" किसी अन्य प्रोग्रामिंग कार्य की तरह ही एक प्रोग्रामिंग कार्य है। आप उस कार्य को संभालने के लिए उपकरणों का उपयोग करते हैं जो उस कार्य के लिए सर्वोत्तम हैं। एक कोडांतरक लिखने के बारे में कुछ खास नहीं है; उच्च स्तर की भाषा में इसे न लिखने का कोई कारण नहीं है। सी वास्तव में काफी निचले स्तर पर है, और मैं शायद सी ++ या कुछ अन्य उच्च स्तरीय भाषा पसंद करूंगा।

असेंबली भाषा वास्तव में इस तरह के एक कार्य के लिए पूरी तरह से अनुपयुक्त है। जिन मामलों में आप उचित रूप से असेंबली भाषा का उपयोग करेंगे, वे बहुत दुर्लभ हैं। केवल तभी जब आपको उन चीजों को करने की आवश्यकता होती है जो उच्च स्तर की भाषा में व्यक्त नहीं की जा सकती हैं।


1
अन्य उत्तर बहुत अच्छे हैं, लेकिन मुझे लगता है कि यह सबसे सीधा है, खासकर पहले दो वाक्यों के साथ। सवाल पढ़ते समय मैं खुद को वही बता रहा था।
मेटलमाइस्टर

मैन्युअल रूप से विधानसभा भाषा लिखना आजकल केवल हार्डवेयर विशिष्ट हैक के लिए आवश्यक है। उदाहरण के लिए, कुछ सीपीयू पर संरक्षित मोड की स्थापना के लिए विशिष्ट निर्देश अनुक्रम की आवश्यकता होती है और तार्किक रूप से समतुल्य अनुक्रम काफी अच्छा नहीं होता है। बहुत अधिक सभी सामान्य कार्यक्रमों को उस कार्य के लिए किसी विशिष्ट निर्देश अनुक्रम की आवश्यकता नहीं होती है जो उन्हें करने की आवश्यकता होती है और परिणामस्वरूप किसी भी विशिष्ट अनुक्रम की आवश्यकता के लिए कोई कारण नहीं होता है, लेकिन केवल कुछ तार्किक रूप से निर्देश के समकक्ष सेट होता है। कंपाइलिंग ऑप्टिमाइज़र्स निष्पादन निष्पादन (निर्देश गणना, दीवार घड़ी समय, कोड कैश आकार) में सुधार करने के लिए ठीक यही काम करते हैं।
मिकको रैंटलैनेन

9

C भाषा के अभाव में वे अतीत में क्या कर रहे थे? क्या वे मशीन कोड में असेंबलर लिख रहे थे?

विधानसभा अनिवार्य रूप से मशीन कोड के लिए एक महामारी है; मशीन की भाषा में प्रत्येक ओपकोड को असेंबली एमएनओनिक दिया जाता है अर्थात x86 NOP में 0x90 है। यह कोडांतरक को सरल बनाता है (nb अधिकांश कोडांतरकों के पास दो पास हैं, एक का अनुवाद करने के लिए, और दूसरा / पते / संदर्भ उत्पन्न करने के लिए दूसरा है।) पहले कोडांतरक को मशीन कोड में हाथ (कागज पर) द्वारा लिखा और अनुवादित किया गया था। एक बेहतर संस्करण हाथ से लिखा और इकट्ठा किया जाता है 'इकट्ठे' कोडांतरक, नई सुविधाओं को इस तरह से जोड़ा जाता है। नई भाषाओं के लिए कंपाइलर इस तरह बनाए जा सकते हैं; अतीत में यह असेंबली के आउटपुट असेंबली के लिए आम था, और उनके बैक एंड के लिए एक कोडांतरक का उपयोग करें!

उच्च स्तरीय भाषा में निम्न स्तर की भाषा के लिए मशीन कोड अनुवादक लिखने से मुझे कोई मतलब नहीं है। ... [मौजूदा असेंबलर] सी में लिखे गए हैं। मैं भी सोच रहा हूं कि वे सी में क्यों लिखे गए हैं?

  • उच्च स्तरीय भाषा में अधिक जटिल सॉफ्टवेयर लिखना आमतौर पर आसान होता है।
  • यह आमतौर पर अधिक कोड लेता है, और उच्चतर स्तर की तुलना में निचले स्तर की भाषा में जो आप कर रहे हैं उसे ट्रैक करने के लिए अधिक मानसिक प्रयास।
    • C की एक सिंगल लाइन कई निर्देशों में पूर्व अनुवाद कर सकती है। सी ++ (या सी) में एक साधारण असाइनमेंट आमतौर पर कम से कम 3 विधानसभा निर्देश (लोड, संशोधित, स्टोर) उत्पन्न करता है, यह एक उच्च स्तर में एक पंक्ति के साथ क्या किया जा सकता है, यह करने के लिए बीस निर्देश या अधिक (संभवतः सैकड़ों) ले सकता है। भाषा (जैसे c ++ या c।) एक आम तौर पर समस्या को हल करने के लिए अपना समय बिताना चाहते हैं, और मशीन कोड में समाधान को लागू करने के तरीके का पता लगाने में समय नहीं खर्च करना चाहते हैं।

जबकि प्रोग्रामिंग भाषा के लिए स्व-होस्टिंग एक सामान्य मील का पत्थर / वांछनीय विशेषता है, असेंबली इतना निम्न स्तर है कि अधिकांश प्रोग्रामर उच्च स्तर पर काम करना पसंद करेंगे। यानी कोई भी असेंबली में असेंबलर (या वास्तव में कुछ भी) लिखना नहीं चाहता है

मान लीजिए कि हमने एक नया माइक्रोप्रोसेसर आर्किटेक्चर बनाया है जो उस आर्किटेक्चर के लिए सी कंपाइलर भी नहीं है।

बूटस्ट्रैपिंग एक नई वास्तुकला पर एक टूल-चेन प्राप्त करने की प्रक्रिया है।

मूल प्रक्रिया है:

  • एक नया बैक एंड लिखें जो समझता है कि आपके नए CPU (या MCU) के लिए कोड कैसे जनरेट करें
  • संकलन करें और अपने बैक एंड का परीक्षण करें
  • अपने नए बैक-एंड का उपयोग करके अपने वांछित संकलक (और ओएस, आदि) को पार करें
  • इन बायनेरिज़ को नई प्रणाली में स्थानांतरित करें

एक बार ऐसा करने के लिए आपको असेंबली (नया या पुराना) में लिखने की ज़रूरत नहीं है, एक को अपने कोडांतरक / बैक-एंड / कोड-जनरेटर को लिखने के लिए सबसे अच्छी भाषा का चयन करना चाहिए।

क्या हमारा असेंबलर जो C में लिखा है, नई वास्तुकला का अनुकरण कर सकेगा?

कोडर अनुकरण नहीं करते हैं!

यदि कोई नई (या मौजूदा) मशीन भाषा के साथ एक नया सीपीयू विकसित कर रहा था, तो एक सिम्युलेटर आमतौर पर परीक्षण के लिए आवश्यक होता है; यानी सिम्युलेटर के माध्यम से यादृच्छिक निर्देश और डेटा चलाएं, और अपने प्रोटोटाइप सीपीयू पर समान निर्देशों और डेटा के साथ आउटपुट की तुलना करें। फिर कीड़े ढूंढें, कीड़े को ठीक करें, दोहराएं।


3

सी (या किसी अन्य उच्च स्तरीय भाषा) में एक कोडांतरक लिखने के कारणों में वे सभी कारण हैं जिनका उपयोग आप उस उच्च स्तर की भाषा में किसी अन्य कार्यक्रम को लिखने के औचित्य के लिए कर सकते हैं। इस मामले में मुख्य रूप से पोर्टेबिलिटी और प्रयोज्य हैं।

पोर्टेबिलिटी: यदि आप अपने असेंबलर को देशी भाषा में लिखते हैं तो आपके पास उस प्लेटफॉर्म पर एक असेंबलर है। यदि आप इसे C में लिखते हैं तो आपके पास C कंपाइलर के साथ किसी भी प्लेटफॉर्म पर एक असेंबलर है। उदाहरण के लिए, आपको अपने वर्कस्टेशन पर अपने एम्बेडेड प्लेटफॉर्म के लिए कोड संकलित करने और बाइनरी को स्थानांतरित करने के बजाय इसे सीधे लक्ष्य डिवाइस पर करने की आवश्यकता है।

प्रयोज्यता: ज्यादातर लोगों के लिए, जब प्रोग्राम असेंबलर या (बदतर) कच्चे मशीन कोड में होता है, तब पढ़ना, उसके बारे में तर्क करना और कार्यक्रमों को संशोधित करना कहीं अधिक स्वाभाविक है। इसलिए, उच्च स्तरीय भाषा में कोडांतरक को विकसित करना और उसे बनाए रखना आसान है क्योंकि आप उच्च स्तरीय भाषाओं द्वारा आपके लिए वहन किए गए अमूर्त के संदर्भ में सोच सकते हैं बजाय इसके कि आप मीनू के बारे में सोचें, जिसके लिए आप कमतर हैं।


3

केवल प्रश्न के इस भाग को संबोधित करते हुए:

"वैसे मुझे पता है कि GNU असेंबलर और नेटवाइड असेंबलर को C में लिखा गया है। मैं भी सोच रहा हूं कि वे C में क्यों लिखे गए?"

मूल रूप से नेटवाइड असेम्बलर लिखने वाली टीम के हिस्से के रूप में बोलते हुए, यह निर्णय उस समय हमें इतना स्पष्ट लग रहा था कि हम मूल रूप से किसी अन्य विकल्प पर विचार नहीं करते थे, लेकिन क्या हमने किया था इसलिए हम उसी निष्कर्ष पर आएंगे, निम्नलिखित कारण:

  • इसे निचले स्तर की भाषा में लिखना कठिन और अधिक समय लेने वाला होता।
  • उच्च स्तर की भाषा में इसे लिखने से यह तेज़ हो सकता है, लेकिन प्रदर्शन के विचार थे (एक संकलक के पीछे के छोर के रूप में उपयोग किया जाने वाला एक असेंबलर, विशेष रूप से, बहुत तेजी से संकलक को रोकने के लिए बहुत तेज़ होने की आवश्यकता है, क्योंकि यह हो सकता है अंत में बहुत बड़ी मात्रा में कोड को संभालना, और यह एक ऐसा उपयोग मामला था जिसे हम विशेष रूप से अनुमति देना चाहते थे) और मेरा मानना ​​है कि प्राथमिक लेखकों में कोई उच्च स्तरीय भाषा नहीं थी (यह जावा के लोकप्रिय होने से पहले था, इसलिए दुनिया ऐसी भाषाओं को तब खंडित किया गया था)। हमने कुछ मेटाप्रोग्रामिंग कार्यों के लिए पर्ल का उपयोग किया था (कोड जनरेटर बैक एंड के लिए एक उपयोगी प्रारूप में निर्देशों की तालिकाओं का निर्माण), लेकिन यह वास्तव में पूरे कार्यक्रम के लिए उपयुक्त नहीं होगा।
  • हम ऑपरेटिंग-सिस्टम पोर्टेबिलिटी चाहते थे
  • हम हार्डवेयर प्लेटफ़ॉर्म पोर्टेबिलिटी (क्रॉस-कंपाइलर बनाने के लिए) चाहते थे

इसने निर्णय को काफी आसान बना दिया: एएनएसआई-अनुपालन सी (उर्फ सी89 इन दिनों) उस समय एकमात्र भाषा थी जिसने वास्तव में उन सभी बिंदुओं को मारा। अगर कोई मानक सी ++ वापस आ गया था, तो हम उस पर विचार कर सकते थे , लेकिन विभिन्न प्रणालियों के बीच सी ++ समर्थन बल्कि तब वापस पैच था, इसलिए पोर्टेबल सी ++ लिखना एक बुरा सपना था।


1

एक चीज का दूसरे से कोई लेना-देना नहीं है। HTML या php या कुछ अन्य वेब सामग्री भाषा का उपयोग करके वेब ब्राउज़र को सख्ती से लिखा जाना चाहिए? नहीं, वे क्यों करेंगे? क्या कारों को केवल अन्य कारों द्वारा चलाया जा सकता है और मनुष्यों द्वारा नहीं?

बिट्स के एक बूँद (कुछ ascii) को बिट्स के एक बूँद (कुछ मशीन कोड) में परिवर्तित करना सिर्फ एक प्रोग्रामिंग कार्य है, उस कार्य के लिए आपके द्वारा उपयोग की जाने वाली प्रोग्रामिंग भाषा वह है जो आप चाहते हैं। आप कर सकते हैं और कई अलग-अलग भाषाओं में लिखे गए असेंबलर हैं।

नई भाषा शुरू में अपनी भाषा में नहीं लिखी जा सकती है क्योंकि अभी तक उनके लिए कोई कंपाइलर / असेंबलर नहीं है। अगर किसी नई भाषा के लिए कोई मौजूदा संकलक नहीं है, तो आपको पहले किसी और भाषा में लिखना होगा और फिर आप अंततः बूटस्ट्रैप कर सकते हैं यदि वह बूटस्ट्रैप के लिए भी समझ में आता है। (html और एक वेब ब्राउज़र, एक प्रोग्राम जो कुछ बिट्स को अंदर ले जाता है और कुछ बिट्स को बाहर निकालता है, कभी भी html, कैन्ट बी बी) में नहीं लिखा जाएगा।

एक नई भाषा नहीं है, एक मौजूदा एक हो सकता है। नए C या C ++ कंपाइलर अपने आप गेट के ठीक बाहर संकलन नहीं करते हैं।

असेंबली भाषा और सी के लिए लगभग सभी नए या संशोधित निर्देश सेट के लिए पहले दो भाषाएँ। हम अतीत में नहीं हैं, हम वर्तमान में हैं। हम आसानी से C या java या python में या जो भी निर्देश सेट और असेंबली भाषा के लिए जो कुछ भी चाहते हैं, अगर वह अभी तक मौजूद नहीं है, तो हम आसानी से एक असेंबलर उत्पन्न कर सकते हैं। इसी तरह कई रिटार्यडेबल सी कंपाइलर हैं जो हम असेंबली भाषा को असेंबली करते हैं, भले ही असेंबली के लिए कोई असेंबली लैंग्वेज तैयार कर सकते हैं।

ठीक यही हम नए निर्देश सेट के साथ करते हैं। कुछ कंप्यूटर को अपने सी संकलक के साथ हमारे नए निर्देश सेट पर नहीं चलाएं जो हमारे नए निर्देश सेट और न ही इसके कोडर के लिए संकलित किया गया था, एक क्रॉस असेंबलर और क्रॉस कंपाइलर बनाएं। तर्क का निर्माण और अनुकरण करते हुए उसका विकास और उपयोग करें। बग ढूंढने के सामान्य विकास चक्र के माध्यम से जाएं और बग को ठीक करें और फिर से परीक्षण करें, जब तक कि आदर्श रूप से सभी उपकरण और तर्क तैयार न हो जाएं। और लक्ष्य के आधार पर, यह कहें कि यह एक ऑपरेटिंग सिस्टम चलाने में अक्षम माइक्रोकंट्रोलर है, आपके पास कभी भी बूटस्ट्रैप करने का कारण नहीं होगा, जैसे कि टूलचिन उत्पन्न होता है और देशी निर्देश सेट का उपयोग करके चलता है। आप हमेशा संकलन पार करेंगे। एक तरह से एक अन्य मशीन में यह कभी नहीं समझ में आता है कि कोडांतरक को कोडांतरक में लिखा जाए।

हाँ यदि आप वापस जा सकते हैं या वापस जाने का नाटक कर सकते हैं, तो पहला असेंबलर एक पेंसिल और कागज वाला एक मानव था, जिसने कुछ ऐसा लिखा था जिससे उन्हें समझ में आया और फिर उसके बगल में बिट्स लिखें जो तर्क के लिए समझ में आया। फिर मशीन में बिट्स (google pdp8 या pdp11 या altair 8800) लाने के लिए स्विच या किसी अन्य तरीके का इस्तेमाल किया और इसे कुछ करने के लिए बनाया। शुरू में कोई कंप्यूटर सिमुलेटर नहीं थे, आपको बस तर्क को सही से प्राप्त करना था, इसे लंबे समय तक घूरना या चिप के कई चक्कर लगाना। उपकरण आज काफी अच्छे हैं कि आप A0 सफलता प्राप्त कर सकते हैं कि यह चीज सिर्फ एक बड़े अवरोधक से अधिक है, यह बहुत काम करता है आपको अभी भी उन चीजों के लिए एक स्पिन की आवश्यकता हो सकती है जिन्हें आप पूरी तरह से अनुकरण कर सकते हैं, लेकिन आप अक्सर बूट कर सकते हैं तीसरे या चौथे स्पिन के लिए इंतजार किए बिना पहली स्पाई,

अपने तरीके की मशीन में जैसा कि कोई अपेक्षा करता है, आप तब अपना हाथ इकट्ठे कोड लेते हैं और आप इसे टेप या कार्ड से प्रोग्राम लोड करने के लिए कहते हैं। आप मशीन कोड में एक कोड कोड को भी हाथ में लेते हैं, हो सकता है कि यह एक पूर्ण विकसित न हो, लेकिन यह प्रोग्रामिंग को थोड़ा आसान बना देता है। फिर उस उपकरण का उपयोग एक ऐसा बनाने के लिए किया जाता है जो एक अधिक उन्नत या जटिल लैन्गॉज (एक मैक्रो असेम्बलर) को संभाल सकता है, और वह एक और अधिक जटिल बनाने के लिए और आप फॉरट्रान या बेसिक या बी या जो भी हो, के साथ समाप्त होते हैं। और फिर आप एक ही भाषा में बूटस्ट्रैपिंग के बारे में सोचना शुरू करते हैं, एक मूल संकलक होने के लिए क्रॉस कंपाइलर को फिर से लिखना। बेशक आपको आदर्श रूप से उसके लिए किसी प्रकार के वातावरण या ऑपरेटिंग सिस्टम की आवश्यकता है।

जब हम सिलिकॉन का निर्माण या परीक्षण कर रहे हैं, तो हम उन संकेतों को घूरने / करने की आवश्यकता कर सकते हैं जो लोग और शून्य हैं। उपकरण हमें द्विआधारी या हेक्स को डिफ़ॉल्ट रूप से दिखाएंगे और कुछ टूल के साथ संभव है कि लुक अप भी हो, ताकि उपकरण कुछ mnemonics (असेंबली शायद) प्रदर्शित करेंगे लेकिन अक्सर इंजीनियर (सिलिकॉन / हार्डवेयर और सॉफ्टवेयर) या तो पर्याप्त पढ़ सकते हैं मशीन कोड, या निर्देशों को "देखने" के लिए असंतुष्ट / लिस्टिंग का उपयोग करें।

आप जो कर रहे हैं, उसके आधार पर आप कुछ मशीन कोड को टेस्ट वैक्टर में फिर से लिखने और फिर से जमा करने या फिर से इकट्ठा करने के बजाय अलग-अलग कर सकते हैं। उदाहरण के लिए यदि आपके पास कुछ गहराई पर पाइप लाइन और प्रीफैच है, तो आपको प्रोग्राम के अंत में कुछ नोड्स या अन्य वास्तविक निर्देशों को भरने की आवश्यकता हो सकती है, ताकि पाइप अपरिभाषित निर्देशों पर न चले, और आप बस चुन सकते हैं कंपाइलर या असेंबलर या लिंकर प्राप्त करने के लिए मशीन कोड को निम्नतम स्तर की लिस्टिंग / फ़ाइल में भरें।

पाठ्यक्रम के प्रोसेसर का परीक्षण करते समय आपको अपरिभाषित और शायद न ही बिट्स की देखभाल आदि से निपटने की आवश्यकता होती है, इसलिए आपको मशीन कोड में जाने और सामान्य रूप से काम करने वाले कार्यक्रम में एक निर्देश में एक या अधिक विशिष्ट बिट्स को संशोधित करने की आवश्यकता होगी। क्या यह ऐसा करने के लिए एक कार्यक्रम लिखने के लायक है या बस इसे हाथ से करना है। इसी तरह ईसीसी का परीक्षण करते समय आप एक या अधिक बिट्स को फ्लिप करना चाहते हैं और देखें कि वे सही हो गए हैं या फंस गए हैं। दी कि एक बहुत आसान करने के लिए एक कार्यक्रम लिखने के लिए या आप बस हाथ से कर सकता है।

फिर निश्चित रूप से ऐसी भाषाएं हैं जो न तो कोड का उत्पादन करती हैं जो एक प्रोसेसर, शुरुआती पास्कल, जावा, पाइथन आदि पर चलती हैं, आपको उन भाषाओं का उपयोग करने के लिए किसी अन्य भाषा में लिखे गए वीएम की आवश्यकता होती है। आप जावा जावा बनाने के लिए अपने जावा कंपाइलर का उपयोग नहीं कर सकते, भाषा के डिजाइन के आधार पर कोई मतलब नहीं है।

(हाँ इन भाषाओं के शुद्ध कार्यान्वयन के बाद निश्चित रूप से किसी ने एक अनपेक्षित बैकएंड का निर्माण किया है जो कभी-कभी वास्तविक अनुदेश सेट को लक्षित कर सकता है न कि vm निर्देश सेट को और फिर उस स्थिति में आप इसे स्वयं या इसके vm को संकलित करने के लिए भाषा का उपयोग कर सकते हैं यदि आप वास्तव में महसूस करते हैं जरूरत है। उदाहरण के लिए जीसीसी के लिए एक गानू जावा अंत)।

समय के साथ और शायद अब भी हम सी में सी कंपाइलर नहीं लिखते हैं। हम बाइसन / फ्लेक्स जैसी चीजों का इस्तेमाल करते हैं और कुछ अन्य प्रोग्रामिंग लैंग्वेज का इस्तेमाल करते हैं, जो हम अपने लिए सी जेनरेट करने के लिए इस्तेमाल करते हैं जो हम खुद नहीं लिखना चाहते। कुछ प्रतिशत सी निश्चित में है, लेकिन कुछ प्रतिशत किसी अन्य भाषा में है जो कुछ अन्य संकलक का उपयोग करता है जो बिट्स इनपुट करता है और अन्य बिट्स आउटपुट करता है। कभी-कभी इस दृष्टिकोण का उपयोग कोडांतरक बनाने के लिए भी किया जाता है। कंपाइलर / असेंबलर (उन प्रोग्रामों के डिज़ाइनर तक, जिनके पास बिट्स इनपुट करने और फिर अन्य बिट्स आउटपुट करने का कार्य है) के रूप में वे इसे कैसे लागू करने जा रहे हैं। प्रोग्राम जनरेट पर्सर्स को हाथ से प्रोग्राम किया जाना सुनिश्चित किया जा सकता है, बस समय लगता है ताकि लोग शॉर्टकट की तलाश करें। ठीक वैसे ही जैसे आप असेंबलर में एक असेम्बलर लिख सकते हैं लेकिन लोग एक शॉर्टकट की तलाश करते हैं।

एक वेब ब्राउज़र सिर्फ एक प्रोग्राम है जो कुछ बिट्स में होता है और कुछ अन्य बिट्स को बाहर करता है। एक असेम्बलर केवल एक प्रोग्राम है जो कुछ बिट्स में होता है और कुछ अन्य बिट्स को बाहर निकालता है। एक कंपाइलर सिर्फ एक प्रोग्राम है जो कुछ बिट्स में लेता है और कुछ अन्य बिट्स को बाहर निकालता है। आदि इन सभी के लिए प्रत्येक प्रोग्रामिंग कार्य के लिए इनपुट बिट्स और आउटपुट बिट्स के लिए नियमों का एक दस्तावेज सेट है। ये कार्य और बिट्स पर्याप्त सामान्य हैं कि किसी भी उपलब्ध प्रोग्रामिंग भाषा का उपयोग किया जा सकता है (जो कि बिट / बाइट हेरफेर करने और इनपुट और आउटपुट से निपटने में सक्षम है)। यहाँ कुंजी उपलब्ध है। खरोंच पुस्तक / ट्यूटोरियल से लाइनक्स प्राप्त करें और प्रयास करें। एक नकली फ्रंट पैनल के साथ pdp8 या pdp11 या altair 8800 या अन्य सिम्युलेटर आज़माएं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.