Nand2Tetris — الجزء الثاني: من الآلة الافتراضية إلى نظام التشغيل › المشروع 7: الآلة الافتراضية I: الحساب على المكدس 1 / 6 التالي

المشروع 7: الآلة الافتراضية I: الحساب على المكدس

المشروع 7: الآلة الافتراضية I - الحساب على المكدس

خلفية

تُولِّد مُصرِّفات Java (أو C#) شيفرةً مكتوبةً بلغة وسيطة تُسمّى bytecode (أو IL). وهذه الشيفرة مصمَّمة للعمل على معمارية آلة افتراضية مثل JVM (أو CLR). وإحدى طرق تنفيذ برامج هذه الآلات هي ترجمتها إلى برامج أدنى مستوىً مكتوبة بلغة آلة حاسوب مضيف مُعَيَّن (حقيقي لا افتراضي). وفي المشروعَين 7 و8 نبني مثل هذا المترجم، المصمَّم لترجمة البرامج المكتوبة بلغة VM إلى برامج مكتوبة بلغة التجميع Hack. أما لغة VM وتجرّدها وعملية الترجمة فموصوفة في الفصلَين 7 و8 من الكتاب. ويمكن تجاهل الفصل 8 لأغراض هذا المشروع.

الهدف

ابنِ مُترجِم VM أساسيًّا، مع التركيز على تنفيذ أوامر الحساب على المكدس وأوامر الوصول إلى الذاكرة في لغة VM. وفي المشروع 8 سيُوسَّع هذا المترجم الأساسي ليصبح مُترجِم VM متكاملًا.

العقد

اكتب مُترجِمًا من VM إلى Hack، مطابقًا لمواصفة VM الجزء الأول (قسم 7.2 من الكتاب) ولتعيين VM القياسي على Hack الجزء الأول (قسم 7.3.1 من الكتاب). واستخدم مترجمك لترجمة ملفات VM المرفقة أدناه، منتِجًا برامج مقابلة مكتوبة بلغة التجميع Hack. وعند تشغيلها على محاكي CPU المرفق، يجب أن تُنتِج الشيفرة المترجمة التي يولّدها مترجمك النتائج المطلوبة في سكربتات الاختبار وملفات المقارنة المرفقة أدناه.

الاستخدام

حسب لغة البرمجة التي تستخدمها، يُستدعى مُترجِم VM بشيء يشبه "VMTranslator fileName.vm"، حيث السلسلة fileName.vm هي مُدخِل المترجم، أي اسم ملف نصّي يحتوي على أوامر VM. ويُنشئ المترجم ملف إخراج باسم fileName.asm، يُخزَّن في مجلد الملف المدخل نفسه. وقد يحتوي اسم الملف المدخل على مسار.

الموارد

القراءة ذات الصلة بهذا المشروع هي الفصل 7. وستحتاج إلى أداتَين: لغة البرمجة التي ستُنفِّذ بها مترجم VM، ومحاكي CPU المرفق. ويتيح هذا المحاكي تنفيذ واختبار شيفرة الآلة التي يولّدها مترجم VM على حاسوبك. وأداة أخرى تأتي في متناول اليد في هذا المشروع هي محاكي VM المرفق. ويتيح محاكي VM (الموصوف أسفل هذه الصفحة) التجريب مع برامج VM المرفقة قبل الشروع في كتابة مترجم VM.

التنفيذ المقترح

نقترح تنفيذ واجهة برمجة التطبيقات (API) لمترجم VM الأساسي الموصوفة في الفصل 7 على مرحلتَين. وسيتيح لك ذلك اختبار تنفيذك تدريجيًّا باستخدام برامج الاختبار المرفقة أدناه. وفيما يلي، عندما نقول "يجب أن ينفِّذ مترجم VM بعض أوامر VM" فإننا نعني "يجب أن يترجم مترجم VM أمر VM المعطى إلى تسلسل من أوامر تجميع Hack تؤدّي المهمة نفسها".

المرحلة I: التعامل مع أوامر الحساب على المكدس: يجب أن تُنفِّذ النسخة الأولى من مترجم VM الأساسي الأوامر الحسابية/المنطقية التسعة للغة VM، بالإضافة إلى أمر VM المتمثل في push constant x.

والأمر الأخير هو أمر push العام الذي يكون وسيطه الأول constant ووسيطه الثاني عددًا صحيحًا غير سالب x. ويأتي هذا الأمر في متناول اليد في هذه المرحلة المبكرة، إذ يساعد على توفير قيم لاختبار تنفيذ أوامر VM الحسابية/المنطقية. فعلى سبيل المثال، لاختبار كيفية تعامُل مترجم VM مع الأمر add، يمكننا اختبار كيفية تعامُله مع شيفرة VM المتمثلة في: push constant 3، push constant 5، add. وتُختبر الأوامر الحسابية والمنطقية الأخرى بالمثل.

المرحلة II: التعامل مع أوامر الوصول إلى الذاكرة: يجب أن تتضمّن النسخة التالية من مترجم VM الأساسي تنفيذًا كاملًا لأوامر push و pop في لغة VM، مع التعامل مع مقاطع الذاكرة الثمانية الموصوفة في الفصل 7. ونقترح تقسيم هذه المرحلة إلى المراحل الفرعية التالية:

  • لقد تعاملت بالفعل مع مقطع constant؛

  • ثم، تعامل مع المقاطع local و argument و this و that؛

  • ثم، تعامل مع مقطعَي pointer و temp، ولا سيّما السماح بتعديل قاعدتَي مقطعَي this و that؛

  • وأخيرًا، تعامل مع مقطع static.

الاختبار

نرفق خمسة برامج VM، مصمَّمة لاختبار التنفيذ التدريجي المقترح أعلاه اختبارًا وحدويًّا. ولكل برنامج Xxx نرفق أربعة ملفات. ويحتوي ملف Xxx.vm على شيفرة البرنامج. ويتيح سكربت XxxVME.tst تشغيل البرنامج على محاكي VM المرفق، للتجريب مع التشغيل المقصود للبرنامج. وبعد ترجمة البرنامج باستخدام مترجمك، يتيح سكربت Xxx.tst وملف المقارنة Xxx.cmp المرفقان اختبار شيفرة التجميع المترجمة على محاكي CPU المرفق.

اختبار كيفية تعامُل مُترجِم VM مع أوامر الحساب:

البرنامج الوصف سكربتات الاختبار
SimpleAdd.vm يدفع ثابتَين إلى المكدس ويجمعهما. SimpleAddVME.tst SimpleAdd.tst SimpleAdd.cmp
StackTest.vm ينفّذ تسلسلًا من العمليات الحسابية والمنطقية على المكدس. StackTestVme.tst StackTest.tst StackTest.cmp

اختبار كيفية تعامُل مُترجِم VM مع أوامر الوصول إلى الذاكرة:

البرنامج الوصف
BasicTest.vm ينفّذ عمليتَي push/pop باستخدام مقاطع الذاكرة الافتراضية constant و local و argument و this و that و temp.
PointerTest.vm ينفّذ عمليتَي push/pop باستخدام مقاطع الذاكرة الافتراضية pointer و this و that.
StackTest.vm ينفّذ عملية push/pop باستخدام مقطع الذاكرة الافتراضي static.
سكربتات الاختبار
BasicTestVME.tst BasicTest.tst BasicTest.cmp
PointerTestVME.tst PointerTest.tst PointerTest.cmp
StaticTestVME.tst StaticTest.tst StaticTest.cmp

نصائح

التهيئة: لكي تُنفَّذ شيفرة VM المترجمة على منصة الحاسوب المضيف، يجب أن يتضمّن تدفّق الشيفرة المترجمة (المكتوب بلغة آلة المنصة المضيفة) بعض شيفرة التهيئة (bootstrap) التي تُخطِّط المكدس على ذاكرة الحاسوب المضيف وتبدأ تنفيذ الشيفرة الفعلية. وبالإضافة إلى ذلك، يجب تخطيط مقاطع الذاكرة الافتراضية على مناطق مختارة في ذاكرة الحاسوب المضيف. وشيفرة التهيئة وتخطيطات الذاكرة موصوفة في الفصل 8 ويتعامل معها الإصدار النهائي من مترجم VM، المُنفَّذ في المشروع التالي. وفي هذا المشروع لا داعي للقلق بشأن أي من هذه المسائل، إذ تتولّى سكربتات الاختبار المرفقة كل التهيئات وتخطيطات الذاكرة اللازمة. وبعبارة أخرى، يجب أن تحتوي شيفرة التجميع التي يولّدها مترجمك على ترجمة أوامر VM الموجودة في الملف المدخل، ولا شيء غير ذلك.

الخطوات:

لكل واحد من برامج الاختبار الخمسة المرفقة أعلاه، اتّبع الخطوات التالية:

  • للتعرّف على السلوك المقصود لبرنامج الاختبار Xxx.vm المرفق، شغّله على محاكي VM المرفق باستخدام سكربت XxxVME.tst المرفق.

  • استخدم مترجم VM لترجمة ملف Xxx.vm المرفق. ويجب أن تكون النتيجة ملفًا نصّيًا جديدًا يحتوي على شيفرة تجميع Hack، باسم Xxx.asm.

  • افحص برنامج Xxx.asm الذي أنتجه مترجم VM. فإن ظهرت أخطاء في الصياغة (أو أي أخطاء أخرى)، نقِّح وأصلح مترجم VM.

  • وللتحقق من أداء الشيفرة المنتَجة بشكل سليم، استخدم ملفَّي Xxx.tst و Xxx.cmp المرفقَين لتشغيل برنامج Xxx.asm على محاكي CPU المرفق. فإن ظهرت أي مشاكل، نقِّح وأصلح مترجم VM.

ترتيب التنفيذ: خُطِّطت برامج الاختبار المرفقة بعناية لاختبار الميزات التدريجية التي تُدخِلها كل مرحلة من مراحل تطوير مترجم VM الأساسي. لذا من المهم تنفيذ المترجم بالترتيب المقترح، واختباره باستخدام برامج الاختبار المناسبة في كل مرحلة. وقد يُسبّب تنفيذ مرحلة لاحقة قبل مرحلة سابقة فشل برامج الاختبار.

عند الانتهاء من هذا المشروع، احرص على حفظ نسخة من مترجم VM. ففي المشروع التالي سيُطلب منك تعديل هذا البرنامج وتوسعته، بإضافة التعامل مع المزيد من أوامر VM. فإن أدّت تعديلات المشروع 8 إلى تعطيل بعض الشيفرة العاملة التي طُوِّرت في المشروع 7، فستتمكّن من الرجوع إلى نسخة احتياطية نظيفة.

الأدوات

قبل الشروع في تطوير مترجم VM، نوصي بالتعرّف على نموذج معمارية الآلة الافتراضية ولغتها. وكما ذُكر أعلاه، يمكن فعل ذلك بتشغيل برامج الاختبار .vm المرفقة والتجريب بها باستخدام محاكي VM المرفق.

محاكي VM: هذا البرنامج المكتوب بلغة Java، الموجود في مجلد nand2tetris/tools خاصتك، مصمَّم لتنفيذ برامج VM بطريقة مباشرة ومرئية، دون الحاجة إلى ترجمتها أولًا إلى لغة الآلة. فعلى سبيل المثال، يمكنك استخدام محاكي VM المرفق لترى - حرفيًّا - كيف تؤثّر أوامر push و pop في المكدس. ويمكنك استخدام المحاكي لتنفيذ أي من برامج الاختبار .vm المرفقة.

لمزيد من المعلومات، انظر درس محاكي VM (PPT، PDF)

إليك صورة شاشة نموذجية لمحاكي VM أثناء العمل: