قرارداد فراخوانی
در علومهای رایانه ای، یک قرارداد فراخوانی یک طرح در سطح پیادهسازی است برای نشان دادن آن که در یک زیرروال نحوه گرفتن پارامترها از صدازنندهٔ آنها و نحوه برگرداندن نتیجه به چه صورت است
تفاوتها در پیادهسازیهای مختلف شامل مکان پارامترها، مقادیر بازگشتی، آدرسهای بازگشت و نحوه وظایف آمادهسازی برای فراخوانی تابع و بازگرداندن محیط پس از آن بین صدا زننده (caller)و صدا زده شده(callee) میشود.
قراردادهای فراخوانی ممکن است به یک استراتژی ارزیابی زبان برنامهنویسی خاص مربوط باشند، اما اغلب آنها بخشی از آن (یا برعکس) نیستند، زیرا استراتژی ارزیابی معمولاً در سطح انتزاعی تری (بالاتری) تعریف شدهاست و به عنوان بخشی از زبان دیده میشود به جای جزئیات پیادهسازی (سطح پایین) یک زبان خاص کامپایلر.
تغییرات[ویرایش]
قراردادهای فراخوانی ممکن است در موارد زیر متفاوت باشند:
- پارامترها، مقادیر بازگشتی و آدرسهای برگشتی (در ثبات ها، در پشته فراخوانی، ترکیبی از هر دو یا در سایر ساختارهای حافظه) قرار میگیرند
- منظور که در آن آرگومانهای واقعی برای پارامترهای رسمی منتقل میشوند (یا بخشی از یک آرگومان بزرگ یا پیچیده)
- چطور یک مقدار بازگشتی (احتمالا طولانی یا پیچیده) از صدا زده شده به صدازننده (در پشته، در یک ثبات یا درون پشته) تحویل داده میشود
- چگونگی وظیفه تنظیم و تمیز کردن پس از یک فراخوانی تابع بین صدا زننده و صدا زده شده تقسیم میشود
- این که چگونه فرادادههای توصیف کننده المانها پاس داده میشوند
- جایی که مقدار اشاره گربه قاب(frame pointer) قبلی ذخیره شدهاست، که برای بازگرداندن اشاره گر به قاب هنگامی که روال به پایان میرسد (در پشته قاب یا در برخی از ثباتها)
- چگونگی اختصاص دادن متغیرهای محلی میتواند بخشی از قرار داد فراخوانی باشد (زمانی که صدا زننده برای صدا زده شده اختصاص میدهد)
در برخی موارد، تفاوت هازیر نیز شامل موارد میشوند:
- قراردادهایی که در آن ثباتها میتوانند بهطور مستقیم توسط تابع صدا زده شده مورد استفاده قرار گیرد، بدون رزرو قبلی (در غیر این صورت به عنوان جزئیات ABI در نظر گرفته میشود)
- کدام ثباتها به عنوان تغییرپذیر(volatile) در نظر گرفته شود و اگر تغییرپذیر باشد باید توسط صدا زده شده بازگردانی نشود (اغلب به عنوان جزئیاتABI در نظر گرفته میشود)
تنوع کامپایلر[ویرایش]
اگر چه برخی زبان در واقع ممکن است این تا حدی در مشخص زبان برنامهنویسی مشخصات (یا در برخی اجرای محوری)، پیادهسازیهای مختلف از جمله زبان (به عنوان مثال مختلف کامپایلر) بهطور معمول ممکن است هنوز هم استفاده از کنوانسیونهای مختلف تماس، اغلب انتخاب. دلایل این کار عملکرد، سازگاری مکرر با توافقنامههای دیگر زبانهای محبوب (با توجه به یا بدون دلایل فنی)، و محدودیتها یا قراردادهای اعمال شده توسط «سیستم عاملهای مختلف» (ترکیبی از معماری CPU و سیستم عامل) است.
تنوع معماری[ویرایش]
معماریهای CPU همیشه دارای بیش از یک قرارداد فراخوانی ممکن هستند. با تعداد زیادی از ثباتهای کلی و سایر ویژگیها، پتانسیل چند قرارداد فراخوانی زیاد است، اگر چه برخی معماری بهطور رسمی مشخص شدهاست که فقط از یک قرارداد فراخوانی استفاده کند که توسط معمار ارائه شدهاست.
x86 (32 بیتی)[ویرایش]
معماری x86 از قراردادهای فراخوانی مختلفی استفاده میکند. با توجه به کم بودن ثباتها، قراردادهای فراخوانی x86 اغلب آرگومان را در پشته منتقل میکنند، در حالی که مقدار بازگشتی (یا اشارهگر به آن) در یک ثبات منتقل میشود. برخی از قراردادها از ثباتها برای چند پارامتر اول استفاده میکنند که ممکن است باعث بهبود عملکرد و سریعتر شدن برای زیرروال - برگ (یعنی روالهایی که با روشی دیگر تماس نداشتهاند و نیازی به بازنگری ندارند) که مکرراً استفاده میشود شود.
مثال فراخوانی:
push EAX ; pass some register result
push byte[EBP+20] ; pass some memory variable (FASM/TASM syntax)
push 3 ; pass some constant
call calc ; the returned result is now in EAX
ساختار callee معمولی: (برخی یا همه (به جز ret) دستورالعملهای زیر ممکن است در روشهای ساده بهینهسازی شوند)
calc:
push EBP ; save old frame pointer
mov EBP,ESP ; get new frame pointer
sub ESP,localsize ; reserve place for locals
.
. ; perform calculations, leave result in EAX
.
mov ESP,EBP ; free space for locals
pop EBP ; restore old frame pointer
ret paramsize ; free parameter space and return
PowerPC[ویرایش]
معماری PowerPC دارای تعداد زیادی از ثباتها است، بنابراین اکثر توابع میتوانند تمام آرگومنتها را در رجیسترها برای فراخوانیهای تک مرحله ای منتقل کنند. آرگومانتهای اضافی در پشته منتقل میشوند و برای آرگومنتهای رجیستر-پایه (مقادیری باید در رجیستر خییره شود) همیشه فضای مناسب در پشته تخصیص داده میشود تا فراخوانی تابع در موارد فراخوانی چند مرحله ای (بازگشتی) راحت تر شودو ثباتها باید ذخیره شوند. همچنین در توابع variadic مانند printf()
، جایی که پارامترهای تابع باید به صورت آرایه قابل دسترسی باشند. تنها یک قرارد فراخوانی برای تمام زبانهای رویه ای استفاده میشود.
ملاحظات پیادهسازی[ویرایش]
این تغییرپذیری باید در هنگام ترکیب ماژولهای نوشته شده در چندین زبان یا هنگام فراخوانی سیستم عامل یاکتابخانهAPIها از یک زبان غیر از آن که در آن نوشته شده باشد، در نظر گرفته شود. در این موارد، باید مراقبتهای ویژه ای را برای هماهنگکردن قراردهای فراخوانی مورد استفاده توسط صدازننده و صدا زده شده انجام شود. حتی یک برنامه که از یک زبان برنامهنویسی استفاده میکند، میتواند از قراردادهای فراخوانی چندگانه یا انتخاب شده توسط کامپایلر، برای بهینهسازی کد یا برنامهنویس مشخص شده استفاده کند.
کد ریسه ای[ویرایش]
کد ریسه ای همه مسئولیت را برای تنظیم و تمیز کردن کد پس از فراخوانی تابع بر روی کد صدا زده شده دارد. کد صدا زده شده چیزی نیست جز فهرست زیرروالهایی که باید فراخوانی شوند. این باعث میشود تمام تابع تنظیم و تمیز کردن در یک مکان - prolog و epilog تابع - و نه در بسیاری از مکانهایی که عملکرد نامیده میشود. این باعث میشود کد رشته کمترین قرارداد تماس.
کد ریسه ای تمام آرگومنتهای مربوط به پشته را منتقل میکند. تمام مقادیر برگشتی در پشته بازگشته اند. این باعث میشود پیادهسازی ساده از قرارداد فراخوانیهایی که مقادیرهای بیشتری در ثباتها دارند، کندتر شود. با این حال، پیادهسازی کد ریسه ای که چندین مقدار پشته بالا را در رجیسترها ذخیره میکند - به ویژه، آدرس بازگشت - معمولاً سریع تر از قراردادهای فراخوانی است که همیشه آدرس بازگشت به پشته را push و popمیکند.[۱][۲][۳]
PL / I[ویرایش]
قرارداد فراخوانی پیش فرض برای برنامههای نوشته شده در زبان PL / I تمام آرگومان را با مرجع منتقل میکند (by reference)، هرچند ممکن است قراردادهای دیگر مشخص شود. رفتار کردن با آرگومنتها برای کامپایلرها و سیستم عاملها مختلف متفاوت است، اما معمولاً آدرسهای آرگومنتها توسط یک لیست آرگومنت در حافظه منتقل میشوند. یک آدرس نهایی یا پنهان ممکن است به یک منطقه منتقل شود تا حاوی مقدار بازگشتی باشد. به دلیل طیف گستردهای از دادههای پشتیبانی شده توسط PL / I، توصیفگر داده نیز ممکن است برای تعریف پاس داده شود، به عنوان مثال، طول رشتههای کاراکتر یا بیت، ابعاد و طول آرایهها. آرگومنتهای ساختگی آرگومنتهایی هستند کهیا ثابت هستند یا با نوع ورودی ای که انتظار میرود متفاوت اند.
This article "قرارداد فراخوانی" is from Wikipedia. The list of its authors can be seen in its historical and/or the page Edithistory:قرارداد فراخوانی. Articles copied from Draft Namespace on Wikipedia could be seen on the Draft Namespace of Wikipedia and not main one.
- ↑ براد رودریگز. "حرکت به جلو، قسمت 1: تصمیمگیری طراحی در هسته چهارم". نقل قول: "در 6809 یا Zilog Super8 DTC سریعتر از STC است."
- ↑ آنتور اورتل "سرعت روشهای مختلف ارسال تفسیر".
- ↑ متیو زالسکی. "YETI: یک مترجم پیشرفته قابل گسترش". فصل 4: طراحی و اجرای تفسیر کارآمد. نقل قول: "اگرچه مترجمان مستقیم-رشته شناخته شده دارای ویژگیهای پیش بینی شاخه ضعیف هستند … تاخیر تماس و بازگشت ممکن است بیشتر از یک حرکت غیر مستقیم باشد."