الدرس 2 من 8

اصطلاح الاستدعاء وإطار المكدّس

هدف الدرس

أين تدخل الوسائط وأين يخرج الناتج

01

الشرح

حين تستدعي دالةٌ دالةً أخرى يجب أن تتّفقا على مكان الوسائط ومكان الناتج، وهذا الاتّفاق اسمه اصطلاح الاستدعاء (calling convention). والبرامج على x86-64 في لينكس وماك تتبع اصطلاح System V:

  • الوسائط الستّة الأوّلى في المسجّلات بهذا الترتيب: rdi ثم rsi ثم rdx ثم rcx ثم r8 ثم r9.
  • ما زاد على ستّة وسائط يمرّ على المكدّس.
  • الناتج يعود في rax.

أمّا ويندوز فله اصطلاح آخر يبدأ بـ rcx، فاعرف أوّلًا لأي نظام بُني البرنامج الذي تقرؤه.

والمكدّس (stack) ذاكرة تنمو نحو العناوين الأدنى، وتحجز فيه كل دالة إطارًا (stack frame) لمتغيّراتها المحلّية. والمترجِم بلا تحسين يبدأ الدالة عادةً بأمرين: الأمر push rbp يحفظ قاعدة إطار الدالة التي استدعتها، والأمر mov rbp, rsp يجعل القمّة الحالية قاعدةً للإطار الجديد. بعدها تُقرأ المتغيّرات المحلّية بإزاحة سالبة من rbp مثل [rbp-4]، والقوسان المربّعان يعنيان القيمة المخزّنة في ذلك العنوان.

     العنوان الأعلى
+----------------+
| return address |  [rbp+8]
+----------------+
| saved rbp      |  [rbp]
+----------------+
| a              |  [rbp-4]
| b              |  [rbp-8]
+----------------+
     العنوان الأدنى
  • في [rbp+8] عنوان العودة الذي وضعه الأمر call.
  • في [rbp] قاعدة إطار الدالة التي استدعتها.
  • في [rbp-4] و[rbp-8] الوسيطان a وb بعد أن نسختهما الدالة من edi وesi.

وهذه دالة الإطار المرسوم أعلاه كما يُخرجها المترجِم بلا تحسين. نسخت وسيطيها من المسجّلين إلى إطارها ثم قرأتهما منه، والأمر pop rbp في آخرها يُرجع قاعدة الإطار السابق قبل أن يعود ret إلى عنوان العودة:

g:
  push rbp
  mov  rbp, rsp
  mov  [rbp-4], edi   ; a
  mov  [rbp-8], esi   ; b
  mov  eax, [rbp-4]   ; eax = a
  sub  eax, [rbp-8]   ; eax = a - b
  pop  rbp
  ret

ولاحظ أنها كتبت في [rbp-4] و[rbp-8] دون أن تحجز مكانًا بالأمر sub rsp, N أوّلًا. والسبب أن لينكس يمنح الدالة التي لا تنادي غيرها (leaf) مئةً وثمانية وعشرين بايتًا تحت قمّة المكدّس تسمّى المنطقة الحمراء (red zone)، تستعملها بلا حجز. أمّا الدالة التي تنادي غيرها فتحجز إطارها بـ sub rsp, N، وويندوز لا منطقة حمراء فيه بل يحجز المنادي اثنين وثلاثين بايتًا تسمّى مساحة الظلّ (shadow space).

02

المطلوب

اكتب الدالة g(a, b) التي تكافئ دالة الأسمبلي أعلاه، والدالة arg_register(n) التي تُرجع اسم المسجّل الذي يحمل الوسيط رقم n في اصطلاح System V (من 1 إلى 6)، والمتغيّر return_register وفيه اسم مسجّل الناتج. اكتب أسماء المسجّلات الكاملة بحروف صغيرة، مثل "rdi".

الفحوص

5 فحوص
  1. الدالة g تطرح الوسيط الثاني من الأوّل
  2. الدالة g تكافئ دالة الأسمبلي على قيم أخرى
  3. الوسيط الأوّل في rdi
  4. الوسائط الستّة بترتيبها
  5. الناتج في rax
03

تلميحات

0/3
دروس المسارأتممت 0 من 8

اقرأ الأسمبلي واصطلاح الاستدعاء وتدفّق التحكّم، وابنِ لآلة صغيرة مفكّكًا ومحاكيًا، ثم رقّع بايتاتها وتحقّق من سلامتها.

مستواه متوسّط، وفيه 8 دروس مجموع مدّتها ساعتان.

main.py
المخرجاتPython (Pyodide)

نحمّل بيئة Python الآن. يحدث هذا مرّة واحدة فقط، ثم يحفظها متصفّحك.

–/5

يبدأ الفحص حين تجهز البيئة.

تجد 5 فحوص في بطاقة «المطلوب».

دروس المسارأتممت 0 من 8

اقرأ الأسمبلي واصطلاح الاستدعاء وتدفّق التحكّم، وابنِ لآلة صغيرة مفكّكًا ومحاكيًا، ثم رقّع بايتاتها وتحقّق من سلامتها.

مستواه متوسّط، وفيه 8 دروس مجموع مدّتها ساعتان.