retछद्म

ret

छद्म
RISC-V असेंबली संदर्भ

lyszt.net ret और अन्य RISC-V निर्देशों को अधिक विस्तार से कवर करता है।

विवरण

ret किसी फ़ंक्शन से वापस लौटता है और नियंत्रण कॉलर को सौंप देता है। एक call इसकी अपेक्षा करता है। जब किसी फ़ंक्शन को कॉल किया जाता है, तो कॉलर ra रजिस्टर में एक रिटर्न एड्रेस डालता है (call और jal देखें), और ret उस एड्रेस पर जंप करता है, जो मूल कॉल के ठीक बाद से जारी रहता है। यह एक स्यूडो-इंस्ट्रक्शन है जो ra पर जंप करता है।

ret केवल तब काम करता है जब ra में अभी भी सही एड्रेस हो। ऐसे फ़ंक्शन में जो किसी और चीज़ को कॉल नहीं करता, एंट्री और एग्ज़िट के बीच ra को कुछ नहीं बदलता। फ़ंक्शन के अंदर एक call ra को नए रिटर्न एड्रेस से ओवरराइट कर देता है और फ़ंक्शन को जिसकी ज़रूरत है उसे मिटा देता है। जो फ़ंक्शन दूसरों को कॉल करता है, वह एंट्री पर अपने ra को सेव करता है और ret से पहले उसे रीस्टोर करता है। रीस्टोर के बिना, फ़ंक्शन गलत जगह पर लौटता है, और प्रोग्राम असंबंधित कोड में जंप कर जाता है या हमेशा के लिए लूप करता रहता है।

परंपरा के अनुसार एक फ़ंक्शन लौटने से पहले अपना परिणाम a0 रजिस्टर में डालता है, और कॉलर उसे वहीं पढ़ता है।

RISC-V मैनुअल कहता है कि मानक कॉलिंग कन्वेंशन में एक प्रोसीजर रिटर्न को jalr के रूप में एन्कोड किया जाता है जिसमें rd=x0, rs1=x1 और इमीडिएट 0 होता है। यह x1 में मौजूद एड्रेस पर जंप करता है और कोई लिंक एड्रेस नहीं लिखता, क्योंकि x0 उसे डिस्कार्ड कर देता है। मैनुअल आगे कहता है कि प्रोसेसर jal और jalr में रजिस्टर नंबरों का उपयोग फ़ंक्शन रिटर्न की भविष्यवाणी करने के लिए संकेत के रूप में करते हैं, जो एक कारण है कि मानक कन्वेंशन रिटर्न एड्रेस को x1 में रखता है।

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

विस्तृत होता है

jalr zero, ra, 0

असेंबलर इस छद्म-निर्देश को ऊपर सूचीबद्ध वास्तविक निर्देश या निर्देशों से बदल देता है।

उदाहरण

square:
  mul a0, a0, a0
  ret              # return to the caller