الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

ماذا تعني Calling Conventions ؟

بدأه The Hidden Ghost في 12 سبتمبر 2012 · 6 رد · 1,035 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع
NogSa.png

أريد أن أعرف ماذا تعني ال Calling Conventions in C++ or C ؟ لأنني عندما عملت لها traduction في الشيخ Google biggrin.gif ، ظهرت لي هذه الترجمة:

927775212.png

blink.gifblink.gifblink.gif

749644306.png

وإن كان بالإمكان أريد أمثلة في هذا الشأن و شكرا laugh.gif

rS3eY.png
#2

الترجمة الصحيحة هي "Conventions d'appel" أو "اتفاقيات الإستدعاء".

اتفاقية الإستدعاء هي الطريقة التي تحدد الكيفية التي يتم بها استدعاء دالة معينة بأدق التفاصيل و بالأخص :

  • يتم تخزين الوسائط في المكدس (pile) أو في سجلات (registres) منفصلة ؟
  • كيف سيكون ترتيب الوسائط إذا تم تخزينهم في المكدس ؟ من الأول إلى الأخير أو من الأخير للأول ؟
  • إذا تم تخزين الوسائط في المكدس, من سيكون المسئول عن تنظيف المكدس بعد نهاية الإستدعاء ؟
1
#3

لا يختلف اثناء على ان معني call فى سي++ هو يستدعي .... وهي علمية تشغيل(اجراء routine) سواء كان( دالة او برنامج) من اجل مهمة ما او الحصول على نتائج الاجراء.

وعندما نضيف لــ call مصطلح Conventions كأننا نريد ان نقول:

ماهي برتوكولات استدعاء الدوال او البرامج؟ أو معنى آخر ما هي قوانين استدعاء دالة او اجراء؟

يمكننا وضع تعريف للمصطلح كــ:

  • برتوكولات الاستدعاء
  • قوانين الاستدعاء

وعندما نتحدث عن عمليات قوانين او بروتوكولات الاستدعاء للأجراءات(دالة او برنامج) فأن هذا يحدث اثناء عمل البرنامج ومن ثم فأن التحكم الرئيسي يرجع الى تعلميات الاسمبلى فى بيئة المعالج فتجد ان لمعالجات x86 لها قوانين الاستدعاء وأيضا PowerPC ايضا لها قوانين استدعاء ...
وبشكل عام فأن قوانين استدعاء الاجراءات تدور حول :
  • كيف يمكن للأجراءات استلام الوسائط من البرنامج المستدعى للأجراء؟
  • وكيفية ارجاع الناتج الى البرنامج المستدعى للأجراء.

ومن النقاط التى تختلف فيها قوانين الاستدعاء سواء من لغة الى آخر او من منصة تشغيل الى آخر هي:

  • أين يتم وضع الوسائط والقيمة المرجعة (فى المسجلات أم متراصة الاستدعاء ام كلاهما)
  • ترتيبط تمرير الوسائط (اة أجزاء من وسيط مفرد).
  • كيفية تقسيم مهمة اعداد الدوال ومهمة تنظيف الذاكرة عقب انتهاء عمل الدالة بين البرنامج المستدعى والدالة المستدعاة.
  • اي من المسجلات يتم استخدامة بشكل مباشر بواسطة الدالة المستدعاة.
  • اى من المسجلات اعتارة كمستودع ذاكرة دائم او مؤقت لو كان مؤقت فلاحاجة لأسترجاعة بواسطة الدالة المتسدعاة.

قد تكون تفصيل فهم المصطلح مملة ولكن المعرفة بالشئ لا تضر.

تم تعديل هذه المشاركة بواسطة محمد عودة في 12 سبتمبر 2012 في 14:59

2

post-15367-027053900%201340345097.gifpost-15367-087183200%201340344597.gif
post-247365-0-10080400-1379403554_thumb.

#4

الـcalling conventions تصف الطريقة التي ستُستدعى فيها الدوال وكيف ستمرر المعاملات للدالة المُستدعاة ومن سيتولى عملية التنظيف بعد الإنتهاء , المُستدعى callee أم المُستدعي caller.

هناك عدّة أساليب لإستدعاء الدوال وأشهرها ثلاثة :

  • cdecl.
  • stdcall.
  • fastcall.

خُذ هذا البرنامج كمثال عليها:

#include <windows.h>

int __cdecl cde_call(int param1, int param2, int param3);
int __stdcall std_call(int param1, int param2, int param3);
int __fastcall fast_call(int param1, int param2, int param3);

int main(int argc, char **argv)
{

    cde_call(1, 2, 3);
    std_call(1, 2, 3);
    fast_call(1, 2, 3);

    return 0;
}

int __cdecl cde_call(int param1, int param2, int param3)
{
    return 1;
}

int __stdcall std_call(int param1, int param2, int param3)
{
    return 1;
}

int __fastcall fast_call(int param1, int param2, int param3)
{
    return 1;
}

فيه ثلاث دوال : cde_call وstd_call وfast_call جميعها نفس الشيء وتأخذ ثلاث مُعاملات int إلا أن كُل واحدة منها تستخدم طريقة إستدعاء مُختلفة ,لن يتأثر بها برنامجك أو سيختلف إستخدامك لأي منها أبداً, فهي تتم على مُستوى الآلة وسيحدث الإختلاف في البرنامج الناتج بعد التصريف.

الدالة الأولى : تستخدم إسلوب cdecl:

int __cdecl cde_call(int param1, int param2, int param3);

في هذا الإسلوب ستمرر المُعاملات للدالة المُستدعاة عن طريق المُكدس بطريقة مقلوبة وسبدو كود الأسمبلي لها هكذا :

...
push    3
push    2
push    1
call    cde_call
add     esp, 12
...

لاحظّ أن المُستدعي caller هو من سيتولى التظيف بعد الإستدعاء, عندما دُفعت param1 وparam2 و param3 فالمكدس زاد بـ12 بايت (حجم كل منها 4 بايت * 3). يلزم إعادة المكدس لحالة. يُمكن عمل شيء مثل :

pop    ebx
pop    ebx
pop    ebx

الا أنّك يُمكنك أن تعمل نفس الشيء بتعليمة واحدة "add esp, 12".

الدالة الثانية : تستخدم إسلوب std_call :

int __stdcall std_call(int param1, int param2, int param3);

يُسمى هذا الإسلوب stdcall أو pascal call (باسكال). وهو تماماً نفس cdecl من ناحية طريقة تمرير المُعاملات للدالة المُستدعاة :

...
push    3
push    2
push    1
call    std_call
...

إلا أن في هذا الإسلوب لايتولى المُستدعي مسؤولية التنظيف بعد الإنتهاء, بل ستتولاها الدالة المُستدعاة. تجده مُستخدم كثيراً في دوال ويندوز.

الدالة الثالثة : تستخدم إسلوب fastcall :

int __fastcall fast_call(int param1, int param2, int param3);

في هذا الإسلوب لايُستخدم المُكدس لمترير المُعاملات للدالة المُستدعاة. بل تُستخدم مُسجلات المُعالج :

...
push    3
mov     edx, 2
mov     ecx, 1
call    fast_call
...

هذا الإسلوب أسرع مقارنة بالإسلوبين الآخرين حيث أن التعامل مع مُسجلات المعالج أسرع من التعامل مع الذاكرة الا أنه محدود. فمثلاً عند تصريف المثال على ويندوز 32بت تجد إلا فقط المُسجلين ecx, ebx وباقي المُعاملات تُدفع للمُكدس. في بعض الأنظمة كلينكس يُستخدم حتى خمس مُسجلات, الا أنه أيضاً يُستخدم المُكدس إذا زاد على ذلك. تجد هذا الإسلوب مُستخدم في الدوال التي تُستخدم بكثرة كإستدعاءت النظام system calls , وهي دوال ذات أغراض عامة والتي بُنيت وتشكلت منها باقي دوال النظام.

3
#5

يوجد اسلوب استدعاء يستخدم داخل الـ ++c يسمي بـ thiscall.

و الله ولي التوفيق

مدونتي: C++ Tips and Tricks

#6

يُستخدم الاستدعاء thiscall مع الدوال الأعضاء الغير ساكنة (non static).

في الــ GCC, نجد أن thiscall مُطابق عمليا لــ cdecl لأن الدالة المُستدعية هي من يقوم بتنظيف المكدس كما يتم تمرير الوسائط من الأيمن إلى الأيسر, لكن الفرق يكمن في إضافة المؤشر this حيث تتم إضافته في نهاية المكدس كما لو كان الوسيط الأول.

في الــ MSVC يتم تمرير المؤشر this إلى المسجل ECX و المُستدعى (callee) هو من ينظف المكدس, على غرار الإستدعاء stdcall المُستخدم في C.

أما إذا كانت الدالة تستقبل عدد غير محدد من الوسائط فالمُستدعي caller هو من ينظف المكدس.

مواضيع مشابهة