क्या इंटेल सीपीयू पर प्रोग्राम काउंटर सीधे पढ़ा जा सकता है (जो 'ट्रिक्स' के बिना है) कर्नेल मोड या किसी अन्य मोड में?प्रोग्राम काउंटर को सीधे पढ़ना
उत्तर
नहीं, ईआईपी/आईपी को सीधे एक्सेस नहीं किया जा सकता है, लेकिन स्थिति-निर्भर कोड में यह एक लिंक-टाइम स्थिर है ताकि आप तत्काल के रूप में पास के (या दूरस्थ) प्रतीक का उपयोग कर सकें।
स्थिति स्वतंत्र कोड में 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
आप एक विशिष्ट निर्देश का पता की जरूरत है, आम तौर पर कुछ इस तरह काम कर देता है नोट: कुछ असेंबलरों पर यह गलत चीज कर सकता है और [इस] से एक शब्द पढ़ सकता है, लेकिन आमतौर पर कुछ वाक्यविन्यास एफ होता है या असेंबलर को सही काम करने के लिए मिल रहा है।)
यदि आपका कोड किसी विशिष्ट पते पर स्थिर रूप से लोड किया गया है, तो असेंबलर पहले से ही जानता है (यदि आपने इसे सही प्रारंभ पता बताया है) सभी निर्देशों के पूर्ण पते। गतिशील रूप से लोड कोड, किसी भी आधुनिक ओएस पर किसी एप्लिकेशन के हिस्से के रूप में कहें, डायनामिक लिंकर द्वारा किए गए पते के स्थानांतरण के लिए सही पता धन्यवाद मिलेगा (बशर्ते असेंबलर स्थानान्तरण तालिकाओं को उत्पन्न करने के लिए पर्याप्त स्मार्ट है, जो वे आमतौर पर होते हैं)।
जानकारी के लिए धन्यवाद, वास्तव में अच्छा विचार।:) –
मैंने x86-64 पर इनलाइन जीसीसी असेंबली के साथ कोशिश की, लेकिन बैकएंड में त्रुटि मिली: 32-बिट पूर्ण एड्रेसिंग 64-बिट मोड में समर्थित नहीं है 'llvm 6.1.0 का उपयोग कर। क्या यह एलएलवीएम की समस्या है, या 64-बिट मोड में संभव नहीं है? – csl
@csl: या तो आप ओएस एक्स पर हैं (जहां 'ली रैक्स, [इसोन]' का उपयोग करने के अलावा कोई कामकाज नहीं है, या आप लिनक्स पर साझा ऑब्जेक्ट बना रहे हैं और इस प्रकार यह काम नहीं कर सकता है। ('mov'-तत्काल एक लिंक-टाइम निरंतर पता की आवश्यकता है, इसलिए यह केवल स्थिति-निर्भर कोड में काम करता है)।लेकिन यदि आप एक लिनक्स निष्पादन योग्य बना रहे हैं, [आपका कंपाइलर स्थिति-स्वतंत्र निष्पादन योग्य बनाने के लिए डिफ़ॉल्ट हो सकता है, और '-no-pie -fno-pie' स्थिति-निर्भर निष्पादन योग्य बनाता है जहां आप पूर्ण पते का उपयोग कर सकते हैं] (https: //stackoverflow.com/questions/43367427/32-bit-absolute-addresses-no-longer-allowed-in-x86-64-linux)। –
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 में है), तो आपको अनावश्यक शाखा गलतफहमी का पूरा समूह मिल जाएगा, जिससे आपका प्रोग्राम धीमा हो जाएगा। यह विधि आरएएस को उड़ाती नहीं है, क्योंकि इसमें कॉल और आरईटी निर्देशों की एक मिलान की जोड़ी है।
धन्यवाद, आप लोग रॉक :) –
जानकारी के लिए बहुत धन्यवाद, मुझे नहीं पता था कि दो ढेर थे .. :) –
आरएएस प्रोसेसर द्वारा उपयोग किया जाने वाला एक आंतरिक ढेर है; यह किसी भी तरह से कोड के लिए सुलभ नहीं है। यह केवल शाखा लक्ष्य भविष्यवाणी के लिए उपयोग किया जाता है। इसके बिना, कोड अभी भी धीरे-धीरे काम करेगा, बस धीरे-धीरे। –
आप उदाहरण के लिए कर सकते हैं x86-64 पर:
lea rax,[rip] (48 8d 05 00 00 00 00)
धन्यवाद! संख्याओं का क्या अर्थ है? –
निर्देश एन्कोडिंग है - एक अंतर्निहित 32-बिट ऑफ़सेट है जो 0 है, मुझे यकीन नहीं है कि एक छोटा एन्कोडिंग – matja
'ली रैक्स, [रिप]' NASM 2.10 में काम नहीं करता है। ऐसा लगता है कि आरआईपी केवल 'रिला' के साथ अप्रत्यक्ष रूप से 'ली' रैक्स, [rel _start] 'के रूप में उपयोग किया जा सकता है? –
तुम भी से/proc/stat इस पढ़ सकते हैं। Proc manpages की जांच करें।
क्या आप कहां बता सकते हैं? मैं इसे आसानी से नहीं मिला। –
इन/proc/stat में आप निर्देश सूचक (ईआईपी) –
पा सकते हैं, मुझे लगता है कि आपका मतलब '/ proc/self/stat' है, यह मैनपेज उद्धृत करने के लिए भी अच्छा होगा। –
वहाँ एक वास्तुकला पते जो मूल्यों के रूप में लेबल का उपयोग करके मार डाला जा रहा है तक पहुँचने के स्वतंत्र (लेकिन जीसीसी निर्भर) तरीका है:
http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
void foo()
{
void *current_address = $$current_address_label;
current_address_label:
....
}
यह बिल्कुल असेंबली नहीं है :-) – hirschhornsalz
यह '&& current_address_label' होना चाहिए, न कि' $$ ' –
क्या यह कोई सापेक्ष पता नहीं है (आईपी नहीं)? –
- 1. सी # से प्रदर्शन काउंटर पढ़ना: निर्दिष्ट श्रेणी
- 2. कार्यक्रम काउंटर?
- 3. जावास्क्रिप्ट - एक क्लिक काउंटर प्रोग्राम कैसे करें?
- 4. डेल्फी डिबगिंग में प्रोग्राम काउंटर को ले जाएं
- 5. प्रोग्रामिंग रूप से हडोप मैप्रिडस प्रोग्राम के आउटपुट को पढ़ना
- 6. सी लिनक्स डिवाइस प्रोग्रामिंग - सीधे से पढ़ना/देव
- 7. क्या कोई प्रोग्राम मेमोरी को सीधे असाइन कर सकता है?
- 8. प्रोग्राम के StdOut स्ट्रीम को सीधे सी # में कैसे लिखें?
- 9. "प्रोग्राम काउंटर" और "स्टार्ट एड्रेस" के बीच अंतर
- 10. एरेस्टलिस्ट को इनपुटस्ट्रीम पढ़ना
- 11. पढ़ना
- 12. पुराने काउंटर को हटाए बिना मौजूदा प्रदर्शन काउंटर श्रेणी में नया काउंटर कैसे जोड़ें?
- 13. प्रोग्राम को
- 14. एनएसएमयूटेबलएरे काउंटर हमेशा शून्य
- 15. sharded काउंटर
- 16. प्रदर्शन काउंटर
- 17. सरल काउंटर
- 18. सीधे GPU
- 19. लूप काउंटर
- 20. स्वचालित काउंटर?
- 21. एक धार से फाइलसेट को पढ़ना
- 22. एक फ़ाइल में सी ++ वेक्टर को पढ़ना और लिखना
- 23. उपाय हार्डवेयर काउंटर
- 24. निर्देशिका से एकाधिक फ़ाइलों को पढ़ना
- 25. जावा: छवियों को पढ़ना और छवि आइकन
- 26. प्रक्रिया मेमोरी आकार - विभिन्न काउंटर
- 27. पाइथन प्रोग्राम को पाइथन प्रोग्राम
- 28. अक्सर अद्यतन फ़ाइल से पढ़ना
- 29. शेल स्क्रिप्ट में काउंटर जोड़ना
- 30. पढ़ना मूल्यों
आह, मुझे लगता है कि चाल से प्यार है। एआरएम में, पीसी पढ़ने के दौरान पाइपलाइनिंग मुद्दे हैं। क्या यह समस्या इंटेल सीपीयू के साथ भी मौजूद है? – strager
नहीं, यह x86 पर मौजूद नहीं है। (बीटीडब्ल्यू - एआरएम पाइपलाइनिंग मुद्दा पागल है) –
x86 में, आपके पास एक शाखा की लागत है, जो कि पीसी पढ़ने से पाइपलाइन के लिए बहुत खराब है। एआरएम पर पीआईसी पाइपलाइन विषमता के साथ भी x86 से कहीं सस्ता है। –