2009-03-01 13 views

उत्तर

27

नहीं, ईआईपी/आईपी को सीधे एक्सेस नहीं किया जा सकता है, लेकिन स्थिति-निर्भर कोड में यह एक लिंक-टाइम स्थिर है ताकि आप तत्काल के रूप में पास के (या दूरस्थ) प्रतीक का उपयोग कर सकें।

स्थिति स्वतंत्र कोड में EIP या आईपी प्राप्त करने के लिए:

call _here 
_here: pop eax 
; eax now holds the PC. 

लेकिन यह कॉल/वापसी भविष्यवक्ता ढेर unbalances, तो एक समारोह है कि वास्तव में वापसी करता है, पर 15 या तो शाखा mispredicts से बचने के लिए बुला पसंद करते हैं भविष्य के ret आपके मूल कार्यों में निर्देश। एक आरआईपी-रिश्तेदार lea (जब तक आप वापस जाने के लिए नहीं जा रहे हैं, या तो शायद ही कभी यह है कि यह कोई फर्क नहीं पड़ता।)

get_retaddr: 
    mov eax, [esp] 
    ret    ; keeps the return-address predictor stack balanced 

x86-64 मोड में, आरआईपी सीधे का उपयोग कर पढ़ा जा सकता है।

default rel   ; NASM directive: use RIP-relative by default 

lea rax, [_here]  ; RIP + 0 
_here: 

MASM: lea rax, [rip]

& टी वाक्य रचना एटी:

thisone: 
    mov (e)ax,thisone 

(: lea 0(%rip), %rax

+0

आह, मुझे लगता है कि चाल से प्यार है। एआरएम में, पीसी पढ़ने के दौरान पाइपलाइनिंग मुद्दे हैं। क्या यह समस्या इंटेल सीपीयू के साथ भी मौजूद है? – strager

+0

नहीं, यह x86 पर मौजूद नहीं है। (बीटीडब्ल्यू - एआरएम पाइपलाइनिंग मुद्दा पागल है) –

+0

x86 में, आपके पास एक शाखा की लागत है, जो कि पीसी पढ़ने से पाइपलाइन के लिए बहुत खराब है। एआरएम पर पीआईसी पाइपलाइन विषमता के साथ भी x86 से कहीं सस्ता है। –

26

आप एक विशिष्ट निर्देश का पता की जरूरत है, आम तौर पर कुछ इस तरह काम कर देता है नोट: कुछ असेंबलरों पर यह गलत चीज कर सकता है और [इस] से एक शब्द पढ़ सकता है, लेकिन आमतौर पर कुछ वाक्यविन्यास एफ होता है या असेंबलर को सही काम करने के लिए मिल रहा है।)

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

+0

जानकारी के लिए धन्यवाद, वास्तव में अच्छा विचार।:) –

+0

मैंने x86-64 पर इनलाइन जीसीसी असेंबली के साथ कोशिश की, लेकिन बैकएंड में त्रुटि मिली: 32-बिट पूर्ण एड्रेसिंग 64-बिट मोड में समर्थित नहीं है 'llvm 6.1.0 का उपयोग कर। क्या यह एलएलवीएम की समस्या है, या 64-बिट मोड में संभव नहीं है? – csl

+1

@csl: या तो आप ओएस एक्स पर हैं (जहां 'ली रैक्स, [इसोन]' का उपयोग करने के अलावा कोई कामकाज नहीं है, या आप लिनक्स पर साझा ऑब्जेक्ट बना रहे हैं और इस प्रकार यह काम नहीं कर सकता है। ('mov'-तत्काल एक लिंक-टाइम निरंतर पता की आवश्यकता है, इसलिए यह केवल स्थिति-निर्भर कोड में काम करता है)।लेकिन यदि आप एक लिनक्स निष्पादन योग्य बना रहे हैं, [आपका कंपाइलर स्थिति-स्वतंत्र निष्पादन योग्य बनाने के लिए डिफ़ॉल्ट हो सकता है, और '-no-pie -fno-pie' स्थिति-निर्भर निष्पादन योग्य बनाता है जहां आप पूर्ण पते का उपयोग कर सकते हैं] (https: //stackoverflow.com/questions/43367427/32-bit-absolute-addresses-no-longer-allowed-in-x86-64-linux)। –

7

x86 पर निर्देश सूचक (ईआईपी) को सीधे पढ़ने के लिए कोई निर्देश नहीं है। आप प्राप्त कर वर्तमान निर्देश का पता एक छोटे इनलाइन विधानसभा के साथ इकट्ठे किया जा रहा कर सकते हैं:

// GCC inline assembler; for MSVC, syntax is different 
uint32_t eip; 
__asm__ __volatile__("movl $., %0", : "=r"(eip)); 

. कोडांतरक निर्देश कोडांतरक द्वारा वर्तमान निर्देश का पता के साथ बदल जाता है। ध्यान दें कि यदि आप उपरोक्त स्निपेट को फ़ंक्शन कॉल में लपेटते हैं, तो आपको हर बार एक ही पता (उस फ़ंक्शन के भीतर) मिल जाएगा। आप एक अधिक प्रयोग करने योग्य सी समारोह चाहते हैं, आप के बजाय कुछ गैर इनलाइन विधानसभा का उपयोग कर सकते हैं:

// In a C header file: 
uint32_t get_eip(void); 

// In a separate assembly (.S) file: 
.globl _get_eip 
_get_eip: 
    mov 0(%esp), %eax 
    ret 

यह हर बार जब आप अनुदेश सूचक प्राप्त करना चाहते हैं इसका मतलब है, यह थोड़ा कम कुशल जब से तुम एक अतिरिक्त समारोह कॉल की जरूरत है। ध्यान दें कि ऐसा करने से यह रिटर्न पता स्टैक (आरएएस) नहीं उड़ाता है। रिटर्न एड्रेस स्टैक आरईटी निर्देशों के लिए branch target prediction की सुविधा के लिए प्रोसेसर द्वारा आंतरिक रूप से उपयोग किए जाने वाले रिटर्न पतों का एक अलग ढेर है।

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

+0

धन्यवाद, आप लोग रॉक :) –

+0

जानकारी के लिए बहुत धन्यवाद, मुझे नहीं पता था कि दो ढेर थे .. :) –

+1

आरएएस प्रोसेसर द्वारा उपयोग किया जाने वाला एक आंतरिक ढेर है; यह किसी भी तरह से कोड के लिए सुलभ नहीं है। यह केवल शाखा लक्ष्य भविष्यवाणी के लिए उपयोग किया जाता है। इसके बिना, कोड अभी भी धीरे-धीरे काम करेगा, बस धीरे-धीरे। –

15

आप उदाहरण के लिए कर सकते हैं x86-64 पर:

lea rax,[rip] (48 8d 05 00 00 00 00) 
+0

धन्यवाद! संख्याओं का क्या अर्थ है? –

+0

निर्देश एन्कोडिंग है - एक अंतर्निहित 32-बिट ऑफ़सेट है जो 0 है, मुझे यकीन नहीं है कि एक छोटा एन्कोडिंग – matja

+1

'ली रैक्स, [रिप]' NASM 2.10 में काम नहीं करता है। ऐसा लगता है कि आरआईपी केवल 'रिला' के साथ अप्रत्यक्ष रूप से 'ली' रैक्स, [rel _start] 'के रूप में उपयोग किया जा सकता है? –

0

तुम भी से/proc/stat इस पढ़ सकते हैं। Proc manpages की जांच करें।

+0

क्या आप कहां बता सकते हैं? मैं इसे आसानी से नहीं मिला। –

+0

इन/proc/stat में आप निर्देश सूचक (ईआईपी) –

+0

पा सकते हैं, मुझे लगता है कि आपका मतलब '/ proc/self/stat' है, यह मैनपेज उद्धृत करने के लिए भी अच्छा होगा। –

3

वहाँ एक वास्तुकला पते जो मूल्यों के रूप में लेबल का उपयोग करके मार डाला जा रहा है तक पहुँचने के स्वतंत्र (लेकिन जीसीसी निर्भर) तरीका है:

http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html

void foo() 
{ 
    void *current_address = $$current_address_label; 
    current_address_label: 
     .... 
} 
+2

यह बिल्कुल असेंबली नहीं है :-) – hirschhornsalz

+0

यह '&& current_address_label' होना चाहिए, न कि' $$ ' –

+0

क्या यह कोई सापेक्ष पता नहीं है (आईपी नहीं)? –

संबंधित मुद्दे