یکشنبه, ۵ اسفند, ۱۴۰۳ / 23 February, 2025
مجله ویستا

مفاهیم اولیه CLR


مفاهیم اولیه CLR
فریمورک دات نت یک محیط اجراء با نام CLR)Common Language Runtime) را ارائه که مسئولیت مدیریت اجرای کد و تامین سرویس های لازم بمنظور پیاده سازی نرم افزار را برعهده دارد . CLR ، زیرساخت مستحکمی را بمنظورایجاد انواع نرم افزار در اختیار پیاده کنندگان قرار می دهد . یک برنامه ASP.NET ، یک برنامه فرم های ویندوز ، یک سرویس وب ، یک برنامه مختص موبایل ، یک برنامه توزیعی و یا یک برنامه که چندین مدل از برنامه های فوق را با یکدیگر ترکیب می نماید ، نمونه هائی از برنامه هائی می باشند که می توان آنها را بر اساس زیرساخت ارائه شده ، پیاده سازی نمود. CLR ، دارای مزایای متعددی بمنظور پیاده سازی سریع و آسان نرم افزار با قابلیت مهم ارتباط و یکپارچگی بین کدهای نوشته توسط زبانهای متفاوت برنامه نویسی است .
CLR ، ابزاری ( Engine) است که دستورالعمل های IL)Intermediate Language) را بعنوان ورودی اخذ و در ادامه آنها را به دستورالعمل های زبان ماشین ترجمه و در نهایت آنان را اجراء می نماید. موضوع فوق ، بدین معنی نیست که CLR ، دستورالعمل ها را تفسیر می نماید. عبارت فوق ، بدین دلیل بیان شده است که بنوعی به این موضوع اشاره گردد که CLR ، محیط لازم بمنظور اجرای کد IL را فراهم می نماید. بمنظور نیل به اهداف مورد نظر خصوصا" : کارآمدی کدها و قابلیت حمل آنان ، هسته اجرائی می بایست، شرایط ومحیط لازم بمنظور ایجاد کد با لحاظ نمودن اهداف موردنظر ( کارآمد ، قابلیت حمل) را ارائه نماید. کارآمدی کدها ، یکی از مسائل کلیدی در رابطه با محیط اجراء خواهد بود. اگر کد، با سرعت قابل قبول اجراء نگردد ، تمام ویژگی های دیگر موجود در سیستم ، تحت الشعاع قرار خواهند گرفت .
قابلیت حمل ، امکان استفاده از نرم افزار را مستقل از نوع پردازنده و دستگاه فراهم می نماید. بنابراین افزایش تعداد پردازنده ها و دستگاههائی که CLR می تواند بر روی آنها اجراء گردد، همواره دارای اهمیت خاص خود خواهد بود. مکروسافت و اینتل برای مدت زمان زیادی ، دارای همکاری مناسبی در عرصه تجارت بودند. مکروسافت کم و بیش از خط پردازنده های اینتل بمنظور اجراء نرم افزارهای خود ، استفاده می کرد.بدین ترتیب ، مکروسافت ، بدون وجود نگرانی ( حمایت از معماری چندین پردازنده ای و دستورالعمل های مربوطه ) ، اقدام به ایجاد و پیاد ه سازی نرم افزار می نمود. شرکت مکروسافت هرگز نگران ارائه یک نسخه خاص از محصولات خود برای یک نسخه خاص از پردازنده های Motoral ۶۸XXX ، نبود ، چرکه اصولا" آنها را حمایت نمی کرد . بروز محدودیت در حمایت از پردازنده ها در زمان انتقال از برنامه ها یمبتنی بر Win۱۶ به Win۳۲، بعنوان یک مسئله مهم ،مطرح گردید. ( ما عملا" دارای API با نام Win۱۶ نبوده ایم ، ولی می توان این واژه را برای API قبل از Win۳۲ استفاده کرد) . مکروسافت اگر می خواهد همچنان بعنوان یکی از شرکت های فعال در زمینه تولید و طراحی نرم افزار در سطح جهان مطرح باشد ، می بایست تدابیر لازم در خصوص قابلیت حمل نرم افزارهای پیاده سازی شده خود را بر روی محیط های متفاوت فراهم نماید. باتوجه به تغییرات بنیادین و مهم در طراحی و پیاده سازی برنامه های مبتنی بر وب طی سالیان اخیر و ضرورت استفاده از دستگاههای متعدد بمنظور ارتباط به اینترنت و در نهایت استفاده از خدمات برنامه های موجود ، ما با واقعیت بزرگ دیگری نیز مواجه هستیم و آن اینکه هر یک از دستگاههای موجود ( تلفن های موبایل ، کامپیوترهای hand-held ، tablet ، ) دارای معماری و پردازنده اختصاصی خود می باشند. با توجه به وضعیت موجود، می بایست تمهیدات و تدابیر خاصی در رابطه با طراحی و پیاده سازی اندیشیده گردد که ماحصل آن قابلیت حمل نرم افزار از یک معماری خاص به معماری دیگر باشد .
مکروسافت نیز در صدد حضوری فعال تر و ارائه نرم افزار در رابطه با دستگاه های فوق ، است ، بدیهی است می بایست اقدامی صورت می گرفت که پاسخگوی واقعیت های جدید صنعت نرم افزارباشد . مکروسافت در پاسخ به محدودیت های موجود، خواسته های جدید و حل مشکل قابلیت حمل به سایر پردازنده ها ، تصمیم به ایجاد یک محیط اجراء و یا CLR نمود ه است .
در ادامه این مقاله ، قصد داریم بدون درگیر شدن به جزیئات مربوطه ، به بررسی محیط اجراء پرداخته امکانات آن را در رابطه با اجرای برنامه های managed ، بررسی نمائیم .
● مروری بر Runtime
قبل از دات نت، یک برنامه اجرائی معمولا" بصورت یک فایل با انشعاب exe. ارائه می گردید ( برنامه صرفا" شامل یک فایل بود) . بمنظور اجراء کارآمد تمامی سیستم ، برنامه می بایست از کدهائی استفاده نماید که بصورت اشترکی باشند ( معمولا" یک فایل با انشعاب dll. ) اگر در زمان استفاده از کد مشترک ، مسائلی ایجاد می گردید، می توان از یک کتابخانه وارداتی استفاده و یا یک DLL را در زمان اجراء ، load کرد ( با استفاده از LoadLibrary,LoadLibraryEx و GetProcAddress )
در دات نت ، واحد اجراء و بکارگیری ، اسمبلی (Assembly ) است . فرآیند اجراء، همواره با یک اسمبلی که دارای انشعاب exe . می باشد ، آغاز می گردد . برنامه می تواند از کد اشترکی بکمک Importing اسمبلی که شامل کد مشترک بهمراه یک مرجع صریح است ، استفاده نماید ( برای اضافه نمودن مرجع ، می توان از AddReference در ویژوال استودیو دات نت استفاده کرد ) برنامه ها همچنین می توانند با استفاده از Assembly.Load و یا Assembly.loadForm ، اقدام به استقرار یک اسمبلی در حافظه نمایند .
در ادامه ، لازم است با برخی از اصطلاحات آشنا و تعریف مناسبی از آنها را ارائه نمائیم .
▪ اسمبلی(Assembly ) . اسمبلی واحد اولیه بکارگیری نرم افزار در فریمورک دات نت است .یک اسمبلی می تواند شامل مراجعی به سایر اسمبلی ها و ماژول ها باشد .
▪ ماژول( Module ) . ماژول، فایلی شامل محتویات اجرائی است . یک اسمبلی می تواند یک و یا بیش از یک ماژول را کپسوله نماید. یک ماژول بدون اینکه یک اسمبلی به آن مراجعه ای داشته باشد ، Stand alone نمی گردد . کلاسی در کنابخانه کلاس پایه ( System) ، مسئولیت کپسوله نمودن کثر ویژگی های یک " ماژول " را برعهده دارد ( مشابه اسمبلی ). این کلاس Module ، نام دارد.
▪ APPDomain ، بعنوان یک پردازه کم حجم ( سبک ) در نظر گرفته می شود.قبل از دات نت ، ایزولاسیون از طریق جداسازی پردازش ها از یکدیگر و بکمک سیستم عامل انجام می گردید. اگر پردازه ای ، عملیات نامشحص و تعریف نشده ای را انجام که باعث بروز مشکل برای ادامه حیات خود می گردید ، حرکت وی باعث بروز اختلال در تمام سیستم نشده و صرفا" مشکل بوجود آمده در ارتباط با پردازه خواهد بود . با توجه به اینکه "نوع ها" ،بصورت کاملا" هدایت شده توسط فریمورک دات نت کنترل می گردند ، می توان از روش هائی بمنظورپیاده سازی سطح مشابهی ایزولاسیون در ارتباط با یک پردازه استفاده کرد . این روش Application Domain ویا AppDomain نامیده می شود. همانند اسمبلی و ماژول ، یک کلاس در کتابخانه کلاس فریمورک دات نت ، کثر ویژگی ها و پتانسیل های مربوط به یک Application Domain را کپسوله می نماید. کلاس فوق ، AppDomain نامیده شده و در namespace با نام System قرار دارد .
▪ IL یا MSIL . واژه IL از Intermediate Language و MSIL از Microsoft Intermediate Language ، اقتباس شده اند . IL ، زبانی است که اسمبلی ها توسط آن نوشته شده و شامل مجموعه ای از دستورالعمل هائی است که کد مربوط به برنامه را ارائه می نمایند. به زبان فوق بدین دلیل بدین دلیل " میانی " ( Intermediate ) ، اطلاق می گردد ، چون هنوز بصورت native code درنیامده است . در زمان مورد نطر ، کدهای IL توسط کمپایلر JIT به native code ، ترجمه خواهند شد .
▪ JIT . واژه JIT از کلمات Just-In-Time اقتباس شده است . از کمپایلر فوق ، بمنظور ترجمه کدهای IL به native code استفاده می شود.
پس ازاستقرار کد در حافظه ( Loading ) ، امکان اجرای آنان فراهم می گردد . از این مرحله به بعد ( آغاز عملیات اجراء کد ) ، تفاوت محسوسی را بین برنامه های قدیمی ( قبل از دات نت ) و برنامه های جدید ( دات نت ) ، شاهد خواهیم بود . در حالت کد غیرمدیریت یافته ( Unmanaged) ، کمپایلر و linker بر روی کدهای مربوطه عملیات خود را آغاز و آنها را به native code تبدیل می نمایند . بدین ترتیب ،دستورالعمل ها می توانند بلافاصله اجراء گردند. لازم است به این نکته مهم اشاره گردد که در صورتیکه قصد استفاده از برنامه نوشته شده بر روی محیط های متفاوت ( سایر پلات فرم ها ) وجود داشته باشد ، می بایست برای هر یک نسخه ای جداگانه را کمپایل کرد. در برخی حالات ، امکان ایجاد و ترجمه نسخه های متعدد بمنظور اجراء بر روی محیط های متفاوت ، امری مطلوب بنظر نمی رسد ، در چنین مواردی سعی می گردد ، صرفا" یک نسخه ارائه گردد. نسخه فوق ، بگونه ای طراحی و پیاده سازی می گردد که بتواند با محیط های متفاوت سازگار باشد . بدین ترتیب ، امکان اجراء نرم افزارهای تولیدی در محیط های متفاوت ، فراهم خواهد شد . وجود پتانسیل در بطن یک دستگاه سخت افزاری یک موضوع است و ارائه برنامه ای که زمینه بهره برداری از پتانسیل های مربوطه را فراهم و برنامه ای که از پتانسیل های دستگاه فوق ، در نهایت استفاده می نماید ، موضوعات دیگری است . مثلا" امروز ما کمتر شاهد ارائه نرم افزار از طرف شرکت های تولید کننده ای می باشیم که تکید و اصرار بر استفاده از یک محیط سخت افزاری نظیر وجود یک " شتاب دهنده گرافیک " ، داشته باشند . در چنین موارد علاوه بر اینکه تولید کننده " شتاب دهنده گرافیک " ، می بایست برای هر " کارت شتاب دهنده گرافیک " ، برنامه ای خاص را ارائه نماید ، بلکه همچنین پیاده کنندگان می بایست از برناهه های مجزائی برای هر یک از کارت ها ی عرضه شده ، استفاده نمایند . " شتاب دهنده گرافیک " ، صرفا" یک نمونه در این رابطه بوده و می توان به مواردی دیگر نظیر : disk cache,memory cache ، شبکه های با سرعت بالا ، سیستم های مبتنی بر چندین پردازنده و سخت افزارهای خاص بمنظور پردازش تصاویر، اشاره کرد .
یکی از اولین مراحلی که CLR در ارتباط با اجراء یک برنامه انجام می دهد ، بررسی متدی است که می بایست اجراء گردد ( آیا به native code ،تبدیل شده است ؟) . در صورتیکه متد به native code ، تبدیل نشده باشد ، کد موجود در متد بصورت JITd) Just - In - time compild) خواهد بود . تاخیر در ترجمه یک متد ، دارای دو مزیت است :
▪ یک شرکت می تواند نسخه ای از نرم افزار تولید ی خود را براحتی بر روی محیط مورد نظر خود منتقل ( در محیط فوق نسخه ای از CLR نصب شده است ) و از CLR بمنظور مدیریت و سفارشی نمودن کدها، متناسب با محیط سخت افزاری مربوطه ، استفاده نماید .
▪ کمپایلرهای JIT قادر به استفاده از مزایای بهینه سازی می باشند . بدین ترتیب ، امکان اجراء سریعتر یک برنامه نسبت به یک برنامه همه منظور( نسخه unmanaged برنامه ) ، فراهم می گردد . سیستم هائی که دارای پردازنده های ۶۴ بیتی می باشند ، دارای یک مد " سازگاری " خواهند بود که به برنامه های سی و دو بیتی اجازه می دهد بدون اعمال تغییرات بر روی یک پردازنده ۶۴ بیتی اجراء گردند .اگر برنامه ای به IL ترجمه گردد ، می تواند از مزایای پردازش ۶۴ بیتی بهره مند گردد (موتور JIT ، قادر به target نمودن پردازنده جدید ۶۴ بیتی است) .
فرآیند استقرار یک متد در حافطه ( Loading ) و ترجمه آن ، در صورت نیاز تکرار تا زمانیکه تمام متدها ی موجود در برنامه ترجمه و یا برنامه متوقف گردد .
● شروع یک متد
CLR ، درارتباط با هر متد به اطلاعات زیر نیاز خواهد داشت . تمامی اطلاعات مورد نیاز CLR از طریق متادیتا ( Metadate) موجود در هر اسمبلی در دسترس و ارائه خواهد شد .
▪ دستورالعمل ها . CLR ، نیازمند لیستی از دستورالعمل های MSIL است . هر متد دارای اشاره گری به مجموعه دستوراتی است که بعنوان بخشی از متا دیتا ی مورد نظری است که به آن مرتبط شده است.
▪ Signature . هر متد دارای یک Signature است و CLR نیازمند استفاده از یک signature برای هر متد است . signature ، برگرداندن نوع ، تعداد پارامتر و نوع پارامترها را تشریح می نماید.
▪ Exception Handling Array . دستورالعمل خاصی از IL که مربوط به برخورد با exception باشد ، وجود ندارد . در این رابطه از دایرکتیوهائی خاص در مقابل دستورالعمل های IL ، استفاده می گردد . در مقابل دستورالمل های Exception-handling ، اسمبلی دارای لیستی از exceptions است . لیست فوق، شامل نوع exception ، یک آدرس offest به اولین دستورالعمل پس از بلک exception try ، طول مربوط به بلک try ، است . لیست فوق ، همچنین شامل آفست به handler code ، طول handler code ، و یک token که مسئول تشریح کلاسی است که از آن بمنظور کپسوله نمودن exception استفاده می گردد .
▪ اندازه Evaulation stack . داده فوق ، از طریق متا دیتا اسمبلی قابل دسترس خواهد بود. می توان آن را از طریق maxstack x در لیست ILDASM مشاهده نمود. مقدار x ، اندازه پشته مورد نظر است . اندازه منطقی پشته که توسط x ، مشخص شده است ، حدکثر آیتم هائی را که می توان در پشته ، مستقر ( Push ) نمود ، مشخص می نماید. اندازه فیزیکی آیتم ها و پشته به CLR واگذار تا در زمان اجراء آن را مشخص نماید (زمانیکه متد JITd است ) .
▪ تشریح بردارهای محلی . هر متد نیازمند تعریف و ذخیره سازی محلی آیتم های مورد نیاز است. evaluation stack ،( برداری منطقی از آیتم ها بهمراه نوع هر آیتم) و استفاده از یک flag در متادیتا بمنظور مشخص نمودن ضرورت مقداردهی اولیه ( مقدارصفر ) متغیرهای محلی در ابتدای فراخوانی یک متد ، نمونه هائی در این زمینه می باشند.
با استفاده از اطلاعات فوق ، CLR ، قادر به ایجاد یک abstraction از چیزی خواهد بود که native stack frame است. عموما" هر پردازنده و یا ماشین یک stack frame را شکل که شامل آرگومانها ( پارامترها ) و یا مرجع به آرگومانها ی مربوط به متد است . در وضعیتی مشابه ، متغیرهای برگردانده شده در stack frame بر اساس فراخوانی که وابسته به یک پردازنده و یا ماشین خاص است ، ذخیره می گردند. اولویت پارامترهای ورودی و خروجی در رابطه با یک ماشین خاص ، مشخص می گردد . با توجه به اینکه تمام اطلاعات مورد نیاز برای هر متد در دسترس است ، CLR ، قادر به تشخیص وضعیت مورد نظر stack frame ، در زمان اجراء است .
فراخوانی یک متد بگونه ای انجام خواهد شد که CLR دارای حداقل کنترل در رابطه با اجراء متد و حالت آن باشد .زمانیکه CLR ، یک متد را فرامی خواند ، متد و حالت آن تحت کنترل CLR خواهد بود ( Thread of control ) .
دربخش دوم این مقاله به بررسی نوع ها ی حمایت شده توسط IL ، خواهیم پرداخت .
● نوع ها ی حمایت شده در IL
مجموعه ای از نوع ها ی متفاوت در سطح IL ارائه شده است . نوع های فوق را می توان مستقیما" و از طریق دستورالعمل های IL استفاده نمود .برخی از نوع های حمایت شده در IL عبارتند از :
• int۸ : هشت بیتی علامت دار ( متمم دو )
• Unsigned int۸ : هشت بیتی بدون علامت
▪ int۱۶ : شانزده بیتی علامت دار
▪ Unsigned int۱۶ : شانزده بیتی بدون علامت
▪ int۳۲ : سی و دو بیتی علامت دار
▪ Unsigned int۳۲ : سی و دو بیتی بدون علامت
▪ int۶۴ : شصت و چهار بیتی علامت دار
▪ Unsigned : شصت و چهار بیتی بدون علامت
▪ float۳۲ : سی و دو بیتی اعشاری
▪ float۶۴ : شصت و چهار بیتی اعشاری
▪ native int : نوع فوق ، دارای اندازه Native بوده و اعداد علامت دار متمم دو را در خود نگهداری می نماید.
▪ native unsigned int : نوع فوق ، دارای اندازه Native بوده و مقادیر بدون علامت باینری را در خود نگهداری می نماید .
▪ F : متغیر اعشاری Native size . این متغیر برای CLR داخلی بوده و برای کاربر مشهود نیست .
▪ O . یک شی با اندازه native بمنظور اشاره به حافظه مدیریت یافته (اداره شده ).
▪ & . اشاره گر مدیریت یافته( اداره شده ) با اندازه native
نوع های فوق ، قابل ارائه در حافظه بوده ولی در ارتباط با پردازش آنان ، برخی محدودیت ها وجود دارد . CLR ، پردازش های لازم در ارتباط با نوع های فوق را از طریق یک پشته ارزیابی ( evaluation stack) که بعنوان بخشی از حالت داده در رابطه با هر متد می باشد ، انجام می دهد . پشته فوق ، قادر به ارائه یک آیتم با هر اندازه ای می باشد. تنها عملیات مجاز در این رابطه ، تکثیر آنان به حافظه ( و یا از حافظه ) و محاسبه آدرس نوع های تعریف شده توسط کاربر است . تمامی عملیاتی که شامل مقادیر اعشاری می باشند از یک نمایش داخلی برای ارائه اعداد اعشاری استفاده که به سبک خاصی پیاده سازی شده است ( یک مقدار F ) .
سایر نوع های داده ، بجزء مقایر اعشاری که به آنان اشاره گردید ، دارای یک اندازه native می باشند : native int ، native unsigned int ، مرجع شی ( O ) و اشاره گر مدیریت یافته ( &) . نوع های داده فوق ، مکانیزمی برای CLR بمنظور تاخیر در انتخاب اندازه نوع مورد نظر می باشد . مثلا" ، مکانیزم فوق ، این امکان را فراهم می آورد که یک native int بر روی یک ماشین شصت و چهار بیتی ، ۶۴ بیت و در یک ماشین سی و دو بیتی ، ۳۲ بیت در نظر گرفته شود.
دو نوع از داده های فوق( native ) ، بنظر مشابه یکدیگر می باشند . نوع O ( با اندازه native و اشاره به شی ) و نوع & ( با اندازه native اشاره گر مدیریت یافته ) . یک متغیر از نوع O ، به یک شی مدیریت یافته ، اشاره و استفاده از آن محدود به دستورالعمل هائی است که با صراحت یک عملیات بر روی یک شی مدیریت یافته را انجام و یا دستورالعمل هائی که متایتا آنان امکان اشاره به یک شی مدیریت یافته را اجازه داده باشد، . نوع O ، به خارج از شی و یا تمام شی اشاره می نماید . نوع & ، نیزبه یک شی مدیریت یافته ، اشاره نموده با این محدودیت که صرفا" به یک فیلد شی و یا عنصری از بردار ، اشاره خواهد کرد . نوع های O و & ، توسط CLR ردیابی شده و می توانند با توجه به نتایج جمع آوری اطلاعات زائد ( garbage collection) ، تغییر نمایند .
یکی از موارد خاص استفاده از نوع های native ، اشاره گرهای غیر مدیریت یافته است . با اینکه نوع اشاره گره های غیرمدیریت یافته را می توان توسط متادیتا ، مشخص نمود ولی آنان بعنوان native unsigned int در کد IL نشان داده می شوند . بدین ترتیب ، CLR دارای انعطاف لازم بمنظور نسبت دهی یک اشاره گر غیرمدیریت یافته به یک فضای آدرس دهی بزرگ و بر روی پردازنده ای است که آن را حمایت ولی الزامی دررابطه با درگیر شدن حافظه بمنظور ذخیره سازی مقادیر فوق بر روی پردازنده هائی که دارای قابلییت آدرس دهی چنین فضای آدرس دهی بزرگی نمی باشند ، وجود نخواهد داشت .
برخی از دستورالعمل های IL نیازمند وجود یک آدرس در پشته می باشند ، دستورالعمل های زیر : calli ، cpblk ، initblk نمونه هائی در این زمینه می باشند. استفاده از یک نوع native ، قابلیت حمل مناسبی در ارتباط با عملیاتی که شامل نوع فوق می باشند را فراهم و تضمین می نماید . در صورتیکه آدرس مشخص شده ، یک عدد ۶۴ بیتی صحیح را مشخص نماید ، در ادامه ،قابلیت حمل آن در صورت دنبال نمودن مراحل موردنظر بمنظور اطمینان از تبدیل مقدار به یک آدرس فراهم می گردد .در صورتیکه یک آدرس بعنوان یک عدد سی و دو بیتی و یا کوچکتر مشخص گردد ، کد هرگز قابل حمل نخواهد بود، ولواینکه ممکن است بر روی کثر ماشین های سی و دو بیتی امکان اجرای آن وجود داشته باشد. در کثر موارد ، رویکرد فوق ، ماحصل نتایج تولید کننده IL و یا کمپایلر بوده و نمی بایست نسبت به این موضوع نگران گردید . در این رابطه لازم است به این نکته توجه شود که با استفاده غیر صحیح از دستورالعمل ها ، ممکن است قابلیت حمل کد ، حذف و عملا" امکان چنین پتانسیل ارزشمندی از یک برنامه و یا بخشی از برنامه نوشته شده ، سلب گردد .
مقادیر عددی کوچک ( آنانی که که کمتر از چها ر بایت می باشند ) ، در زمان لود ( زمانیکه از حافظه در پشته قرار می گیرند ) به چهار بایت تبدیل و در زمان ذخیره سازی محدودتر خواهند شد ( کپی از پشته به حافظه ) . هر نوع عملیاتی که شامل یک مقدار عددی کوچک باشد ، بعنوان یک عملیات چهار بایتی در نظر گرفته شده و با آن برخورد خواهد شد . دستورالعمل های خاص IL که با نوع های عددی کوچک سروکار دارند عبارتند از :
▪ عملیات لود و ذخیره سازی به / از حافظه : ldelem, ldind, stind و stelem
▪ تبدیل داده : conv ,conv.ovf
▪ ایجاد آرایه ( بردار ) : newarr
بعبارت دیگر ، IL صرفا" عملیات علامت دار را حمایت می نماید . تفاوت بین عملیات علامت دار و بدون علامت ، به نحوه تفسیر مقدار برمی گردد. برای عملیاتی که نحوه تفسیر مقدار مورد نظر حائز اهمیت است ، عملیات انجام شده ، دارای یک نسخه بدون علامت ویک نسخه علامت دار می باشد .
● منزلگاه مقادیر
بمنظور ردیابی اشیاء ، CLR مفهوم جدیدی با نام محدوده ( منزلگاه ) یک شی را معرفی نموده است . . منزلگاه شی ، محلی است که مقدار شی ذخیره و می بایست دارای مکانیزمی بمنظور مشخص نمودن نوع شی توسط کمپایلر JIT ، باشد . زمانیکه یک شی بصورت Reference ( ارسال اشاره گری به شی ) ، پاس داده میشود ، شی فوق ، می بایست دارای یک منزلگاه باشد، چرکه آدرس منزلگاه بعنوان مرجع ارسال می گردد . در این رابطه دو نوع داده وجود داشته که بی خانمان ! ( بدون منزلگاه ) بوده و نمی توان آنان را بصورت Reference ارسال نمود : مقادیر ثابت و میانی در پشته ارزیابی از دستورالعمل های IL و یا مقادیر برگردانده شده توسط متدها . CLR منزلگاه های زیر را در ارتباط با اشیاء حمایت می نماید :
▪ آرگومان incoming . دستورالعمل های ldarg و ldarga ، آدرس یک آرگومان منزلگاه را مشخص می نمایند. signature متد، نوع مربوطه را مشخص خواهد نمود.
▪ متغیرهای محلی . دستورالعمل های ldloca و یا idloc ، آدرس یک متغیر محلی را مشخص می نمایند. پشته ارزیابی محلی ، نوع متغیرهای محلی را بعنوان بخشی از متادیتا مشخص خواهد نمود.
▪ فیلد ( نمونه و یا ایستا ) . استفاده از ldflda برای نمونه ای از فیلد و ldsflda برای یک فیلد ایستا ، آدرس فیلد مورد نظر رامشخص می نماید . متا دیتا ئی که با اینترفیس کلاس و یا ماژول مرتبط است ، نوع فیلد را مشخص خواهد نمود.
▪ عنصر آرایه . استفاده از ldelema ، آدرس یک عنصر بردار را مشخص می نماید. نوع المان بردار، نوع المان را مشخص خواهد نمود.
● Method Flow Control
CLR ، مجموعه گسترده ای از دستورالعمل های کنترلی را ارائه می نماید :
▪ پرش شرطی و غیر شرطی . کنترل می تواند در هر محلی از یک متد انتقال یابد، مشروط به اینکه انتقال فوق ، با کرانه های یک محدوده حفاظت شده ، تلاقی ننماید. یک محدوده حفاظت شده ، در متادیتا تعریف وناحیه ای است که با یک exception handler مرتبط شده است . در سی شارپ ناحیه فوق ، یک try block نامیده شده و با یک catch block که بعنوان یک handler می باشد ، مرتبط می گردد . CLR ، قابلیت اجرای انواع متفاوتی از exception handler ها را دارا بوده که در بخش بعدی این مقاله در رابطه با آنان توضیح داده خواهد شد . نکته مهمی که لازم است به آن اشاره گردد ،عدم امکان پرش شرطی و یا غیر شرطی به مقصدی است که با محدوده یک execption تلاقی می نماید .
▪ فراخوانی متد. دستورالعمل های متفاوتی امکان فراخوانی متدها توسط متدهای دیگر را فراهم می نماید.
▪ فراخوانی دنباله . نوع خاصی پیشوند است که بلافاصله مقدمات فراخوانی یک متد را فراهم و به متد فراخوانده شده اعلام می نماید که فریم پشته را قبل از فراخوانی متد مورد نظر نادیده و رها نماید . بدین ترتیب ، متد فراخوانده شده به نقطه ای مراجعت می نماید که متد صدازننده می بایست مراجعه نماید .
▪ مراجعت . نوع ساده ای بمنظور مراجعت از یک متد است .
▪ پرش متد . نوع بهینه شده ای از فراخوانی "دنباله " بوده که آرگومانها و کنترل یک متد را به متد دیگر منتقل می نماید ( با signature مشابه )
▪ Exception . شامل مجموعه ای از دستورالعمل ی لازم بمنظور ایجاد یک execption بوده که کنترل را به خارج از یک ناحیه حفاظت شده منتقل می نماید.
CLR ، در مواردیکه کنترل درون یک متد منتقل می گردد ، از مجموعه ای قوانین استفاده می نماید .
▪ کنترل نمی تواند درون یک Exception handler منتقل گردد ( بجز درمواردیکه بعنوان نتیجه یک Exception باشد ) . قانون فوق ، نشاندهنده این واقعیت است که مقصد یک پرش نمی تواند با یک ناحیه حفاظت شده تلاقی نماید .
▪ پس از استقرار در یک handler مرتبط با یک ناحیه حفاظت شده ، امکان انتقال به خارج از handler صرفا" از طریق مجموعه ای محدود از دستورالعمل های exception ( نظیر : Leave, end.finally ,end.filter و end.catch ) وجود خواهد داشت .
▪ هر اسلات در پشته ارزیابی ، می بایست نگهداری نوع مربوط به خود را در مدت زمان عمر مفید پشته ارزیابی ( طبیعتا" عمر مفید متد ) ، انجام دهد . بعبارت دیگر ، نمی توان نوع یک اسلات ( متغیر) در پشته ارزیابی را تغییر داد . موضوع فوق ، مسئله ای خاص را بدنبال نخواهد داشت ، چرکه پشته ارزیابی برای کاربران در دسترس نخواهد بود .
▪ این امکان وجود نخواهد داشت که کنترل بسادگی به حیات خود خاتمه دهد . در این رابطه لازم است ، تمامی مسیرهای اجراء متوقف گردند . ( استفاده از دستورالعمل های ret ، Jmp,throw و یا * . tail )
فراخوانی متد
CLR ، قادر به فراخوانی متدها با استفاده از سه روش متفاوت است . تفاوت هر یک از روش های فوق صرفا" به روشی که call site descriptor مشخص می نماید ، بستگی دارد.call site descriptor ، به CLR و موتور JIT اطلاعات کافی در رابطه با فراخوانی متد را ارائه می نماید. بنابراین، امکان ایجاد یک فراخوانی native فراهم ، آرگومان های مناسب امکان دستیابی به متد را ایجاد و اطلاعات مورد نیاز بمنظور مراجعت ایجاد می گردد.
▪ دستورالعمل calli ، ساده ترین نوع فراخوانی متد می باشد . دستورالعمل فوق، زمانیکه آدرس مقصد در زمان اجراء محاسبه می گردد ، استفاده می شود.
▪ دستورالعمل call ، در مواردیکه آدرس تابع در زمان کمپایل شناخته شده باشد ، استفاده می گردد .
▪ دستورالعمل callvirt ، متدی در رابطه با نمونه ای خاص از یک شی را فرامی خواند .
● روش فراخوانی متد
CLR از یک روش خاص بمنظور فراخوانی در تمامی کد IL استفاده می نماید. اگر متدی که صدا زده شده است ، متدی مربوط به یک نمونه باشد ، یک مرجع به نمونه شی مورد نظر بهمراه هر یک از آرگومانهای متد با اولویت چپ به راست در پشته مستقر می گردند . بدین ترتیب ، اشاره گرفوق ، در ابتدا توسط متد فراخوانده شده از پشته برداشته شده ( pop ) و در ادامه نوبت به هر یک از آرگومان ها خواهد رسید ( شروع با آرگومان صفر تا آرگومان شماره n ) . اگر متد فراخوانده شده یک متد ایستا باشد ، اشاره گر مرتبط با نمونه شی مربوطه وجود نداشته و پشته صرفا" شامل آرگومانها خواهد بود . برای دستورالعمل calli ، آرگومانها با اولویت چپ به راست و بدنبال آن اشاره گر تابع درون پشته مستقر می گردند .
● ارسال پارامتر متدها
CLR، از سه روش متفاوت برای ارسال پارامتر ( parameter-passing ) استفاده می نماید :
▪ By value . در این روش ، مقدار شی درون پشته قرار خواهد گرفت . برای نوع های از قبل ایجاد شده ، نظیر inreger و float ، بسادگی مقدار مورد نظر درون پشته مستقر می گردد . برای اشیاء ، یک نوع مرجع O مرتبط با شی ، درون پشته قرار خواهد گرفت . برای اشاره گرهای مدیریت یافته و غیر مدیریت یافته ، آدرس در پشته مستقر خواهد شد. برای نوع های تعریف شده توسط کاربر ، می توان یک مقدار را در پشته ارزیابی مستقر تا زمینه فراخوانی یک متد رابه دو صورت فراهم نماید : روش اول : می توان با استفاده از دستورالعمل های ldarg , ldloc , ldfld و یا ldsfld مقدار مورد نظررا مستقیما" در پشته قرار داد، . روش دوم : آدرس مقدار مورد نظر محاسبه و مقدار مربوطه را می توان با استفاده از دستورالعمل ldobj در پشته مستقر نمود.
▪ By Reference . با استفاده از روش فوق ، آدرس پارامتر در مقابل مقدار مورد نظر به متد ارسال می گردد.بدین ترتیب ،یک متد قادر به تغییر پارامتر در صورت لزوم می باشد . در این رابطه صرفا" مقادیری که دارای منزلگاه می باشند را می توان با استفاده از روش فوق ، ارسال نمود( عملا" آدرس منرلگاه ارسال می گردد ) . بمنظور بررسی امنیت نوع ها ، می بایست از دستورالعمل های * . ldind و* . stind ( به ترتیب ) برای ارسال و مراجعه به پارامترها ، استفاده گردد.
▪ Type reference . روش فوق ، مشابه یک پارامتر Reference نرمال بوده که بهمراه آن یک نوع داده ایستا بهمراه مرجع داده ارسال می گردد .
● زمان اجرای زبان مشترک
CLR اجرای کد .NET را کنترل می‌کند. CLR گامی بالاتر از COM ، MTS و COM+ است و درطی زمان به عنوان لایه زمان اجرای ویژوال بیسیک جایگزین آنها می‌شود.
برای برنامه‌نویسان، مفهوم این مسئله این است که کد VB.NET ما هر متد از زبان‌های دیگر اجرا خواهد شد، درحالی که اندازة فایل را یکسان و کوچک نگه می‌دارد.
CLR محیط زمان اجرایی برای .NET است و اجرای کد را همانند سرویس‌های فراهم شده .NET مدیریت می‌کند. CLR می‌داند که از طریق داده‌های خاصی که در برنانه‌ها وجود دارند، چه کاری انجام دهد. داده‌های خاص در برنامه‌ها ، نقشه مکانی را برای یافتن کلاس‌ها، زمان بار کردن کلاس‌ها و زمان تنظیم کران‌های زمینه زمان اجرا تولید کد طبیعی، تقویت امنیت، تعیین کلاس‌های مورد استفاده متدها ، و بارکردن کلاس‌ها در صورت نیاز ذخیره می‌کنند. باتوجه به اینکه CLR از این اطلاعات آگاه است، می‌تواند زمان استفاده یک شیء و زمان آزادسازی آن را تعیین می‌کند. این مسئله تحت عنوان کد مدیریت شده شناخته می‌شود.
حذف تمام این زائده‌ها نیز باعث فراهم شدن یک مدل برنامه‌نویسی مستحکم‌تر می‌گردد. باتوجه به این که CLR تمام عملکردهایی را به همراه دارد که درکد مدیریت نشده داشتیم، نباید متکی به فایل‌های DLL از قبل موجود باشیم که روی درایو سخت قرار دارند. این مسأله بدان معنی نیست که آخرین DLLها را دیده‌ایم، بلکه به این معنی است که چارچوب کاری .NET حاوی سیستمی درخود است که می‌تواند محل منابع مورد استفاده ما را نگاشت کند. ما دیگر وابسته به فایل‌های زمان اجرای VB نیستیم که نصب شده‌اند یا وابسته به اجزاء ازقبل موجود خاص نیستیم.
به دلیل این که مکمل CLR نیز کد مکمل مشخصه زبان مشترک (CLS) است، به کد مبتنی بر CLR اجازه اجرای صحیح را می‌دهد. CLS زیرمجموعه‌ای از انواع CLR تعریف شده در سیستم نوع مشترک (CTS) می‌باشد. ویژگی‌های CLS در فرآیند چند محیطی مفید است، زیرا آن‌ها حاوی انواع اصلی موردنیاز برای قابلیت CLR می‌باشند. این ویژگی‌های مرکب به .NET اجازه می‌دهند تا چندین زبان برنامه‌نویسی را مدیریت کند. CLR نگاشت را مدیریت می‌کند، تمام آنچه که شما نیاز دارید کامپایلری است که بتواند کد و داده خاص موردنیاز برنامه را برای عمل کردن CLR تولید کند. این امر اطمینان می‌دهد که هر وابستگی به برنامه شما ممکن است همیشه برآورده شود.
هنگامی که کامپایلر خود را برای تولید کد .NET تنظیم می‌کنید، از طریق CTS اجرا می‌شود و داده مناسب را در برنامه برای خواندن توسط CLR اضافه می‌کند، هنگامی که CLR داده را می‌یابد، از طریق آن به اجرا ادامه می‌دهد و هر چیزی را که نیاز دارد، در حافه می‌چیند، هر شیئی را در هنگام فراخوانی می‌کند (و نه از قبل). هر محاوره با برنامه، از قبیل ارسال مقادیر کلاس‌ها، نیز در داده‌های خاص نگاشت می‌شود و توسط CLR مدیریت می‌شود.
منبع : جنوبی‌ها