اسمبلر، یا زبان اسمبلی، یک زبان برنامهنویسی سطح پایین است که نمایشی نمادین از دستورالعملهای کد ماشین یک کامپیوتر را فراهم میکند. بر خلاف زبانهای برنامهنویسی سطح بالا که جزئیات سختافزاری را پنهان میکنند، زبان اسمبلی به برنامهنویسان این امکان را میدهد که برنامههایی بنویسند که به معماری کامپیوتر نزدیک باشد. این به توسعهدهندگان کنترل دقیقتری بر منابع سختافزاری میدهد و آن را برای کارهایی که نیاز به تعامل مستقیم یا دستکاری سختافزار دارند، مانند سیستمهای عامل، سیستمهای تعبیهشده و برنامههای حساس به عملکرد، ضروری میسازد.
زبان اسمبلی در روزهای اولیه محاسبات به عنوان وسیلهای برای سادهسازی فرآیند برنامهنویسی با استفاده از کد ماشین باینری ظهور کرد. اولین اسمبلر برای کامپیوتر و ادغام عددی الکترونیکی (ENIAC) در دهه 1940 ایجاد شد و به برنامهنویسان این امکان را داد که دستورالعملها را به فرمت قابل خواندن برای انسان بنویسند. با تکامل معماریهای کامپیوتری، زبانهای اسمبلی نیز تکامل یافتند و اسمبلرهای مختلفی برای پاسخگویی به طراحیهای سختافزاری مختلف توسعه یافتند.
اسمبلر به طور مستقیم از معماری کامپیوتر خاصی که هدف قرار میدهد، الهام گرفته است. هر نوع پردازنده زبان اسمبلی خاص خود را دارد، مانند x86 (برای پردازندههای اینتل و AMD)، ARM (که به طور گسترده در دستگاههای موبایل استفاده میشود) و MIPS (که در سیستمهای تعبیهشده استفاده میشود). در حالی که زبانهای اسمبلی برخی مفاهیم بنیادی را به اشتراک میگذارند، اما مجموعه دستورالعملها و قابلیتهای عملیاتی منحصر به فرد پلتفرمهای سختافزاری خود را منعکس میکنند.
امروزه، در حالی که زبان اسمبلی زبان اصلی برای توسعه برنامهها نیست، در حوزههای خاصی همچنان مرتبط است. این زبان به طور معمول برای نوشتن بخشهای حساس به عملکرد کد، درایورهای دستگاه و سیستمهای زمان واقعی استفاده میشود. علاوه بر این، درک زبان اسمبلی برای زمینههایی مانند مهندسی معکوس، تحلیل بدافزار و امنیت سیستمها ضروری است.
اسمبلر از نمادها استفاده میکند که نمایندگیهای نمادین از دستورالعملهای ماشین هستند. به عنوان مثال، MOV AX, 1
نمایانگر انتقال مقدار 1
به رجیستر AX
است.
زبان اسمبلی اجازه دستکاری مستقیم رجیسترهای پردازنده را میدهد. به عنوان مثال، دستور ADD AX, BX
مقادیر موجود در رجیسترهای AX
و BX
را جمع کرده و نتیجه را در AX
ذخیره میکند.
برچسبها برای علامتگذاری موقعیتها در کد برای پرشها و حلقهها استفاده میشوند. یک برچسب ممکن است به شکل start:
باشد. این برای ایجاد حلقهها با دستوراتی مانند JMP start
مفید است.
دستورات رفتار اسمبلر را کنترل کرده و متاداده را فراهم میکنند. به عنوان مثال، دستورات .data
و .text
بخشهایی برای داده و کد را نشان میدهند.
نظرات میتوانند برای مقاصد مستندسازی با استفاده از نقطهویرگول گنجانده شوند. به عنوان مثال، ; این یک نظر است
.
زبان اسمبلی از دستورهای جریان کنترل مانند JMP
، JE
(پرش اگر برابر باشد) و JNE
(پرش اگر برابر نباشد) پشتیبانی میکند که امکان انشعاب در اجرای کد را فراهم میآورد.
هر دستور اسمبلی معمولاً شامل یک عمل (کد عملیاتی) به همراه عملوندها است. عملیات میتواند یکعملی، دو عملی یا از فرمتهای پیچیدهتری بسته به معماری مجموعه دستورالعملها استفاده کند.
زبان اسمبلی اجازه استفاده از مقادیر فوری را به طور مستقیم در دستورها میدهد، مانند MOV AX, 5
، جایی که 5
یک مقدار فوری است که به رجیستر AX
اختصاص داده شده است.
زبان اسمبلی از رویهها و فراخوانیهای زیررویه پشتیبانی میکند که امکان استفاده مجدد از کد را فراهم میآورد. این میتواند با استفاده از دستور CALL
به دنبال یک برچسب فراخوانی شود، به عنوان مثال، CALL myFunction
.
در حالی که اسمبلی انواع دادههای سطح بالا ندارد، دادهها میتوانند با استفاده از بایت، کلمه یا دو کلمه بر اساس معماری مدیریت شوند و آدرسهای حافظه میتوانند به طور مستقیم دستکاری شوند.
یک اسمبلر کد زبان اسمبلی را به کد ماشین تبدیل میکند. اسمبلرهای مختلفی وجود دارند، مانند NASM (اسمبلر نتواید)، MASM (اسمبلر ماکرو مایکروسافت) و GAS (اسمبلر گنو)، که هر کدام به معماریها یا سیستمعاملهای خاصی هدفگذاری شدهاند.
محیطهای توسعه برای زبان اسمبلی کمتر از زبانهای سطح بالاتر رایج هستند، اما شامل IDEهای خاصی مانند MPLAB X IDE برای میکروکنترلرهای PIC یا Keil برای توسعه ARM میشوند.
برای ساخت یک پروژه در زبان اسمبلی، توسعهدهندگان معمولاً کد منبع را در یک ویرایشگر متن مینویسند و سپس اسمبلر را از طریق خط فرمان برای تولید فایلهای باینری یا شیء فراخوانی میکنند. به عنوان مثال، با استفاده از NASM، یک دستور معمولی ممکن است به شکل زیر باشد:
nasm -f elf64 myprogram.asm -o myprogram.o
سپس، لینک کردن میتواند با استفاده از یک لینککننده مانند ld
برای ایجاد یک فایل اجرایی انجام شود:
ld myprogram.o -o myprogram
زبان اسمبلی عمدتاً در زمینههایی که نیاز به عملکرد بهینه و دستکاری مستقیم سختافزار دارند، استفاده میشود. کاربردهای کلیدی شامل:
بر خلاف زبانهای سطح بالاتر مانند C، C++ یا Java که انتزاعهایی بر روی سختافزار ارائه میدهند، زبان اسمبلی کنترل مستقیم بر روی دستورالعملهای ماشین را فراهم میکند. این باعث میشود برنامههای اسمبلی معمولاً سریعتر و کوچکتر باشند، که در محیطهای محدود از نظر منابع حیاتی است، اما به طور قابل توجهی کمتر قابل حمل هستند.
در حالی که بهینهسازی زبان اسمبلی میتواند عملکرد برتری را به ارمغان آورد، زبانهایی مانند C و C++ فرآیند توسعه را به طور قابل توجهی ساده میکنند. زبانهای سطح بالا مدیریت حافظه، بررسی خطا و کتابخانههای گستردهای را مدیریت میکنند که آنها را برای اکثر برنامهها مناسب میسازد.
نحو زبان اسمبلی در مقایسه با زبانهایی مانند Python یا JavaScript که بر خوانایی و سهولت استفاده تأکید دارند، پیچیدهتر در نظر گرفته میشود. یادگیری اسمبلی نیاز به درک معماری کامپیوتر دارد، در حالی که زبانهای سطح بالا این جزئیات را پنهان میکنند.
چندین ابزار برای ترجمه زبانهای سطح بالا به اسمبلی یا امکان تعامل اسمبلی با کدهای سطح بالا وجود دارد. برخی از اسمبلرها میتوانند کد C را به طور مستقیم ادغام کنند و اجازه پروژههای مختلط را بدهند. ابزارهایی مانند LLVM نیز میتوانند از کد نوشته شده در زبانهای سطح بالا اسمبلی تولید کنند.
برای توسعهدهندگانی که به دنبال تبدیل کد از یک زبان سطح بالا به اسمبلی هستند، مطالعه مجموعه دستورالعملهای معماری هدف و استفاده از ابزارهای پروفایلینگ برای راهنمایی تلاشهای بهینهسازی مفید است. همچنین توصیه میشود از کامپایلرهای موجود مانند GCC که میتوانند کد اسمبلی را برای تحلیل یا اصلاح بیشتر تولید کنند، استفاده شود.