سلام من یک کامپایلر هستم امروز می خواهم برایتان از زندگی نامه خودم صحبت کنم. چرا من متولد شدم؟
همان طور که می دانید رایانه ها ترکیبی از نرم افزارها و سخت افزارها هستند. سخت افزار یک قطعه مکانیکی است که کارکردهای آن از طرف نرم افزارهای مناسب کنترل می شود و سخت افزار دستورالعمل ها را به شکل بار الکتریکی که معادل زبان باینری یا همان صفرویک، در برنامه نویسی رایانه است درک می کند. از این رو نوشتن کد به زبان اسمبلی برای برنامه نویسان بسیار سخت و طاقت فرسا بود و بنده یعنی کامپایلر به عنوان نرم افزار واسط متولد شدم. حالا به تعریفی از خود می پردازم.
کامپایلر چیست:
همان طور که در معرفی خودم گفتم بنده یک نرم افزار واسط هستم و دستوراتی که برنامه نویس به زبان های مختلف جاوا، سی شارپ و .... می نویسد تبدیل به کد قابل فهم برای CPU می کنم تا آن را ترجمه کند زیرا CPU نمی تواند دستورات را به شکلی که هست متوجه شود.
چه ابزارهایی با کامپایلر ارتباط نزدیک دارند؟
قبل از اینکه بگم بنده چه انواعی دارم و یا چگونه کار می کنم باید با تعدادی از مفاهیم که ارتباط نزدیکی با من دارند، آشنا شوید.
اولین مفهوم، پیش پردازنده نام دارد. کار آن تهیه کردن ورودی های من می باشد و وظایفی چون ریز پردازش، تقویت، گنجایش فایل و بسط زبان را بر عهده دارد.
مفهوم بعدی اسمبلر نام دارد. وظیفه آن ترجمه زبان اسمبلی به کد ماشین است که خروجی آن را فایل آبجکت می نامند.
مورد بعدی، لینکر نام دارد که فایل های مختلف آبجکت را با هم پیوند داده و ادغام کرده تا یک فایل اجرایی ایجاد شود. وظیفه اصلی آن جست وجو و یافتن ماژول های ارجاعی در یک برنامه و تعیین موقعیت حافظه برای بارگذاری کدها است تا دستور العمل های برنامه، ارجاع های صحیح داشته باشد. حالا به معرفی لودر که بخشی از سیستم عامل است، می پردازم که مسئولیت بارگذاری فایل های اجرایی در حافظه و اجرا کردن آن ها را برعهده دارد. لودر، رجیسترهای مختلف را برای آغاز اجرا، مقداردهی اولیه می کند.
معماری یک کامپایلر برای کامپایل کردن:
با ابزارهایی که ارتباط نزدیکی با من دارند، آشنا شدید. اکنون می خواهم درباره معماری که برای کامپایل کردن نیاز است، صحبت کنم.
روش کامپایل کردن من به طور کلی در 2 فاز تقسیم می شود:
در فاز تحلیل که به نام فرانت-اند نامیده می شود، بنده ابتدا اقدام به خواندن منبع برنامه می کنم و آن را به اجزای اصلی تقسیم می کنم؛ سپس به دنبال خطاهای واژه ای، نحوی و ساختاری می گردم و یک کد میانجی از کد منبع برای ماشین هدف تولید می کنم. این کد میانجی رابطی بین زبان سطح بالا و زبان ماشین است و به گونه ای ایجاد می شود که ترجمه آن به کد ماشین مقصد، آسان باشد. در نهایت به عنوان ورودی به فاز سنتز وارد خواهد شد. در این فاز که بک-اند هم خوانده می شود، برنامه هدف با کمک کد میانجی و جدول نمادها ایجاد می شود.
انواع کامپایلرها کدامند؟
من انواع مختلفی دارم که به بیان 3 مورد از آنها می پردازم:
-
تک فاز و چند فاز:
در این نوع بنده به محدودیت های منابع سخت افزاری وابسته هستم و به مجموعه برنامه های کوچکتر تقسیم می شوم که هر بخش از من بخشی از عمل ترجمه و آنالیز را بر عهده می گیرد. به عبارت دیگر ویژگی برخی از زبان ها به گونه ای است که در کامپایل کردن خواندن مجدد سورس کد، در آن ها ضروری است که در این موقعیت نوع چند فاز بنده با ایجاد خروجی های میانی در نهایت سورس کد را تولید می کند. اما در نوع تک فاز من، تنها در یک گذر و به طور کامل تمام سورس کد دریافتی از زبان مبدا به زبان مقصد تبدیل می شود.
-
تفسیری و کامپایلی:
زبان های سطح بالا را در دو دسته تفسیری و کامپایلی تقسیم بندی کرده اند که من و مفسرها روی آنها عمل می کنیم. برخی از زبان ها، این ویژگی را برای خود مشخص می کنند مثلا زبان C کامپایلری است و اکثر زبان های اسکریپتی که کد منبع زمان اجرا دارند، تفسیری می باشند.
-
Crossو :Native
در نوع Native یا محلی، بنده برای اجرای برنامه های باینری هستم و خروجی آنها تنها در کامپیوترهایی که با یک نوع سیستم عامل یکسان هستند قابل به کارگیری هستم ولی در نوع Cross یا عبوری، کدهای باینری در سیستم های مختلف قابل اجراست و وابستگی به سخت افزار ندارم.
زبان های کامپایلری:
خب با انواع من آشنا شدین حالا می خوام زبان هایی که توسطم کامپایل می شوند را نام ببرم که باز هم به دو دسته محلی و مجازی تقسیم می شوند. در زبان های بومی (Native) برای تبدیل کد به کد ماشین به صورت مستقیم توسط امپراطوری بنده ترجمه می شوند، البته قبل از اجرای آنها توسط سیستم عامل. مانند: C, C++, Rust, Haskell, Clean, Swift, Go, Fortran, D
اما در زبان های مجازی(Virtual) برای تبدیل کد آنها به کد ماشین توسط یک رابط میانی به زبان مشترک ترجمه
می شود. مانند: Java و خانوادهی داتنت مانند C#, Visual Basic.Net و C++/CLR
بیشتر بخوانید: الگوریتم برنامه نویسی چیست؟ یک مفهوم مهم برای هر برنامه نویس
کار کردن کامپایلر به چه صورت است؟
خب حالا وقت آن است که بگویم چگونه کار می کنم؟
تا این جا یاد گرفتیم که کامپیوتر فقط قادر به درک مفهوم سیگنال های پذیرش و عدم پذیرش و اعداد صفر و یک است و به هیچ وجه قادر به درک الفاظ و زبان ها نیست و از کاری که قرار است انجام بگیرد هم خبری ندارد و فقط از کدهای حافظه و در نهایت پردازش هایی که توسط پردازنده در واحد کنترل و ALU صورت می گیرد، اعمالی انجام می دهد.
اما شکل گیری صفر و یک ها در نتیجه یک برنامه به زبان، مورد اهمیت است و این کار توسط من یعنی کامپایلر صورت می گیرد اما مکانیسم کلی کارم به این صورت است که برنامه مبدا را خوانده و یک شکل میانی از آن ایجاد می کنم و سرانجام آن را به زبان اسمبلی تبدیل کرده و زبان اسمبلی نیز از شکل میانی برنامه شکل قابل فهم برای سیستم یعنی صفر و یک ها را ایجاد می کند و آن ها را در قالب کلمات حافظه برای سیستم و سخت افزار مهیا می کند پس تبدیل شکل ابتدایی برنامه مقصد به یک شکل اجرایی سیستمی از وظایف قدرتمند کامپایلرها می باشد. البته یک نکته هست که باید به شما بگویم اینکه ما کامپایلرها براساس قواعد گرامر زبان مبدا اقدام به تولید زبان مقصد می نماییم.
کلام آخر:
خب عزیزان به پایان زندگی نامه ای که برایتان شروع کردم رسیدیم امیدوارم لذت برده باشید اما به عنوان آخرین حرف می خواهم درباره تفاوت هایی که بین من و یک مفسر وجود دارد صحبت کنم.
یکی ازمهم ترین تفاوت بنده و مفسر، روش اجرا کردن کدهای برنامه است. وقتی یک مفسر کدی را اجرا می کند، کد در همان لحظه به صورت خط به خط اجرا و برای کامپیوتر جهت ارسال و ترجمه فرستاده می شود اما زمانی که من می خواهم کدی را اجرا کنم کد را به صورت کامل بر روی دیسک قرار می دهم. یعنی کد به یکباره اجرا نمی شود و به شما این امکان را می دهم که هر زمان دوست داشتید ، کد را اجرا کنید.
تفاوت بعدی مربوط به بحث وابستگی به برنامه است. زبان های مفسری برای این که بتوانند بر روی یک سیستم اجرا شوند باید مفسر مورد نظر از قبل روی سیستم نصب شده باشد وگرنه اجرای برنامه امکان پذیر نیست؛ یعنی برای اجرا شدن وابسته به یک مفسر هستند . اما ما کامپایلرها یک بار برای همیشه برنامه را به همراه کدهای اجرایی کامپایل می کنیم که بعد از آن نه نیازی به وجود ما هست نه کد اجرایی برنامه. پس وابستگی به ما بعد از تبدیل کد وجود نخواهد داشت.
تفاوت دیگر در کارایی و انعطاف پذیری بین من و یک مفسر است. این بستگی به شما دارد که کدام گزینه مد نظرتان است، کارایی بهتر را انتخاب می کنید یا قابل حمل بودن و انعطاف پذیری مد نظرتان است. چرا که سرعت اجرای برنامه های مفسری به دلیل خط به خط اجرا شدن کد سرعت کندتری نسبت به ما کامپایلرها دارند.
آخرین تفاوت مسئله خطایابی است. خطایابی کدهای اجرایی در برنامه های مفسری با توجه به اجرای خط به خط آسان تر از خطایابی کدهای اجرایی در ما است.
خب دوستان امیدوارم از مقاله ای که خواندید لذت کافی را برده باشید.
نظر شما در تصمیم دیگران اثرگذار است.
لطفا برای همراهان درسمن و بهتر شدن دوره نظر خود را بنویسید.