زبان اسمبلی چیست؟ معایب و مزایا و چرا باید یاد بگیریم؟ (مقایسه با کامپایل)
زبان اسمبلی (Assembly) یک زبان برنامه نویسی سطح پایین است. سطح پایین به این معنا که دستورالعمل ها ساده هستند و کامپیوتر می تواند به راحتی تشخیص دهد که به او دستور داده شده است. در واقع با استفاده از اسمبلر می توان زبان اسمبلی را به زبان ماشین که پایین ترین سطح زبان است، تبدیل کرد.
چرا بهتر است اسمبلی یاد بگیریم؟
هر شخصی ممکن است این سوال برایش به وجود بیاید که چه لزومی دارد تا وقتی پایتون، جاوا، C++ یا هر زبان دیگری هست، اسمبلی یاد بگیرم؟ در پاسخ باید گفت که اسمبلی به توسعه دهنده امکان دسترسی مستقیم و بدون فیلتر به منابع دستگاه را می دهد. در مقایسه با سایر زبان های برنامه نویسی (مثل C++) که به کامپایل متکی هستند یا تفسیر می شوند (مثل پایتون یا جاوا)، اسمبلی به هیچ وجه نیازی به پیش پردازش ندارد.
بد نیست مفهوم زبان سطح پایین و زبان سطح بالا را بیشتر توضیح بدهیم. معمولا یک برنامه نویس با توجه به هر مشکلی، باید برنامه ای بنویسد که بتواند محاسبات خاصی را انجام بدهد. برای ایجاد کد ، با مشخصاتی به زبان طبیعی (یعنی زبانی که برای انسان قابل درک است) شروع و متغیر ها، توابع و موارد دیگر را اعلان می کند. توضیحات این کد بسته به زبان مورد استفاده می تواند به زبان طبیعی نزدیک باشد یا نباشد.
برای یادگیری کامل اسمبلی: دانلود رایگان آموزش صفر تا صد اسمبلی+ جزوه
زبان سطح بالا زبانی است که خیلی نزدیک به منطق انسان و جزئیات نحوه کار کد روی کامپیوتر، معنادار تر است. این بدان معنا است که یک توسعه دهنده مجبور نیست هنگام نوشتن کد بداند که بخش خاصی از معماری چه طور کار می کند. سه زبان اصلی که به عنوان سطح بالا تعریف می شوند عبارتند ازC ، C++ وJava .
سادگی این 3 زبان برنامه نویسی باعث شده است که همه برای شروع برنامه نویسی به آن ها گرایش پیدا کنند. C، C++ و Java نیازی به دانش خاصی ندارند و ساختار آن ها به راحتی قابل درک است، زیرا خیلی نزدیک به تفکر انسان هستند.
به عنوان نمونه بیایید کد زیر را تجزیه و تحلیل کنیم:
int sum_two_numbers(int a, int b){
int sum;
sum = a + b;
return sum;
}
یک متغیر به نام sum اعلان می کنیم و نتیجه عمل جمع بین دو متغیر a و B را درون آن ذخیره می کنیم. ما نمی دانیم که برنامه به چه روشی با دو متغیر a و b رفتار می کند، چه برسد به سه متغیر! در این مورد، همان طور که می بینید، این خود زبان است که انتزاع ها یا Abstract بسیار ساده ای را برای پیاده سازی جمع ارائه می دهد. برخی از نمونه های ساده این ابسترکت ها می توانند int sum برای ایجاد متغیر، علامت + برای جمع کردن و همین طور return برای برگرداندن یک مقدار باشند.
به دنبال یادگیری سریع تر، حرفه ای تر، کامل تر و با کیفیت فول اچ دی هستید؟ بهترین پکیج آموزش اسمبلی موجود در ایران را ببینید!
برای زبان های سطح پایین که به شیوه کار کامپیوتر نزدیک تر هستند و مستقیما با منابع کامپیوتر کار می کنند، موضوع متفاوت است. در برنامه نویسی به این زبان ها، برنامه نویس باید با ساختار سخت افزاری کامپیوتر، عملکرد و معماری پردازنده ، مخصوصا آدرس های حافظه و ثبات های CPU آشنا باشد.
وقتی قابلیت های زبان اسمبلی را با یک زبان برنامه نویسی سطح بالا مقایسه می کنیم، می بینیم که این زبان هم مزایا و معایبی دارد:
مزایا
- مطالعه اسمبلی به شما کمک می کند تا بفهمید یک کامپیوتر واقعا چه طور کار می کند.
- به شما کمک می کند تا کد زبان های سطح بالاتر (مثل C) را بهتر بنویسید، زیرا متوجه می شوید که چطور آن را اجرا می کند.
- اسمبلی به خاطر این که امکان دسترسی گسترده به تمام منابع کامپیوتر را فراهم می کند، بهترین زبان برنامه نویسی سطح پایین است.
- به شما امکان می دهد تا عملکرد برنامه را بهینه کنید.
معایب
- نوشتن یک برنامه اسمبلی بسیار پیچیده است و نیاز به دانش بالایی دارد.
- هر معماری یک سری دستورالعمل خاص دارد، بنابراین کد اسمبلی روی هر پلتفرمی قابل پیاده سازی نیست.
- طول کد زیاد است و خوانایی پایینی دارد .
مقایسه کامپایل با اسمبل
ممکن است برای یک فرد عادی این سوال به وجود بیاید که اگر هر دو زبان سطح بالا و سطح پایین وجود داشته باشند ، کامپیوتر چه چیزی را تفسیر می کند؟ برای پاسخ به این سوال ابتدا لازم است یک گام به عقب برویم.
همان طور که مشخص است، کامپیوتر در حل مسائل بسیار مفید است . یک الگوریتم (یعنی یک سری دستورات ابتدایی) وجود دارد که اجرای آن امکان اجرای یک مسئله را می دهد. نمونه ای از این الگوریتم ها یافتن 10 عدد اول تا الگوریتم مرتب کردن مجموعه ای از اعداد است. الگوریتم توسط برخی از زبان های برنامه نویسی خاص توصیف و به دستورالعمل هایی قابل درک برای کامپیوتر تبدیل می شوند.
زبان اسمبلی با اسمبلی سالیدورک فرق داره! آموزش اسمبلی سالیدورک از صفر تا صد
به دلیل ماهیت الکترونیکی مجری برنامه ، توصیف یک برنامه فقط با دنبالهای از سیگنال های الکتریکی 0 یا 1 که به صورت فیزیکی توسط یک طرف تفسیر می شوند، امکان پذیر است. بنابراین هدف زبان های برنامه نویسی تبدیل کد به زبان ماشین (یعنی دنباله ای از 0 و 1ها) است. این تبدیل توسط دو برنامه خارجی به نام های “کامپایلر” و ” مفسر ” انجام می شود که بسته به زبان مورد استفاده، هر دو یا فقط یکی از آن ها استفاده خواهد شد.
یک مفسر یا Interpreter وظیفه ارزیابی برنامه را بر عهده دارد. یعنی جریان اجرای کد را دنبال می کند و به طور هم زمان ترجمه دستورات برنامه و اجرای آن ها را به زبان ماشین انجام می دهد. آنچه مفسر برمی گرداند نتیجه اجرای برنامه است. مفسر ها در زبان هایی مثل پایتون ، روبی، پِرل و PHPاستفاده می شوند (به همین دلیل به آن ها زبان های تفسیری می گویند.)
از طرف دیگر یک کامپایلر یا Compiler یک کد شی (باینری) از زبان مبدأ تولید می کند. اجرای برنامه حاصل سریع تر است زیرا مرحله تفسیر قبلا انجام شده است. کامپایلر ها در زبان های برنامه نویسی C وC++ استفاده می شوند.
همه زبانهای برنامه نویسی را از اینجا رایگان یاد بگیرید
برای جبران نقاط ضعف این دو ابزار ، کامپایلر درجا (just-in-time) یا همزمان real-time وجود دارد. این نوع خاص از کامپایلر که گاهی به آن compreter (ترکیبی از کامپایلر و مفسر) هم می گویند، کد برنامه را مثل مفسر ترجمه می کند، یعنی فقط در حین اجرا. به این ترتیب، سرعت اجرای بالا (به لطف کامپایلر) با یک فرآیند توسعه ساده ترکیب می شود.
یکی از بهترین نمونه های شناخته شده زبان مبتنی بر کامپایل درجا، جاوا است. این زبان به عنوان جزئی از محیط اجرای جاوا (JRE)، مثل کامپایلر JIT با تبدیل کد بایتی از قبل تولید شده به زبان ماشین در زمان اجرا، عملکرد برنامه های جاوا را بهتر می کند.
کامپایل و اجرای برنامه
برای اجرای برنامه 3 مرحله طی می شود: کامپایل، لینک دهی، بارگذاری و اجرا.
در طول مرحله کامپایل، کد تجزیه و تحلیل می شود و برای هر دستورالعمل، بخشی از زبان ماشین که آن را پیاده سازی می کند، ایجاد می شود. دستورالعمل های مربوط به اعلان ها یا تخصیص داده ها هم به درستی تفسیر می شوند. خروجی یک فایل شی است که در آن نماد های استفاده شده در کد (مثل برچسب های یادآور مرتبط با داده ها) نگاه داشته می شوند.
یک کامپایلر چهار مرحله اصلی انجام می دهد:
- اسکن: اسکنر یا تجزیه کننده هر بار یک کاراکتر را از کد می خواند و پیگیری می کند که کدام کاراکتر در کدام خط وجود دارد.
- آنالیز لغوی : کامپایلر دنباله کاراکتر هایی که در کد ظاهر می شوند را به یک سری رشته کاراکتر (معروف به توکن) تبدیل می کند که بر اساس یک قانون خاص توسط برنامه ای به نام تحلیلگر لغوی به هم مرتبط می شوند. یک جدول نماد توسط تحلیل گر لغوی به منظور ذخیره کلماتی در کد که با نشانه تولید شده مطابقت دارند، استفاده می شود.
- تجزیه و تحلیل سینتکسی : تجزیه و تحلیل سینتکسی در این مرحله انجام می شود. این آنالیز شامل پیش پردازش برای تعیین این است که آیا توکن های ایجاد شده در طول تجزیه و تحلیل لغوی ترتیب درستی دارند یا خیر. ترتیب صحیح مجموعه ای از کلمات کلیدی که نتیجه دل خواه را ایجاد کند، سینتکس نامیده می شود. کامپایلر باید کد را برای اطمینان از درستی سینتکس بررسی کند.
- تحلیل معنایی : این مرحله از چند مرحله میانی تشکیل شده است. ابتدا ساختار توکن ها به همراه ترتیب آن ها با توجه به گرامر یک زبان خاص بررسی می شود. معنای ساختار توکن توسط تجزیه کننده تفسیر می شود تا در نهایت یک کد میانی به نام کد شی تولید شود.
کد شی شامل دستورالعمل هایی است که عملکرد پردازنده برای یک توکن متناظر را اگر در برنامه شناسایی شود، نشان می دهد. در نهایت، کل کد تجزیه و تحلیل و تفسیر می شود تا ببینیم آیا بهینه سازی ممکن است یا خیر. بعد از انجام بهینه سازی، توکن های اصلاح شده مناسب وارد کد شی می شوند تا کد شی نهایی که در یک فایل ذخیره می شود، تولید شود.
فایل های شی (یا ترجمه شده به زبان ماشین) با Resolve کردن مراجع به نماد های خارجی مورد استفاده در فایل های شی مختلف، با استفاده از برنامه ای به نام پیوند دهنده (Linker)، به یکدیگر مرتبط می شوند. در میان نماد های خارجی مورد استفاده، فراخوانی هایی از توابع کتابخانه ای (مثل Printf() داریم) که خارجی هستند، یعنی در کد تعریف نشده اند. نتیجه یک فایل اجرایی است ، یعنی فایلی که در آن علاوه بر کد، اطلاعاتی در مورد مکان حافظه که برنامه باید در آن بارگیری شود و همین طور نماد هایی که هنوز “مشخص نشده اند” وجود دارد.
حتی اگر کامپایلر فقط در “فاز اول” استفاده شود، اغلب اصطلاح کامپایل برای کل فرآیند تفسیر از زبان سطح بالا به زبان ماشین به کار برده می شود.
زبان برنامه نویسی لینوکس (و 3 زبان برتر برای آن)
برای اجرا، Loader که جزئی از سیستم عامل است، برنامه را در حافظه بارگذاری می کند (سلسل مراتب) و سپس کنترل CPU را به اولین دستور العمل برنامه منتقل می کند (در سیستم هایی مثل ویندوز که کتابخانه های پویایی دارند، پیوند دهنده پویا برای مشخص کردن نماد های گم شده فراخوانی می شود). رویه های دیگری در سایر مکانیسم های پیچیده تر انجام می شوند . در زمان اجرای واقعی اولین دستور برنامه، یک مکان حافظه ویژه که در یک ثبات CPU قرار گرفته، وجود دارد که حاوی آدرس حافظه به درد بخوری است که دستور بعدی زبان ماشین است و باید اجرا شود .
تا به حال در مرحله کامپایل، به اسمبلی اشاره ای نکرده ایم، اما باز هم این سوال پیش می آید که به چه دردی می خورد؟ و چرا نیاز به یک زبان سطح پایین وجود دارد در حالی که نوشتن برنامه ها با استفاده از زبان های سطح بالا آسان تر است؟
سطوح اجرا
هر کد 5 سطح برای اجرا دارد. هر سطح شامل یک رابط (یعنی چیزی که از بیرون قابل مشاهده است و در واقع توسط سطح بالا استفاده می شود) و اجرا که از رابط سطح پایین استفاده می کند.