2009-10-13 14 views
6

तो, मैं इस बारे में उलझन में हूं कि एक ऑपरेटिंग सिस्टम में कूद निर्देश कैसे काम करते हैं। मैंने सोचा कि कूद निर्देश प्रोसेसर के कार्यक्रम काउंटर में मूल्य निर्धारित करता है। लेकिन कार्यक्रम स्मृति में विभिन्न स्थानों में चलाया जा सकता है। मैं देखता हूं कि x86 में, JMP EAX निर्देश है, लेकिन मेरा C++ कोड इसका उपयोग नहीं करता है।असेंबली में कूद निर्देश कई प्रक्रियाओं के साथ कैसे काम करता है?

int main() 
{ 
    int i = 0; 
    while (i < 10) 
    { 
     ++i; 
     if (i == 7) 
     { 
      i += 1; 
      continue; 
     } 
    } 
} 

यह करने के लिए अनुवाद:: मैं कुलपति में ++ और कुछ सी ++ कोड संकलित

int main() 
    { 
00411370 push  ebp 
00411371 mov   ebp,esp 
00411373 sub   esp,0CCh 
00411379 push  ebx 
0041137A push  esi 
0041137B push  edi 
0041137C lea   edi,[ebp-0CCh] 
00411382 mov   ecx,33h 
00411387 mov   eax,0CCCCCCCCh 
0041138C rep stos dword ptr es:[edi] 
     int i = 0; 
0041138E mov   dword ptr [i],0 
     while (i < 10) 
00411395 cmp   dword ptr [i],0Ah 
00411399 jge   main+47h (4113B7h) 
     { 
      ++i; 
0041139B mov   eax,dword ptr [i] 
0041139E add   eax,1 
004113A1 mov   dword ptr [i],eax 
      if (i == 7) 
004113A4 cmp   dword ptr [i],7 
004113A8 jne   main+45h (4113B5h) 
      { 
       i += 1; 
004113AA mov   eax,dword ptr [i] 
004113AD add   eax,1 
004113B0 mov   dword ptr [i],eax 
       continue; 
004113B3 jmp   main+25h (411395h) 
      } 
     } 
004113B5 jmp   main+25h (411395h) 
    } 
004113B7 xor   eax,eax 
004113B9 pop   edi 
004113BA pop   esi 
004113BB pop   ebx 
004113BC mov   esp,ebp 
004113BE pop   ebp 
004113BF ret    

तो मैं उलझन में हूँ, आदेश jmp 411395h के लिए, इस कार्यक्रम संकेत करता है हमेशा में एक ही स्थान में लोड किया जाता है याद? क्योंकि यह अजीब लगता है।

+3

ध्यान रखें कि आधुनिक CPUs वर्चुअल मेमोरी का समर्थन करते हैं, जिसका अर्थ है कि प्रत्येक प्रोग्राम का अपना पता स्थान होता है। यही है, एक प्रक्रिया में 0x12345678 पर बाइट एक और प्रक्रिया में 0x12345678 पर बाइट की तुलना में वास्तविक स्मृति में एक अलग बिंदु हो सकता है। –

उत्तर

6

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

जब लिंकर निष्पादन योग्य उत्पन्न करता है, तो यह एक विशेष base address का अनुमान लगाने वाले पूर्ण पते उत्पन्न करता है; माइक्रोसॉफ्ट लिंकर आमतौर पर 400000h का उपयोग करता है। जब ओएस निष्पादन योग्य या डीएल लोड करता है, तो यह उस पते के बीच अंतर जोड़कर सभी पूर्ण पते को "ठीक करता है" जिस पर निष्पादन योग्य वास्तव में लोड किया गया था और वह पता जिस पर लिंकर आधारित था। .com को छोड़कर सभी निष्पादन योग्य प्रारूप कुछ प्रकार की फ़िक्सअप तालिका निर्दिष्ट करते हैं, जो निष्पादन योग्य में सभी स्थानों को सूचीबद्ध करता है जिन्हें इस तरह से पैच किया जाना चाहिए। इसलिए, ओएस आपके निष्पादन योग्य को आधार पते पर स्मृति में लोड करने के बाद, 1500000h कहें, आपकी कूद jmp 1511395h की तरह दिखाई देगी। आप डीबगर के साथ वास्तविक कोड बाइट्स देख कर इसे देख सकते हैं।

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

+1

004113 बी 3 पर जेएमपी निर्देश और ... बी 5 सापेक्ष कूद होना चाहिए। हम पता लेबल से बता सकते हैं कि ये jmp निर्देश दो-बाइट निर्देशों के रूप में एन्कोड किए गए हैं। इसलिए, वे रिश्तेदार jmp निर्देश हैं। दो-बाइट जेएमपी निर्देश ईआईपी +/- 127 के साथ पुनः लोड होने का कारण बनते हैं। +/- 127 का मान दो बाइट ऑपोड का दूसरा बाइट है। उस जेएमपी ओपोड का पहला बाइट ईबी है। जेएमपी (उदाहरण के लिए, गैर-रिश्तेदार एड्रेसिंग) के संस्करण हैं जो ई 9, ईए, एफएफ से शुरू होते हैं - इसलिए यह महसूस करना महत्वपूर्ण है कि असेंबली भाषा में निमोनिक "जेएमपी" के साथ कुछ अलग-अलग ऑपकोड हैं। –

2

अधिकांश चिप्स के सापेक्ष कूद (वर्तमान स्थान के सापेक्ष) और वर्चुअल एड्रेसिंग होते हैं।

+0

उत्तर के साथ कुछ गलत है? कृपया एक टिप्पणी छोड़ दो। धन्यवाद! –

3

स्मृति स्थान प्रक्रिया के सापेक्ष हैं। कार्यक्रम की शुरुआत के सापेक्ष, main हमेशा मेमोरी में एक ही स्थान पर है।

+1

यह बिल्कुल सही नहीं है - कुछ ओएस सुरक्षा पते के खिलाफ बेहतर सुरक्षा के लिए हर बार एक अलग पते पर एक प्रोग्राम लोड करने के लिए * पता स्थान लेआउट यादृच्छिकरण * का उपयोग करते हैं। –

+1

@ एडम, इससे कोई फ़र्क नहीं पड़ता कि यह कहां लोड किया गया है, कार्यक्रम समान पते को देखता है चाहे कोई भी ओएस क्या करता हो। अन्यथा अराजकता बीमा होगी। –

+1

@ बाय्रॉन - पूर्व पते को अलग-अलग पते पर लोड किया जा सकता है। निष्पादन योग्य फ़ाइल में स्थानान्तरण जानकारी होती है ताकि लोडर exe में पूर्ण पते को समायोजित कर सके यदि यह अपने पसंदीदा पते पर लोड नहीं होता है। Exes के साथ यह सामान्य नहीं है, यह DLL लोड करने के साथ और अधिक आम है। – Michael

3

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

6

नहीं, संभवतः यहां दो चीजें हैं जो आप यहां खेल सकते हैं - आप ओएस निर्दिष्ट नहीं करते हैं इसलिए मैं एक सामान्य उत्तर देने जा रहा हूं।

पहला यह है कि एक निष्पादन योग्य फ़ाइल शायद ही कभी अंतिम प्रारूप में है। एक सरलीकरण के रूप में, संकलन ऑब्जेक्ट फ़ाइलों में स्रोत बदल जाता है और लिंकिंग ऑब्जेक्ट फ़ाइलों को निष्पादन योग्य में जोड़ती है।

लेकिन निष्पादन योग्य लोड हो गया है और उस चरण में, और भी संशोधन किए जा सकते हैं। इन संशोधनों में से एक निष्पादन योग्य के भीतर मेमोरी संदर्भों को ठीक करने के लिए हो सकता है ताकि विभिन्न स्थानों पर लोड की गई स्मृति को इंगित किया जा सके।

इसे निष्पादन योग्य फ़ाइल द्वारा प्राप्त किया जा सकता है जिसमें स्वयं के पते की एक सूची होती है जिसे रन टाइम पर ठीक करने की आवश्यकता होती है।

कई आधुनिक ऑपरेटिंग सिस्टम में वर्चुअल मेमोरी और भौतिक स्मृति के बीच एक डिस्कनेक्ट भी है।

जब आपकी प्रक्रिया शुरू होती है, तो आपको अपना स्वयं का (विंडोज 32 बिट के लिए 4 जी, मुझे विश्वास है) पता स्थान जिसमें आपकी प्रक्रिया लोड होती है। इस पता स्थान के भीतर के पते आपके वास्तविक भौतिक स्मृति पते से थोड़ा सा संबंध रखते हैं और दोनों के बीच अनुवाद स्मृति प्रबंधन इकाई (एमएमयू) द्वारा किया जाता है।

वास्तव में, आपकी प्रक्रिया सभी भौतिक पता स्थान पर उड़ान भर सकती है क्योंकि यह बाहर और अंदर है। वर्चुअल पते हालांकि नहीं बदलेगा।

+0

"आप एक ओएस निर्दिष्ट नहीं करते हैं" विजुअल सी ++ कितने ऑपरेटिंग सिस्टम चलते हैं? –

+2

ठीक है, उन्होंने कहा, "मैं देखता हूं कि x86 में" और "मैंने वीसी ++ में कुछ सी ++ कोड संकलित किया" लेकिन मैंने इसे एक उदाहरण के रूप में लिया (1) कोई ओएस-विशिष्ट टैग नहीं है; और (2) प्रश्न प्रकृति में बहुत सामान्य है: "असेंबली में", "एक ऑपरेटिंग सिस्टम"। – paxdiablo

3

सापेक्ष कूद वर्तमान मशीन निर्देश (निर्देश सूचक कहा जाता है) का पता लेते हैं और पते को गणना करने के लिए ऑफसेट जोड़ते हैं।

आप अपने कोड को देखें, तो

004113B3 jmp   main+25h (411395h) 
004113B5 jmp   main+25h (411395h) 
004113B7 xor   eax,eax 

आप ध्यान दें हूँ कि JMP अनुदेश 2 बाइट्स लंबा है (JMP के लिए 1 बाइट, 1 ऑफसेट के लिए बाइट), और संभवतः एक पूर्ण 4 बाइट की दुकान नहीं कर सकते हैं पता।

सापेक्ष छलांग CPU की बुनियादी कार्यक्षमता कर रहे हैं (से मैं क्या 65xx, Z80, 8086, 68000 के बारे में पता है), और आभासी स्मृति, स्मृति मैपिंग या पता स्थान यादृच्छिकीकरण के रूप में इस तरह के उन्नत सुविधाओं से संबंधित नहीं हैं।

0
int main() 
    { 
00411370 push  ebp 
00411371 mov   ebp,esp 
00411373 sub   esp,0CCh 
00411379 push  ebx 
0041137A push  esi 
0041137B push  edi 
0041137C lea   edi,[ebp-0CCh] 
00411382 mov   ecx,33h 
00411387 mov   eax,0CCCCCCCCh 
0041138C rep stos dword ptr es:[edi] 
     int i = 0,int j=0; 
0041138E mov   dword ptr [i][j],0 
     while (i < 10) 
00411395 cmp   dword ptr [i][j[,0Bh 
00411399 jge   main+47h (4113B7h) 
     { 
      ++i; 
0041139B mov   eax,dword ptr [i][j] 
0041139E add   eax,1 
004113A1 mov   dword ptr [i][j],eax ' 
      if (i == 7) 
004113A4 cmp   dword ptr [i][j],7 
004113A8 jne   main+45h (4113B5h) 
      { 
       i += 1; 
004113AA mov   eax,ebx,dword ptr [i][j] 
004113AD add   eax,1 
004113B0 mov   dword ptr [i][j],ebx 
       continue; 
004113B3 jmp   main+25h (411395h) 
      } 
     } 
004113B5 jmp   main+25h (411395h) 
    } 
004113B7 xor   eax,ebx 
004113B9 pop   edi 
004113BA pop   esi 
004113BB pop   ecx 
004113BC mov   esp,ebp 
004113BE pop   ebp 
004113BF ret 
संबंधित मुद्दे