آلة رمز P

في برمجة الحاسوب ، تُعرف آلة P-code ( آلة الشفرة المحمولة [ 1 ] ) بأنها آلة افتراضية مصممة لتنفيذ شفرة P، وهي لغة التجميع أو شفرة الآلة لوحدة معالجة مركزية افتراضية (CPU). يُستخدم مصطلح "آلة P-code" بشكل عام للإشارة إلى جميع هذه الآلات (مثل آلة جافا الافتراضية (JVM) وشفرة MATLAB المُجمّعة مسبقًا )، بالإضافة إلى التطبيقات المحددة التي تستخدم هذه الآلات. من أبرز استخدامات آلات P-code آلة P في نظام Pascal-P . وقد فسّر مطورو تطبيق UCSD Pascal ضمن هذا النظام حرف P في P-code بمعنى "شبه" أكثر من كونه "محمول"؛ واعتمدوا تسمية فريدة للشفرة الزائفة، أي تعليمات لآلة شبه افتراضية.

على الرغم من أن المفهوم طُبِّق لأول مرة حوالي عام 1966 كلغة O-code للغة البرمجة الأساسية المدمجة ( BCPL ) ولغة P-code للغة أويلر ، [ 2 ] إلا أن مصطلح P -code ظهر لأول مرة في أوائل سبعينيات القرن العشرين. وكان من أوائل المترجمات التي أنتجت لغة P-code مترجم Pascal-P في عام 1973، من قِبَل كيساف ف. نوري، وأورس أمان، وكاثلين جنسن، وهانز-هاينريش ناغيلي، وكريستيان جاكوبي، [ 3 ] ومترجم Pascal-S في عام 1975، من قِبَل نيكلاوس ويرث .

يمكن تفسير البرامج المترجمة إلى لغة P-code إما بواسطة برنامج يحاكي سلوك وحدة المعالجة المركزية الافتراضية، أو ترجمتها إلى لغة الآلة الخاصة بوحدة المعالجة المركزية التي سيتم تشغيل البرنامج عليها، ثم تنفيذها. وفي حال وجود اهتمام تجاري كافٍ، يمكن بناء تطبيق مادي لمواصفات وحدة المعالجة المركزية (مثل محرك Pascal MicroEngine أو نسخة من معالج Java ).

رمز P مقابل رمز الآلة

بينما يهدف نموذج المترجم النموذجي إلى ترجمة كود البرنامج إلى كود الآلة ، فإن فكرة آلة كود P تتبع نهجًا من مرحلتين يتضمن الترجمة إلى كود P والتنفيذ عن طريق التفسير أو الترجمة في الوقت المناسب (JIT) من خلال آلة كود P.

يُتيح هذا الفصل إمكانية فصل تطوير مُفسِّر لغة P عن مُجمِّع لغة الآلة الأساسي، الذي يجب أن يُراعي سلوك الآلة عند توليد رمز البايت الخاص به . وبهذه الطريقة، يُمكن تنفيذ مُفسِّر لغة P بشكل أسرع، كما تُتيح إمكانية تفسير الكود أثناء التشغيل إجراء فحوصات إضافية قد لا تكون مُتاحة في الكود الأصلي. علاوة على ذلك، ولأن لغة P تعتمد على آلة افتراضية مثالية، فغالبًا ما يكون برنامج لغة P أصغر حجمًا من البرنامج نفسه عند ترجمته إلى لغة الآلة. في المقابل، يؤدي التفسير ذو المرحلتين لبرنامج قائم على لغة P إلى إبطاء سرعة التنفيذ، على الرغم من إمكانية معالجة ذلك أحيانًا باستخدام الترجمة الفورية ، كما أن بنيته الأبسط تُسهِّل عملية الهندسة العكسية مقارنةً بالكود الأصلي.

تطبيقات رمز P

في أوائل ثمانينيات القرن العشرين، حقق نظاما تشغيل على الأقل استقلالية تامة عن الأجهزة بفضل الاستخدام المكثف لرمز P. كان نظام تشغيل الأعمال (BOS) نظام تشغيل متعدد المنصات مصممًا لتشغيل برامج رمز P حصريًا. أما نظام UCSD p-System ، الذي طُوّر في جامعة كاليفورنيا، سان دييغو، فكان نظام تشغيل ذاتي التجميع والاستضافة ، يعتمد على رمز P ومُحسَّن للتوليد بواسطة لغة باسكال .

في التسعينيات، أصبحت الترجمة إلى p-code استراتيجية شائعة لتطبيقات لغات مثل Python و Microsoft P-Code في Visual Basic و Java bytecode في Java .

تستخدم لغة Go لغة تجميع عامة وقابلة للنقل كشكل من أشكال التعليمات البرمجية الوسيطة (p-code)، والتي نفذها كين تومسون كامتداد للعمل على Plan 9 من مختبرات Bell . على عكس التعليمات البرمجية الوسيطة لوقت تشغيل اللغة المشتركة (CLR) أو التعليمات البرمجية الوسيطة لآلة جافا الافتراضية (JVM)، لا توجد مواصفات ثابتة، ولا تُصدر أدوات بناء Go تنسيقًا للتعليمات البرمجية الوسيطة لاستخدامه لاحقًا. يستخدم مُجمِّع Go لغة التجميع العامة كتمثيل وسيط ، وتكون ملفات Go التنفيذية عبارة عن ملفات ثنائية مرتبطة بشكل ثابت خاصة بكل جهاز . [ 4 ]

آلة الدفع الإلكتروني بجامعة كاليفورنيا في سان دييغو

بنيان

كغيرها من آلات P-code، تُعدّ آلة UCSD P-Machine آلة مكدس ، ما يعني أن معظم التعليمات تسحب معاملاتها من مكدس ، ثم تعيد النتائج إليه. وبالتالي، addتستبدل التعليمة العنصرين العلويين في المكدس بمجموعهما. وتأخذ بعض التعليمات وسيطًا فوريًا. وكما هو الحال في لغة باسكال، فإن P-code لغة ذات كتابة قوية ، تدعم أنواع البيانات المنطقية (b)، والحرفية (c)، والصحيحية (i)، والحقيقية (r)، والمجموعات (s)، والمؤشرات (a) بشكل أصلي.

بعض التعليمات البسيطة:

وصف مجموعة التعليمات قبل الساعة السابعة   adi i1 i2 i1+i2 جمع عددين صحيحين adr r1 r2 r1+r2 جمع عددين حقيقيين inn i1 s1 b1 set membership; b1 = ما إذا كان i1 عضوًا في s1 ldi i1 i1 i1 تحميل ثابت عدد صحيح mov a1 a2 a2 move ليس b1 b1 -b1 النفي المنطقي

بيئة

على غرار وحدة المعالجة المركزية الحقيقية، يحتوي نظام P على مكدس واحد فقط مشترك بين إطارات مكدس الإجراءات (التي توفر عنوان العودة ، وما إلى ذلك) ووسائط التعليمات المحلية. تشير ثلاثة من سجلات الجهاز إلى المكدس (الذي ينمو للأعلى):

يوجد أيضًا نطاق ثابت، وأسفله كومة الذاكرة التي تنمو نزولًا باتجاه المكدس. يشير سجل NP ( المؤشر الجديد ) إلى أعلى (أقل عنوان مستخدم) كومة الذاكرة. عندما يتجاوز EP قيمة NP، تكون ذاكرة الجهاز قد استُنفدت.

يشير السجل الخامس، PC، إلى التعليمات الحالية في منطقة التعليمات البرمجية.

اصطلاحات الاتصال

تبدو إطارات التكديس كالتالي:

EP -> مجموعة محلية SP -> ... السكان المحليون ... حدود ... عنوان العودة (الكمبيوتر الشخصي السابق) الألبوم المصغر السابق رابط ديناميكي (العضو السابق في البرلمان) رابط ثابت (MP للإجراء المحيط) MP -> قيمة الإرجاع للدالة

يعمل تسلسل استدعاء الإجراء على النحو التالي: يتم تقديم الاستدعاء بواسطة

mst n

حيث nيحدد الفرق في مستويات التداخل (تذكر أن باسكال يدعم الإجراءات المتداخلة). ستُعلِّم هذه التعليمة المكدس ، أي تحجز الخلايا الخمس الأولى من إطار المكدس المذكور أعلاه، وتُهيئ نقطة النهاية السابقة، والربط الديناميكي، والربط الثابت. ثم يقوم المُستدعي بحساب أي معلمات للإجراء ودفعها، ثم يُصدر الأمر

كوب ن، ص

لاستدعاء إجراء مستخدم ( nحيث يمثل عدد المعاملات، pوعنوان الإجراء). سيؤدي هذا إلى حفظ عداد البرنامج في خلية عنوان الإرجاع، وتعيين عنوان الإجراء كعداد البرنامج الجديد.

تبدأ إجراءات المستخدم بتعليمتين

ent 1, i ent 2, j

يُعيّن الأمر الأول SP إلى MP + i، بينما يُعيّن الأمر الثاني EP إلى SP + j. وبذلك i، يُحدد هذا الأمر المساحة المحجوزة للمتغيرات المحلية (بالإضافة إلى عدد المعاملات مضافًا إليه 5)، ويُعطي jعدد الإدخالات المطلوبة محليًا للمكدس. ويتم التحقق من استنفاد الذاكرة عند هذه النقطة.

يتم الرد على المتصل عبر

retC

مع Cتحديد نوع القيمة المُعادة (i، r، c، b، a كما سبق، و p لعدم وجود قيمة مُعادة). يجب تخزين القيمة المُعادة في الخلية المناسبة مسبقًا. في جميع الأنواع باستثناء p، ستترك عملية الإرجاع هذه القيمة في مكدس الاستدعاءات.

بدلاً من استدعاء إجراء المستخدم (cup)، qيمكن استدعاء الإجراء القياسي باستخدام

csp q

هذه الإجراءات القياسية هي إجراءات باسكال مثل readln()( csp rlnsin()( csp sin)، إلخ. وبشكل خاص، eof()هي تعليمات p-Code بدلاً من ذلك.

مثال على آلة

حدد نيكلاوس ويرث نموذجًا بسيطًا لآلة ذات رمز p في كتابه الصادر عام 1976 بعنوان "الخوارزميات + هياكل البيانات = البرامج" . احتوت الآلة على 3 سجلات: عداد البرنامج p ، وسجل الأساس b ، وسجل أعلى المكدس t . وتضمنت 8 تعليمات.

  1. lit 0, a : تحميل الثابت أ
  2. opr 0, a : تنفيذ العملية أ (13 عملية: إرجاع، 5 دوال رياضية، و7 دوال مقارنة)
  3. lodl, a : تحميل المتغير l ، a
  4. stol, a : تخزين المتغير l ، a
  5. call, a استدعاء الإجراء أ في المستوى ل
  6. int 0, a : زيادة قيمة سجل t بمقدار a
  7. jmp 0, a انتقل إلى أ
  8. jpc 0, a : الانتقال المشروط إلى [ 5 ]

هذا هو رمز الآلة، مكتوب بلغة باسكال:

const amax = 2047 ; {الحد الأقصى للعنوان} levmax = 3 ; {الحد الأقصى لعمق تداخل الكتل} cxmax = 200 ; {حجم مصفوفة التعليمات البرمجية}نوع fct = ( lit , opr , lod , sto , cal , int , jmp , jpc ) ; التعليمات = سجل مضغوط f : fct ; l : 0 .. levmax ; a : 0 .. amax ; نهاية ;var code : array [ 0 .. cxmax ] of instruction ;تفسير الإجراء ؛const stacksize = 500 ;var p , b , t : عدد صحيح ؛ {سجلات البرنامج، والقاعدة، والمكدس العلوي} i : تعليمة ؛ {سجل التعليمات} s : مصفوفة [ 1 .. حجم المكدس ] من الأعداد الصحيحة ؛ {مخزن البيانات}دالة base ( l : عدد صحيح ) : عدد صحيح ; متغير b1 : عدد صحيح ; ابدأ b1 := b ; {ابحث عن الأساس l مستويات لأسفل} بينما l > 0 نفّذ ابدأ b1 := s [ b1 ] ; l := l - 1 نهاية ; base := b1 نهاية {base} ;ابدأ كتابة ( 'ابدأ pl/0' ) ؛ t := 0 ؛ b := 1 ؛ p := 0 ؛ s [ 1 ] := 0 ؛ s [ 2 ] := 0 ؛ s [ 3 ] := 0 ؛ كرر i := code [ p ] ؛ p := p + 1 ؛ مع نفّذ ما يلي : حالة f من lit : ابدأ t := t + 1 ؛ s [ t ] := a نهاية ؛ opr : حالة a من {operator} 0 : ابدأ {return} t := b - 1 ؛ p := s [ t + 3 ] ؛ b := s [ t + 2 ] ؛ نهاية ؛ 1 : s [ t ] := -s [ t ] ؛ 2 : ابدأ t : = t - 1 ؛ s [ t ] := s [ t ] + s [ t + 1 ] end ; 3 : begin t := t - 1 ; s [ t ] := s [ t ] - s [ t + 1 ] end ; 4 : begin t := t - 1 ; s [ t ] := s [ t ] * s [ t + 1 ] end ;5 : ابدأ t := t - 1 ؛ s [ t ] := s [ t ] div s [ t + 1 ] نهاية ؛ 6 : s [ t ] := ord ( odd ( s [ t ])) ؛ 8 : ابدأ t := t - 1 ؛ s [ t ] := ord ( s [ t ] = s [ t + 1 ]) نهاية ؛ 9 : ابدأ t := t - 1 ؛ s [ t ] := ord ( s [ t ] <> s [ t + 1 ]) نهاية ؛ 10 : ابدأ t := t - 1 ؛ s [ t ] := ord ( s [ t ] < s [ t + 1 ]) نهاية ؛ 11 : ابدأ t := t - 1 ؛ s [ t ] := ord ( s [ t ] >= s [ t + 1 ]) end ; 12 : begin t := t - 1 ; s [ t ] := ord ( s [ t ] > s [ t + 1 ]) end ; 13 : begin t := t - 1 ; s [ t ] := ord ( s [ t ]<= s [ t + 1 ]) end ; end ; lod : begin t := t + 1 ; s [ t ] := s [ base ( l ) + a ] end ; sto : begin s [ base ( l ) + a ] := s [ t ] ; writeln ( s [ t ]) ; t := t - 1 end ; cal : begin {generate new block mark} s [ t + 1 ] := base ( l ) ; s [ t + 2 ] := b ; s [ t + 3 ] := p ; b := t + 1 ; p := a end ; int : t := t + a ; jmp : p := a ; jpc : begin if s [ t ] = 0 then p := a ; t := t - 1 end end {with, case} until p = 0 ; writeln ( ' end pl/0' ) ; end {interpret} ;

استُخدم هذا الجهاز لتشغيل برنامج Wirth's PL/0 ، وهو مُترجم فرعي من لغة باسكال يُستخدم لتعليم تطوير المُترجمات. [ 6 ]

رمز مايكروسوفت P

كان هدف الشركة هو إصدار برامج لجميع المنصات والبنى الرئيسية الموجودة آنذاك. بين عامي 1980 و1982، طورت مايكروسوفت مُترجمًا مبكرًا للغة C ينتج رمز P (لم تكن لغة C موحدة آنذاك، ولم تُوحد إلا في أواخر الثمانينيات). سمح رمز P بتشغيل البرامج على معظم المنصات مع الحد الأدنى من تغيير الكود. استخدمت جامعة كاليفورنيا في سان دييغو (UCSD) نهجًا مشابهًا. حقق هذا التحويل من C إلى P نجاحًا، ولكنه كان بطيئًا للغاية. في عام 1983، أصدرت مايكروسوفت مُترجم Microsoft C (MSC)، استنادًا إلى ترخيص مُترجم Lattice C للإصدارين 1.0 و2.0؛ ثم، بدءًا من الإصدار 3.0، أُعيدت كتابة MSC بالكامل بواسطة مايكروسوفت. [ 7 ]

P-code هو اسم استخدمته لاحقًا بعض لغات البرمجة الوسيطة من مايكروسوفت . وقد وفرت هذه اللغات صيغة ثنائية بديلة لرمز الآلة. وفي مناسبات مختلفة، ذكرت مايكروسوفت أن P-code هو اختصار إما لـ " الرمز المضغوط" [ 8 ] أو "الرمز الزائف" [ 9 ] .

استُخدم نوعٌ من أكواد مايكروسوفت P-code، يختلف تمامًا عن ذلك المستخدم في مُصرّف لغة C، على نطاق واسع مع لغة Visual Basic التي كانت تحتوي على بيئة تشغيل تتضمن آلة افتراضية أو يُمكن ترجمتها مباشرةً إلى كود أصلي. ومثل تطبيقات P-code الأخرى، مكّنت أكواد مايكروسوفت P-code من إنشاء ملف تنفيذي أكثر إحكامًا على حساب بطء التنفيذ.

تطبيقات أخرى

انظر أيضاً

مراجع

  1. أبتون، إيبن؛ دونتيمان، جيفري؛ روبرتس، رالف؛ ماموتورا، تيم؛ إيفرارد، بن (13 سبتمبر 2016). تعلم هندسة الحاسوب باستخدام راسبيري باي . جون وايلي وأولاده. ISBN 978-1-119-18393-8.
  2. ويرث، نيكلاوس ؛ ويبر، هيلموت (1966). "أويلر: تعميم للغة ALGOL، وتعريفها الرسمي: الجزء الثاني" . مجلة اتصالات ACM . 9 (2). نيويورك، الولايات المتحدة الأمريكية: رابطة آلات الحوسبة (ACM): 89-99 . doi : 10.1145/365170.365202 . S2CID 12124100 . 
  3. ^ نوري، كيساف ف. عمان، أورس؛ جنسن، كاثلين. ناجيلي، هانز هاينريش. جاكوبي ، كريستيان (1975). ملاحظات تنفيذ مترجم Pascal P . زيورخ، سويسرا: Eidgenössische Technische Hochschule (ETH).
  4. بايك، روبرت سي. (2016). "تصميم مُجمِّع لغة جو" . يوتيوب (محاضرة في مؤتمر). مؤرشف من الأصل بتاريخ 11 ديسمبر 2021. تم الاطلاع عليه بتاريخ 25 أغسطس 2017 .
  5. "أرشيف الفئات: ويرث - أويلر - من تصميم نيكلاوس ويرث وهيلموت ويبر" . باسكال للآلات الصغيرة - لغات ويرث، باسكال، جامعة كاليفورنيا في سان دييغو، توربو، دلفي، فري باسكال، أوبرون . 2018-08-02.
  6. ألبرت، دونالد (سبتمبر 1979). مترجم لغة باسكال P-Code لجائزة ستانفورد إيمي (ملف PDF) (تقرير). مختبر أنظمة الحاسوب، قسمي الهندسة الكهربائية وعلوم الحاسوب، جامعة ستانفورد. مذكرة فنية رقم 164.
  7. "البرمجيات" . مجلة Computerworld . 19 (15). فرامينغهام، ماساتشوستس: CW Communications: 71. 15 أبريل 1985. ISSN 0010-4841 . أعلنت مايكروسوفت عن إصدار مُحسّن من مُجمّع لغة C الخاص بها لأجهزة الكمبيوتر الشخصية من IBM... وقال متحدث باسم الشركة إن الإصدار 3.0 هو أول مُجمّع لغة C يتم تطويره داخليًا بواسطة مايكروسوفت. 
  8. باداور، آندي (أبريل 1992). "تقنية مايكروسوفت بي-كود" . شبكة مطوري مايكروسوفت . مؤرشف من الأصل في 22 فبراير 2001.
  9. "تجميع مشروعك إلى كود أصلي" . وثائق Visual Studio 6.0 . 2007. مؤرشف من الأصل في 27-02-2007.

للمزيد من القراءة

  • معلومات رمز VB P من السيد سيلفر على موقع Wayback Machine (تمت أرشفته في 22 ديسمبر 2015)