لغة وسيطة مشتركة
لغة الوسيط المشتركة ( CIL )، والتي كانت تُعرف سابقًا باسم لغة مايكروسوفت الوسيطة ( MSIL ) أو اللغة الوسيطة ( IL )، [ 1 ] هي مجموعة تعليمات ثنائية للغة الوسيطة مُعرَّفة ضمن مواصفات البنية التحتية للغة المشتركة (CLI). [ 2 ] تُنفَّذ تعليمات CIL بواسطة بيئة تشغيل متوافقة مع CIL، مثل بيئة تشغيل اللغة المشتركة ( CLI ). اللغات التي تستهدف CLI تُترجم إلى CIL. CIL هي لغة بايت كود كائنية التوجه تعتمد على المكدس . عادةً ما تُترجم بيئات التشغيل تعليمات CIL إلى كود أصلي في الوقت المناسب .
كانت لغة CIL تُعرف في الأصل باسم لغة مايكروسوفت الوسيطة (MSIL) خلال الإصدارات التجريبية للغات .NET. وبسبب توحيد لغة C# وواجهة سطر الأوامر (CLI)، أصبح رمز البايت يُعرف رسميًا باسم CIL. [ 3 ] ولا تزال تعريفات فيروسات Windows Defender تشير إلى الملفات الثنائية المُجمَّعة باستخدامها باسم MSIL. [ 4 ]
معلومات عامة
أثناء تجميع لغات برمجة واجهة سطر الأوامر (CLI) ، يُترجم الكود المصدري إلى كود CIL بدلاً من كود كائن خاص بمنصة أو معالج معين . CIL عبارة عن مجموعة تعليمات مستقلة عن وحدة المعالجة المركزية والمنصة، ويمكن تنفيذها في أي بيئة تدعم بنية اللغة المشتركة (CIL)، مثل بيئة تشغيل .NET على نظام ويندوز ، أو بيئة تشغيل Mono متعددة المنصات . نظريًا، يُغني هذا عن الحاجة إلى توزيع ملفات تنفيذية مختلفة لمنصات وأنواع وحدات معالجة مركزية مختلفة. يتم التحقق من سلامة كود CIL أثناء التشغيل، مما يوفر أمانًا وموثوقية أفضل من الملفات التنفيذية المُجمّعة أصلاً. [ 5 ] [ 6 ]
تبدو عملية التنفيذ على النحو التالي:
- يتم تحويل الكود المصدري إلى بايت كود CIL ويتم إنشاء تجميع CLI .
- عند تنفيذ تجميعة CIL، يمر رمزها عبر مُترجم JIT الخاص بوقت التشغيل لتوليد رمز أصلي. يمكن أيضًا استخدام الترجمة المسبقة، التي تلغي هذه الخطوة، ولكن على حساب قابلية نقل الملف التنفيذي.
- يقوم معالج الكمبيوتر بتنفيذ التعليمات البرمجية الأصلية.
تعليمات
تحتوي بايت كود CIL على تعليمات لمجموعات المهام التالية:
- تحميل وتخزين
- الحساب
- تحويل النوع
- إنشاء الكائنات ومعالجتها
- إدارة مكدس المعاملات (دفع/سحب)
- نقل السيطرة (التفرع)
- استدعاء الأسلوب وإرجاعه
- إطلاق الاستثناءات
- التزامن القائم على المراقبة
- معالجة مؤشرات البيانات والدوال ضرورية لـ C++/CLI ولشفرة C# غير الآمنة
النموذج الحسابي
لغة الوسيط المشتركة هي لغة كائنية التوجه وقائمة على المكدس ، مما يعني أن معلمات التعليمات والنتائج يتم الاحتفاظ بها في مكدس واحد بدلاً من عدة سجلات أو مواقع ذاكرة أخرى، كما هو الحال في معظم لغات البرمجة .
الكود الذي يجمع رقمين بلغة التجميع x86 ، حيث يحدد eax و edx سجلين مختلفين للأغراض العامة :
أضف eax و edxكتابة الكود بلغة وسيطة (IL)، حيث يمثل 0 قيمة eax ويمثل 1 قيمة edx:
ldloc.0 // دفع المتغير المحلي 0 إلى المكدس ldloc.1 // دفع المتغير المحلي 1 إلى المكدس add // سحب العنصرين العلويين من المكدس وإضافتهما ثم دفع النتيجة إلى المكدس stloc.0 // سحب العنصر العلوي من المكدس وتخزينه في المتغير المحلي 0في المثال الأخير، تُدفع قيم المسجلين eax وedx أولاً إلى المكدس. عند استدعاء تعليمة الجمع، تُسحب المعاملات، أو تُسترجع، وتُدفع النتيجة، أو تُخزن، في المكدس. ثم تُسحب القيمة الناتجة من المكدس وتُخزن في eax.
مفاهيم البرمجة الكائنية
تم تصميم لغة CIL لتكون موجهة نحو الكائنات. يمكن للمستخدم إنشاء كائنات، واستدعاء أساليب، واستخدام أنواع أخرى من الأعضاء، مثل الحقول.
يجب أن يكون كل أسلوب (باستثناءات قليلة) موجودًا في فئة. وينطبق هذا أيضًا على هذا الأسلوب الثابت:
.class public Foo { .method public static int32 Add ( int32 , int32 ) cil managed { .maxstack 2 ldarg .0 // تحميل الوسيط الأول؛ ldarg .1 // تحميل الوسيط الثاني؛ add // جمعهما؛ ret // إرجاع النتيجة ؛ } }لا تتطلب الدالة Add تعريف أي نسخة من Foo لأنها معلنة كدالة ثابتة، ويمكن استخدامها على النحو التالي في لغة C#:
int r = Foo.Add ( 2 , 3 ) ; // 5في نظام CIL، سيبدو الأمر على النحو التالي:
ldc.i4.2 ldc.i4.3 call int32 Foo :: Add ( int32 , int32 ) stloc.0فئات النسخ
تحتوي فئة الكائن على مُنشئ واحد على الأقل وبعض أعضاء الكائن . تحتوي الفئة التالية على مجموعة من الطرق التي تُمثل إجراءات كائن السيارة.
. class public Car { . method public specialname rtspecialname instance void . ctor ( int32 , int32 ) cil managed { /* المُنشئ */ }. method public void Move ( int32 ) cil managed { /* تم حذف التنفيذ */ } . method public void TurnRight () cil managed { /* تم حذف التنفيذ */ } . method public void TurnLeft () cil managed { /* تم حذف التنفيذ */ } . method public void Brake () cil managed { /* تم حذف التنفيذ */ } }إنشاء الكائنات
في لغة C#، يتم إنشاء مثيلات الفئات على النحو التالي:
Car myCar = new Car ( 1 , 4 ); Car yourCar = new Car ( 1 , 3 );وهذه التصريحات هي نفسها تقريباً هذه التعليمات في CIL:
ldc.i4.1ldc . i4 .4newobj instance void Car ::. ctor ( int32 , int32 )stloc .0 // myCar = new Car(1, 4);ldc.i4.1ldc.i4.3newobj instance void Car ::. ctor ( int32 , int32 )stloc .1 // yourCar = new Car(1, 3);استدعاء أساليب الكائن
يتم استدعاء طرق النسخ في لغة C# على النحو التالي:
myCar.Move ( 3 ) ;كما هو منصوص عليه في CIL:
ldloc.0 // تحميل الكائن " myCar " على المكدس ldc.i4.3 call instance void Car :: Move ( int32 )البيانات الوصفية
تسجل بنية اللغة المشتركة (CLI) معلومات حول الفئات المُجمَّعة كبيانات وصفية . ومثل مكتبة الأنواع في نموذج كائن المكون ، يُمكّن هذا التطبيقات من دعم واكتشاف الواجهات والفئات والأنواع والأساليب والحقول في التجميع. وتُعد عملية قراءة هذه البيانات الوصفية جزءًا من البرمجة الانعكاسية ( الانعكاس ).
يمكن أن تكون البيانات الوصفية بيانات على شكل سمات . ويمكن تخصيص هذه السمات بتوسيع Attributeالفئة. هذه ميزة قوية، إذ تتيح لمنشئ الفئة إمكانية إضافة معلومات إضافية يمكن لمستخدمي الفئة استخدامها بطرق متنوعة وفعّالة، بحسب مجال التطبيق.
مثال
فيما يلي برنامج أساسي مكتوب بلغة التجميع CIL بعنوان "Hello, World!" . سيعرض البرنامج العبارة "Hello, world!".
.assembly Hello {} .assembly extern mscorlib { } .method static void Main ( ) { .entrypoint .maxstack 1 ldstr " Hello , world ! " call void [ mscorlib ] System.Console :: WriteLine ( string ) ret }الكود التالي أكثر تعقيدًا من حيث عدد رموز العمليات.
يمكن أيضًا مقارنة هذا الكود بالكود المقابل في المقالة المتعلقة بـ JVM bytecode .
static void Main ( string [ ] args ) { for ( int i = 2 ; i < 1000 ; i ++ ) { for ( int j = 2 ; j < i ; j ++ ) { if ( i % j == 0 ) goto outer ; } Console.WriteLine ( i ) ; outer :; } }في صيغة لغة التجميع CIL، يبدو الأمر كالتالي:
. method private hidebysig static void Main ( string [] args ) cil managed { . entrypoint . maxstack 2 . locals init ( int32 V_0 , int32 V_1 )إل دي سي . i4 .2 ستلوك .0 ر . ق IL_001f IL_0004 : أقل من . i4 .2 ستلوك .1 ر . s IL_0011 IL_0008 : ldloc .0 ldloc .1 rem brfalse . ق IL_001b ldloc .1 LDC . i4 .1 إضافة stloc .1 IL_0011 : ldloc .1 ldloc .0 blt . s IL_0008 ldloc .0 استدعاء باطل [ mscorlib ] النظام . وحدة التحكم :: WriteLine ( int32 ) IL_001b : ldloc .0 ldc . i4 .1 أضف stloc .0 IL_001f : ldloc .0 ldc . i4 0x3e8 بي تي . ق IL_0004 ريت }هذا مجرد تمثيل لكيفية ظهور لغة CIL بالقرب من مستوى الآلة الافتراضية (VM). عند تجميعها، تُخزَّن الطرق في جداول، وتُخزَّن التعليمات كبايتات داخل التجميع، وهو ملف تنفيذي محمول (PE).
جيل
يتم إنشاء تجميع CIL والتعليمات إما بواسطة مترجم أو أداة مساعدة تسمى IL Assembler ( ILAsm ) والتي يتم شحنها مع بيئة التنفيذ.
يمكن أيضًا تفكيك لغة CIL المُجمّعة إلى شفرة برمجية باستخدام مُفكِّك لغة IL (ILDASM). كما يمكن لأدوات أخرى، مثل .NET Reflector ، فك تجميع CIL إلى لغة برمجة عالية المستوى (مثل C# أو Visual Basic ). هذا يجعل CIL هدفًا سهلًا جدًا للهندسة العكسية. تشترك لغة JVM في هذه الخاصية مع بايت كود . مع ذلك، توجد أدوات قادرة على إخفاء الشفرة البرمجية، بحيث يصعب قراءتها مع إمكانية تشغيلها.
تنفيذ
مجموعة مُجمّعة في الوقت المناسب
تتضمن عملية الترجمة الفورية (JIT) تحويل الشفرة البايتية إلى شفرة قابلة للتنفيذ الفوري بواسطة وحدة المعالجة المركزية. ويتم هذا التحويل تدريجيًا أثناء تنفيذ البرنامج. توفر الترجمة الفورية تحسينًا خاصًا بالبيئة وتحققًا من التجميع. ولتحقيق ذلك، يفحص مُترجم JIT بيانات التجميع الوصفية بحثًا عن أي وصول غير مصرح به ويتعامل مع المخالفات بشكل مناسب.
تجميع مسبق
تأتي بيئات التنفيذ المتوافقة مع واجهة سطر الأوامر أيضًا مع خيار إجراء تجميع مسبق (AOT) للتجميع لجعله ينفذ بشكل أسرع عن طريق إزالة عملية JIT في وقت التشغيل.
في إطار عمل .NET، توجد أداة خاصة تُسمى مولد الصور الأصلي (NGEN) تُنفذ عملية الترجمة المسبقة (AOT). وهناك نهج مختلف للترجمة المسبقة يتمثل في CoreRT، الذي يسمح بتجميع كود .NET Core في ملف تنفيذي واحد دون الاعتماد على بيئة تشغيل. كما يدعم Mono أيضًا الترجمة المسبقة.
تعليمات المؤشر - C++/CLI
يتمثل أحد الاختلافات الملحوظة عن بايت كود جافا في أن CIL يأتي مع ldind، stind، ldloca، والعديد من تعليمات الاستدعاء التي تكفي لمعالجة مؤشرات البيانات / الوظائف اللازمة لتجميع كود C / C++ إلى CIL.
class A { public : virtual void __stdcall meth () {} }; void test_pointer_operations ( int param ) { int k = 0 ; int * ptr = & k ; * ptr = 1 ; ptr = & param ; * ptr = 2 ; A a ; A * ptra = &a a ; ptra -> meth (); }يمكن عرض الكود المقابل في لغة CIL على النحو التالي:
. method assembly static void modopt ([ mscorlib ] System . Runtime . CompilerServices . CallConvCdecl ) test_pointer_operations ( int32 param ) cil managed { . vtentry 1 : 1 // حجم الكود 44 (0x2c) . maxstack 2 . locals ([ 0 ] int32 * ptr , [ 1 ] valuetype A * V_1 , [ 2 ] valuetype A * a , [ 3 ] int32 k ) // k = 0; IL_0000 : ldc . i4 .0 IL_0001 : stloc .3 // ptr = &k; IL_0002 : ldloca . s k // تعليمة تحميل عنوان المتغير المحلي IL_0004 : stloc .0 // *ptr = 1; IL_0005 : ldloc .0 IL_0006 : ldc . i4 .1 IL_0007 : ستيند . i4 // تعليمات غير مباشرة // ptr = ¶m IL_0008 : ldarga . s param // تعليمات عنوان معلمة التحميل IL_000a : stloc .0 // *ptr = 2 IL_000b : ldloc .0 IL_000c : ldc . i4 .2 IL_000d : ستيند . i4 // أ = جديد أ؛ IL_000e : ldloca . s a IL_0010 : call valuetype A * modopt ([ mscorlib ] System . Runtime . CompilerServices . CallConvThiscall ) ' A .{ ctor } ' ( valuetype A * modopt ([ mscorlib ]نظام . وقت التشغيل . خدمات المترجم . IsConst ) modopt ([ mscorlib ] System . Runtime . CompilerServices . IsConst )) IL_0015 : pop // ptra = &a; IL_0016 : ldloca . IL_0018 : stloc .1 // ptra->meth( ) ; IL_0019 : ldloc .1 IL_001a : مزدوج IL_001b : ldind . i4 // قراءة VMT للمكالمة الافتراضية IL_001c : ldind . i4 IL_001d : calli unmanaged stdcall void modopt ([ mscorlib ] System . Runtime . CompilerServices . CallConvStdcall )( native int ) IL_0022 : ret } // نهاية الدالة 'Global Functions'::test_pointer_operationsانظر أيضاً
مراجع
- ↑ "ما هو "الرمز المُدار"؟" . مايكروسوفت. 19 أبريل 2023.
- ↑ "ECMA-335 البنية التحتية للغة المشتركة (CLI)" .
- ↑ "ما هي لغة الوسيط (IL)/MSIL/CIL في .NET؟" . تم الاطلاع عليه بتاريخ 17 فبراير 2011.
CIL: ... عند تجميع مشروع .NET، لا يتم تحويله مباشرةً إلى رمز ثنائي، بل إلى لغة وسيطة. عند تشغيل المشروع، يتم تحويل كل لغة من لغات برمجة .NET إلى رمز ثنائي ثم إلى CIL. يتم تحويل جزء فقط من CIL المطلوب أثناء التشغيل إلى رمز ثنائي. ملفات DLL وEXE الخاصة بـ .NET تكون أيضًا بصيغة CIL.
- ↑ "أداة الاختراق: MSIL/SkypeCracker" . مايكروسوفت . تم الاطلاع عليه بتاريخ 26 نوفمبر 2019 .
- ↑ ترولسن، أندرو (2009-05-02). فوائد CIL . أبريس. ISBN 9781590598849تم الاطلاع عليه بتاريخ 17 فبراير 2011 .
- ↑ "الامتدادات غير المُدارة والمُدارة للغة C++، وإطار عمل .Net المُدار" . www.visualcplusdotnet.com . تاريخ الاسترجاع: 7 يوليو 2020 .
للمزيد من القراءة
- بوك، جيسون (2002). برمجة CIL: نظرة معمقة على .NET . دار نشر Apress. رقم ISBN 978-1590590416.
روابط خارجية
- لغات التجميع
- بايت كود
- البنية التحتية للغة المشتركة
