آموزش اسمبلی (Assembly)

آموزش اسمبلی

آنچه در این صفحه می خوانید:

معرفی زبان اسمبلی (Assembly)

Assembly یا ASM یک زبان برنامه نویسی سطح پایین است. زیرا ارتباط یک به یک بین آنچه که به کامپیوتر می گوید تا انجام دهد و آنچه که کامپیوتر انجام می دهد وجود دارد. برنامه های نوشته شده در زبان اسمبلی توسط یک اسمبلر کامپایل می شود. هر اسمبلر دارای زبان اسمبلی خود است، که برای یک معماری خاص کامپیوتری طراحی شده است. زبان ماشین تنها متشکل از اعداد است که خواندن آن برای انسان ها آسان نیست. با استفاده از ASM، برنامه نویسان می توانند برنامه های قابل خواندنی را بنویسند که تقریبا با زبان ماشین شباهت دارد. عیب ASM این است که هر چیزی را که کامپیوتر انجام می دهد باید به روشنی و دقیق توصیف کند. مزیت ASM این است که برنامه نویس حداکثر کنترل بر روی عملکرد کامپیوتر را دارد.

در برنامه نویسی رایانه، زبان اسمبلی، که اغلب به اختصار asm است، هر زبان برنامه نویسی سطح پایین است که در آن مکاتبات بسیار قوی ای بین دستورالعمل های موجود در زبان و دستورالعمل های کد دستگاه معماری وجود دارد. از آنجا که اسمبلی به دستورالعمل کد دستگاه بستگی دارد، هر اسمبلر زبان اسمبلی خود را دارد که دقیقاً برای یک معماری خاص رایانه طراحی شده است. زبان اسمبلی ممکن است کد ماشین نمادین نیز خوانده شود.

کد اسمبلی توسط یک برنامه کاربردی که به آن اسمبلر گفته می شود به کد دستگاه اجرایی تبدیل می شود. فرآیند تبدیل به عنوان اسمبلی، به عنوان اسمبلی کد منبع، به عنوان اسمبلی گفته می شود. زبان اسمبلی معمولاً در هر دستورالعمل دستگاه دارای یک جمله است، اما نظرات و اظهاراتی که بخواهند اسمبلر، ماکرو و برچسب های نمادین از مکان های برنامه و حافظه باشند نیز پشتیبانی می شوند.

هر زبان اسمبلی مختص معماری رایانه ای خاص و بعضی اوقات برای یک سیستم عامل است. اما، برخی از زبانهای اسمبلی برای مکالمات سیستم عامل نحو خاصی را ارائه نمی دهند و اکثر زبانهای اسمبلی می توانند با هر سیستم عامل به صورت جهانی مورد استفاده قرار گیرند، زیرا این زبان امکان دسترسی به کلیه قابلیت های واقعی پردازنده را فراهم می کند، که براساس آن همه مکانیسم های فراخوانی سیستم در نهایت استراحت می کنند. . برخلاف زبانهای اسمبلی، اکثر زبانهای برنامه نویسی سطح بالا معمولاً در معماری های مختلف قابل حمل هستند اما نیاز به تفسیر یا تدوین دارند، کار بسیار پیچیده تری نسبت به اسمبلی.

تاریخچه زبان اسمبلی (Assembly)

زبانهای اسمبلی در زمان معرفی رایانه برنامه ذخیره شده در دسترس نبودند. کاتلین غرفه "با اختراع زبان اسمبلی" اعتبار دارد و براساس کار تئوریکی که در سال 1947 آغاز کرد، در حالی که در ARC2 در بیرکبک کار می کرد، دانشگاه لندن پس از مشورت اندرو بوت (بعداً شوهرش) با ریاضیدان جان فون نویمان و فیزیکدان جیمز گلدنستاین در انستیتوی مطالعات پیشرفته.

در اواخر سال 1948، ماشین حساب خودکار تأخیر الکترونیکی ذخیره سازی (EDSAC) یک اسمبلر (با نام "سفارشات اولیه") در برنامه راه انداز خود داشت. این مونامیک تک حرف ایجاد شده توسط دیوید ویلر، که توسط انجمن رایانه ای IEEE به عنوان خالق اولین "اسمبلر" شناخته شده است، استفاده می شود. گزارش های مربوط به EDSAC اصطلاح "اسمبلی" را برای فرآیند ترکیب زمینه ها در یک کلمه دستورالعمل معرفی می کند. [34] SOAP (برنامه اسمبلی بهینه Symbolic) یک زبان اسمبلی برای رایانه IBM 650 بود که توسط استن پولی در سال 1955 نوشته شده است.

زبانهای اسمبلی بسیاری از برنامه نویسان مستعد خطا، خسته کننده و وقت گیر را که توسط اولین کامپیوترها لازم است، از بین می برد، و برنامه نویسان را از برنامه هایی مثل یادآوری کدهای عددی و محاسبه آدرس ها آزاد می کند. آنها زمانی برای همه نوع برنامه نویسی مورد استفاده قرار می گرفتند. با این حال، تا دهه 1980 (1990s در میکرو رایانه ها)، در جستجوی بهبود بهره وری برنامه نویسی، استفاده از آنها توسط زبانهای سطح بالاتر کاشته شده بود. امروزه زبان اسمبلی هنوز برای دستکاری مستقیم سخت افزار، دسترسی به دستورالعمل های پردازنده تخصصی یا برای رفع مشکلات عملکرد مهم مورد استفاده قرار می گیرد. کاربردهای معمولی درایورهای دستگاه، سیستم های جاسازی شده سطح پایین و سیستم های زمان واقعی هستند.

از لحاظ تاریخی، برنامه های بی شماری کاملاً به زبان اسمبلی نوشته شده است. Burroughs MCP (1961) اولین رایانه ای بود که سیستم عامل کاملاً به زبان اسمبلی توسعه نیافته بود. آن را به زبان سیستم های اجرایی مسئله محور (ESPOL)، با لهجه Algol نوشته شده است. بسیاری از برنامه های تجاری به زبان اسمبلی نیز نوشته شده اند، از جمله مقدار زیادی از نرم افزار اصلی IBM که توسط شرکت های بزرگ نوشته شده است. COBOL، FORTRAN و برخی PL / I سرانجام بخش اعظم این کار را جابجا کردند، اگرچه تعدادی از سازمان های بزرگ زیرساخت های برنامه های کاربردی زبان اسمبلی را به خوبی در دهه 1990 حفظ کردند.

اکثر میکرو رایانه های اولیه به زبان اسمبلی رمزگذاری شده دستی، از جمله بیشتر سیستم های عامل و برنامه های بزرگ، اعتماد داشتند. دلیل این امر این بود که این سیستم ها دارای محدودیت شدید در منابع بودند، حافظه بصری و معماری نمایش را تحمیل می کردند، و خدمات محدودی را برای سیستم های مختلف ارائه می دادند. شاید مهم تر عدم وجود کامپایلرهای سطح اول سطح بالا مناسب برای استفاده از میکرو کامپیوتر باشد. یک عامل روانشناختی نیز ممکن است نقشی داشته باشد: اولین نسل از برنامه نویسان ریز کامپیوتر یک نگرش سرگرمی، "سیم و انبردست" را حفظ کردند.

در یک زمینه تجاری تر، بزرگترین دلایل استفاده از زبان اسمبلی حداقل نفخ (اندازه)، حداقل سربار، سرعت بیشتر و قابلیت اطمینان بود.

نمونه بارز برنامه های زبان اسمبلی بزرگ از این زمان، سیستم عامل های IBM PC DOS، کامپایلر Turbo Pascal و برنامه های اولیه مانند برنامه صفحه گسترده Lotus 1-2-3 است. از زبان اسمبلی برای به دست آوردن بهترین عملکرد از Sega Saturn استفاده شد، کنسولی که برای توسعه و برنامه ریزی بازی ها به سختی چالش برانگیز بود. بازی بازی NBA Jam در سال 1993 نمونه دیگری است.

زبان اسمبلی مدتهاست که زبان اصلی توسعه برای بسیاری از رایانه های خانگی محبوب دهه های 1980 و 1990 بوده است (مانند MSX، Sinclair ZX Spectrum، Commodore 64، Commodore Amiga و ST Atari). این امر تا حد زیادی به این دلیل بود كه گویشهای BASIC در این سیستم تفسیر شده، سرعت اجرای كافی و همچنین امکانات كافی را برای استفاده كامل از سخت افزارهای موجود در این سیستمها ندارند. برخی از سیستم ها حتی دارای یک محیط توسعه یکپارچه (IDE) با امکانات بسیار پیشرفته برای اشکال زدایی و کلان است برخی از کامپایلرهای موجود برای Radio Shack TRS-80 و جانشینان آن توانایی ترکیب منبع اسمبلی درون خطی با گفته های برنامه سطح بالا را داشتند. پس از گردآوری، یک اسمبلر داخلی کد دستگاه درون خطی تولید کرد.

معرفی زبان ماشین (Machine code)

کد ماشین یک برنامه کامپیوتری است که به دستورالعمل های مربوط به زبان دستگاه نوشته شده است که می تواند مستقیماً توسط واحد پردازش مرکزی رایانه (CPU) اجرا شود. هر دستورالعمل باعث می شود CPU یک کار بسیار خاص مانند بار، فروشگاه، پرش یا عملکرد ALU را در یک یا چند واحد داده موجود در ثبات ها یا حافظه های CPU انجام دهد.

کد ماشین یک زبان کاملاً عددی است که برای اجرای سریعترین زمان ممکن در نظر گرفته شده است و ممکن است به عنوان پایین ترین سطح یک برنامه کامپیوتری کامپایل شده یا اسمبلی شده یا به عنوان یک زبان برنامه نویسی بدوی و وابسته به سخت افزار در نظر گرفته شود. در حالی که امکان نوشتن برنامه ها به طور مستقیم با کد دستگاه امکان پذیر است، اما مدیریت بیت های فردی و محاسبه آدرس های عددی و ثابت بصورت دستی خسته کننده و مستعد است. به همین دلیل، برنامه ها به ندرت به طور مستقیم با کد دستگاه در متن های مدرن نوشته می شوند، اما ممکن است برای اشکال زدایی در سطح پایین، وصله برنامه (به ویژه هنگامی که منبع اسمبلر در دسترس نباشد) و جداسازی زبان اسمبلی انجام شود.

امروزه اکثر قریب به اتفاق برنامه های عملی به زبانهای سطح بالاتر یا زبان اسمبلی نوشته شده است. کد منبع پس از آن با استفاده از برنامه هایی مانند کامپایلرها، اسمبلرها و پیوند دهنده ها، به استثنای مهم برنامه های تفسیر شده، که به کد ماشین ترجمه نشده اند، به کد دستگاه اجرایی ترجمه شده است. با این حال، خود مترجم، که ممکن است به عنوان مجری یا پردازنده در نظر گرفته شود، و دستورالعمل کد منبع را انجام می دهد، معمولاً از کد دستگاه مستقیماً قابل اجرا (تولید شده از اسمبلی یا کد منبع سطح بالا) تشکیل شده است.

کد ماشین به معنای پایین ترین سطح جزئیات برنامه نویسی است که برای برنامه نویس قابل مشاهده است، اما در داخل بسیاری از پردازنده ها از میکروکد استفاده می کنند یا دستورالعمل های کد ماشین را به توالی میکرو آپشن تبدیل می کنند. این به طور کلی به عنوان کد دستگاه در نظر گرفته نمی شود.

کاربرد زبان اسمبلی (Assembly)

امروزه، زبان اسمبلی در درجه اول برای دستکاری مستقیم سخت افزار، دسترسی به دستورالعمل های پردازنده تخصصی یا برای رفع مشکلات عملکرد مهم مورد استفاده قرار می گیرد. کاربردهای معمولی درایورهای دستگاه، سیستم های جاسازی شده سطح پایین و سیستم های زمان واقعی هستند (EDIT: Thanks Trollslayer). واقعیت موضوع این است که، هرچه زبانهای سطح بالا پیچیده تر می شوند، و هرچه ADT (انواع داده های انتزاعی) نوشته شود، سرباز بیشتری برای پشتیبانی از این گزینه ها ایجاد می شود. در مواردی از .NET، شاید MSIL نفخ. تصور کنید اگر MSIL را می شناختید. اینجاست که زبان اسمبلی می درخشد. (ویرایش) زبان اسمبلی به همان پردازنده نزدیک است که می توانید به عنوان یک برنامه نویس بدست آورید، بنابراین یک الگوریتم به خوبی طراحی شده چشمک می زند - اسمبلی برای بهینه سازی سرعت بسیار عالی است. این همه در مورد عملکرد و کارایی است. زبان اسمبلی به شما امکان کنترل کامل بر منابع سیستم را می دهد. دقیقاً مانند یک خط اسمبلی، شما برای ارسال مقادیر واحد به رجیسترها، كدی را می نویسید، با آدرس های حافظه مستقیماً بازیابی مقادیر یا نشانگرها می شوید. نوشتن در اسمبلی این است که دقیقاً بدانید که چگونه پردازنده و حافظه با هم همکاری می کنند تا "اتفاقات را بیفتد". هشدار دهید، زبان اسمبلی رمزنگاری است و اندازه کد منبع برنامه ها بسیار بزرگتر از یک زبان سطح بالا است.

سینتکس زبان اسمبلی (Assembly)

زبان اسمبلی برای نشان دادن هر دستورالعمل یا كیفیت سطح پایین دستگاه معمولاً از هر رجیستر معماری، پرچم و غیره استفاده می كند. در بسیاری از عملیات ها برای ایجاد یك دستورالعمل كامل به یك یا چند عملوند نیاز دارند. بیشتر اسمبلر ها ثابت، رجیسترها و برچسب های نامگذاری شده برای مکان های برنامه و حافظه را مجاز می دانند و می توانند عبارات مربوط به عملگرها را محاسبه کنند. بنابراین، برنامه نویسان از محاسبات تکراری خسته کننده خلاص می شوند و برنامه های اسمبلر بسیار خواندنی تر از کد دستگاه هستند. بسته به نوع معماری، این عناصر همچنین ممکن است برای دستورالعمل های خاص یا حالت های آدرس دهی با استفاده از جبران خلال ها یا سایر داده ها و همچنین آدرس های ثابت ترکیب شوند. بسیاری از اسمبلرها مکانیسم های اضافی را برای تسهیل توسعه برنامه، کنترل روند اسمبلی و کمک به اشکال زدایی ارائه می دهند.

واژه شناسی

  • اسمبلر کلان شامل یک تأسیسات کلان است به گونه ای که متن زبان اسمبلی (به صورت پارامتری) می تواند توسط یک اسم نشان داده شود و از آن نام برای وارد کردن متن گسترش یافته در کد دیگر استفاده شود.
  • اسمبلی کننده متقاطع (همچنین به کامپایلر متقاطع مراجعه کنید) اسمبلر است که بر روی رایانه یا سیستم عامل (سیستم میزبان) از نوع دیگری از سیستمی که بر روی آن کد اجرای می شود (سیستم هدف) اجرا می شود. اسمبلی متقابل توسعه برنامه هایی برای سیستمهایی که منابع لازم برای پشتیبانی از توسعه نرم افزار را ندارند، مانند سیستم تعبیه شده یا میکروکنترلر را تسهیل می کند. در چنین حالتی، کد شیء حاصل باید از طریق حافظه فقط خواندنی (ROM، EPROM و غیره)، یک برنامه نویس (هنگامی که حافظه فقط خواندنی در دستگاه است، مانند میکروکنترلرها ادغام شود) به سیستم مورد نظر منتقل شود. یا پیوند داده با استفاده از کپی دقیق بیت بیت کد شیء یا نمایش متن مبتنی بر آن کد (مانند Motorola S-record یا Intel HEX).
  • اسمبلر سطح بالا برنامه ای است که انتزاعات زبان را بیشتر با زبان های سطح بالا همراه می کند، مانند ساختارهای کنترل پیشرفته (IF / THEN / ELSE، DO CASE و غیره) و انواع داده انتزاعی سطح بالا، از جمله ساختارها / سوابق، اتحادیه ها، کلاس ها و مجموعه ها.
  • اسمبلی کننده ماکرو برنامه ای است که به تهیه میکروگرام به نام سیستم عامل کمک می کند تا عملکرد سطح پایین یک کامپیوتر را کنترل کند.
  • meta-assembler اصطلاحی است که در برخی محافل برای "برنامه ای که توصیف نحوی و معنایی یک زبان اسمبلی را می پذیرد، ایجاد می کند و اسمبلر را برای آن زبان تولید می کند".
  • زمان اسمبلی یک مرحله محاسباتی است که در آن یک اسمبلی اجرا می شود.

نصب های 64 بیتی لینوکس از دستورالعمل SYSCALL پردازنده استفاده می کنند تا به بخشی از حافظه که در آن سرویس های سیستم عامل ذخیره شده است ، پرش کنند. برای استفاده از SYSCALL ، ابتدا شماره تماس سیستم را در RAX قرار دهید ، سپس آرگومان ها را در صورت وجود ، به ترتیب در RDI ، RSI ، RDX ، R10 ، R8 و R9 قرار دهید. در مثال اول ما از فراخوانیهای سیستم برای نوشتن به یک فایل (شماره تماس 1) و خروج از یک فرآیند (شماره تماس 60) استفاده خواهیم کرد. اینجا در زبان مونتاژ NASM است:

; ----------------------------------------------------------------------------------------
; Writes "Hello, World" to the console using only system calls. Runs on 64-bit Linux only.
; To assemble and run:
;
;     nasm -felf64 hello.asm && ld hello.o && ./a.out
; ----------------------------------------------------------------------------------------

global _start

section .text _start: mov rax, 1 ; system call for write mov rdi, 1 ; file handle 1 is stdout mov rsi, message ; address of string to output mov rdx, 13 ; number of bytes syscall ; invoke operating system to do the write mov rax, 60 ; system call for exit xor rdi, rdi ; exit code 0 syscall ; invoke operating system to exit

section .data message: db "Hello, World", 10 ; note the newline at the end

آیا زبان اسمبلی هنوز هم کاربرد دارد؟

بله بانک هایی وجود دارند که سیستم بانکی اصلی خود را بر روی اسمبلی اصلی (IBM Z / OS، aka S / 370) اجرا می کنند! اگر در اینترنت به جستجوی اسمبلر اصلی فریم در بانکی بپردازید، هیچ کمبود آگهی شغلی را نشان نمی دهد که نشان می دهد این مورد است.

جالب است بدانید که چرا یک بانک در سال 2017 هنوز سیستمهای اصلی خود را با چنین فناوری میراثی اجرا می کند. معلوم است که وقتی میلیون ها خط از چنین کد با اکوسیستم فناوری گسترده بانکی و شریک فناوری یکپارچه شده اید، حتی اگر بخش اعظم آن از 30+ سال پیش نوشته شده باشد، جایگزین کردن آن بسیار گران و عملی است. به هیچ وجه غیرممکن نیست، اما ایجاد یک پرونده قانع کننده چالش برانگیز است، به ویژه هنگامی که کد موجود به طور کامل مستهلک شود، عملکرد خوبی، نسبتاً پایدار داشته باشد و پاسخگوی نیازهای فعلی تجاری باشد. البته، پاسخگویی به نیازهای آینده ممکن است چالش برانگیزتر باشد، اما این نیز اثبات سختی است.

به سؤال گسترده تری، بررسی پست های مشاغل اسمبلر (نه تنها mainframe بلکه x86 و سیستم عامل های دیگر) نشان می دهد که مجموعه گسترده ای از کار اسمبلی در دامنه هایی مانند:

  • نرم افزار جاسازی شده
  • مهندسی معکوس
  • تجزیه و تحلیل امنیتی
  • ابزارهای نرم افزاری با کارایی بالا

بنابراین به نظر می رسد پاسخ این است که هر دو میراث و دلایل مداوم وجود دارد که چرا اسمبلر همچنان به کار خود ادامه می دهد. به نظر شما در مورد "منحصرا": در بیشتر زمینه ها، حداقل برخی از نرم افزارهای "wrapper" وجود دارند که به زبانها و محیطهای دیگر برنامه نویسی نوشته شده اند، به عنوان مثال. برای عناصر UI. در زمینه هایی مانند زمان واقعی و محاسبات با کارایی بالا، ممکن است این باشد که تنها مهمترین عناصر مهم برای عملکرد در اسمبلر دست ساخته می شوند، و بقیه نرم افزارها به زبانهای سطح بالا قابل انعطاف می باشند.

اسمبلی واقعاً فقط یک پراکسی برای یک زبان ماشین است، بنابراین، مطمئناً شما می توانید با یک زبان سطح بالاتر، کارهایی را در اسمبلی انجام دهید. برعکس همیشه اینگونه نیست. به عنوان مثال، چند سال پیش، من روی یک CPU ARM کار کردم که دارای چند نسخه بد بو برای تغییر حالت های گرافیکی بود که فقط از حالت هسته قابل استفاده هستند. آنها معادل مستقیمی با یک زبان سطح بالاتر نخواهند داشت، و من مطمئن هستم که عملکرد درایور هسته لینوکس برای تغییر این ایالات شامل برخی اسمبلیها است.

در مورد ریز پردازنده های دهه 80 و اوایل اواسط دهه 90، اگر کد خاصی را برای اجرای سریع سریع لازم داشتید، اغلب آنرا در اسمبلی می نوشتید، زیرا یک انسان ماهر می توانست به راحتی اسمبلی بهینه تر را از بیشتر C بنویسد. کامپایلرها می توانند تولید کنند. برخی از برنامه های اولیه مک کاملاً به صورت اسمبلی نوشته شده بودند و برای دوره حیرت انگیز سریع بودند. حتی بدون نوشتن کل برنامه در اسمبلی، مطمئناً سهم خود را از بهینه سازی حلقه های داخلی در C از طریق اسمبلی تعبیه شده انجام دادم.

اما اوضاع از اواسط دهه 1990 شروع به تغییر کرد. CPU از جمله ویژگی هایی مانند خط لوله و پیش بینی شاخه ها شروع شد، بنابراین کارآمدترین دستورالعمل دستورالعمل همیشه برای انسان آشکار نبود. بدتر از آن، کارآمدترین سفارش در بین CPU های یک خانواده متفاوت است. به عنوان مثال، کامپایلرهای PowerPC معمولاً سوئیچ های هدف را برای سری های G3، G4 و G5 ارائه می دهند. همان کد شیء روی همه آنها اجرا می شود، اما کارآمدتر در یکی از آن سری ها است.

از آن زمان، دستورالعمل دستورالعمل به تدریج پیچیده تر می شود، به خصوص در CPU های با معماری پیچیده تر مانند x86، PowerPC و SPARC. (معتقدم ARM هنوز به همین روش بسیار ساده است.) یک عامل بزرگ اضافه شده اندازه کد است - کدی که از سیکل های CPU بیشتری استفاده می کند اما می تواند در حافظه نهان CPU باقی بماند غالباً بسیار سریعتر از کدی که از چرخه های CPU کمتری استفاده می کند اجرا می شود اما باعث می شود حافظه کند شود. کامپایلرهای اصلی مدرن می توانند کار به مراتب بهتر از بهینه سازی کد در آن پردازنده ها نسبت به آنچه انسان منطقی است انجام دهد.

استفاده اصلی برای اسمبلی:

  • برای خواندن زباله های جداسازی شده در هنگام اشکال زدایی، که بعضی اوقات حتی امروز نیز انجام می دهم.
  • برخورد با ویژگی های CPU غیر استاندارد، مانند آن حالت گرافیکی بد بو.
  • نوشتن کامپایلر - این یک فرمت متوسط ​​و قابل خواندن توسط انسان برای ترجمه زبانهای سطح بالاتر به زبان را فراهم می کند.
آیا این نوشته را دوست داشتید؟