2013-02-23 48 views
5

मैं एक ही त्रुटि के बारे में पोस्ट को देखा है लेकिन मैं अभी भी त्रुटि मिल रही है:एएसएम

too many memory references for `mov' 
junk `hCPUIDmov buffer' after expression 

... यहाँ कोड (MinGW संकलक है/सी :: बी):


    #include iostream 

    using namespace std; 

    union aregister 
    { 
     int theint; 
     unsigned bits[32]; 
    }; 

    union tonibbles 
    { 
     int integer; 
     short parts[2]; 
    }; 

    void GetSerial() 
    { 
     int part1,part2,part3; 
     aregister issupported; 
     int buffer; 

     __asm(
      "mov %eax, 01h" 
      "CPUID" 
      "mov buffer, edx" 
     );//do the cpuid, move the edx (feature set register) to "buffer" 


     issupported.theint = buffer; 
     if(issupported.bits[18])//it is supported 
     { 
      __asm(
       "mov part1, eax" 
       "mov %eax, 03h" 
       "CPUID" 
      );//move the first part into "part1" and call cpuid with the next subfunction to get 
      //the next 64 bits 

      __asm(
       "mov part2, edx" 
       "mov part3, ecx" 
      );//now we have all the 96 bits of the serial number 


      tonibbles serial[3];//to split it up into two nibbles 

      serial[0].integer = part1;//first part 
      serial[1].integer = part2;//second 
      serial[2].integer = part3;//third 
     } 
    } 

+2

आप '%' सभी अपने रजिस्टर तक पहुँचता है के लिए उपयोग नहीं करना चाहिए:

निम्नलिखित स्निपेट अपने उपयोग-मामले (मैं जीसीसी इनलाइन विधानसभा या CPUID साथ जटिलता परिचित नहीं कर रहा हूँ) को कवर कर सकते हैं? –

+4

मुझे लगता है कि आप रजिस्टर नाम से पहले कुछ% संकेत भूल गए हैं। – fuz

+0

प्रश्न के अंत में उन 3 पंक्तियां क्या हैं जो मुझे बता रही हैं कि मेरी पोस्ट अधिकतर कोड है? –

उत्तर

8

आपका असेंबली कोड 0ccजीसीसी के लिए है।

सबसे पहले, जीसीसी एटी & टी वाक्य रचना (संपादित करें: by default, thanks nrz) का उपयोग करता है, तो यह की जरूरत है एक % प्रत्येक रजिस्टर में संदर्भ के लिए और तत्काल ऑपरेंड के लिए एक $ गयी। गंतव्य ऑपरेंड हमेशा दाएं पक्ष पर है।

दूसरा, आपको एक लाइन लाइन विभाजक (उदाहरण के लिए \n\t) एक नई लाइन के लिए पास करने की आवश्यकता होगी। चूंकि जीसीसी आपकी स्ट्रिंग को सीधे असेंबलर से गुजरता है, इसलिए इसे एक विशेष वाक्यविन्यास की आवश्यकता होती है।

आपको आमतौर पर अपने असेंबलर को कम करने के लिए कड़ी मेहनत करनी चाहिए क्योंकि इससे ऑप्टिमाइज़र के लिए समस्याएं हो सकती हैं। आवश्यक असेंबलर को कम करने का सबसे आसान तरीका शायद एक समारोह में सीपीयूइड निर्देश को तोड़ना होगा, और इसका पुन: उपयोग करना होगा।

void cpuid(int32_t *peax, int32_t *pebx, int32_t *pecx, int32_t *pedx) 
{ 
    __asm(
     "CPUID" 
      /* All outputs (eax, ebx, ecx, edx) */ 
     : "=a"(*peax), "=b"(*pebx), "=c"(*pecx), "=d"(*pedx) 
      /* All inputs (eax) */ 
     : "a"(*peax)           
    ); 
} 

फिर बस उपयोग करके कॉल करें;

int a=1, b, c, d; 

cpuid(&a, &b, &c, &d); 

do it using macros पर एक और संभवतः अधिक सुरुचिपूर्ण तरीका है।

+0

इस कोड में पंजीकरण बाधाओं की कमी भी है, इसलिए जहां तक ​​मुझे पता है कि यह पूरी तरह से असुरक्षित/फर्जी है। आपको जीसीसी को बताएंगे कि आप किस रजिस्टरों का उपयोग करेंगे/क्लॉबर और जहां इनपुट/आउटपुट जाते हैं। –

+0

@ आर .. हाँ, मेरे बुरे, मैंने पृष्ठ से एक बुरा उदाहरण चुना है। जानकारी के कुछ लिंक और एक और प्रासंगिक उदाहरण के साथ इसे बदल दिया। –

4
  1. क्योंकि कैसे सी काम करता है की

    ,

    __asm(
        "mov %eax, 01h" 
        "CPUID" 
        "mov buffer, edx" 
    ); 
    

    जो

    __asm("mov %eax, 01hCPUIDmov buffer, edx"); 
    

    के बराबर है जो नहीं है कि आप क्या चाहते

    __asm("mov %eax, 01h" "CPUID" "mov buffer, edx"); 
    

    के बराबर है।

  2. एटी & टी वाक्यविन्यास (जीएएस का डिफ़ॉल्ट) अंत में गंतव्य रजिस्टर रखता है।

  3. एटी & टी वाक्यविन्यास को $ के साथ उपसर्ग करने की आवश्यकता है।

  4. आप इस तरह के स्थानीय चर का संदर्भ नहीं दे सकते; आपको उन्हें ऑपरेंड के रूप में पास करने की आवश्यकता है।

Wikipedia's article एक काम उदाहरण है कि eax रिटर्न देता है।

int eax, ebx, ecx, edx; 
eax = 1; 
__asm("cpuid" 
    : "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx)); 
buffer = edx