پرش به محتوا

کد ماشین

از ویکی‌پدیا، دانشنامهٔ آزاد
مانیتور زبان ماشین در یک رایانه تک صفحه W65C816S، نمایش جدا شدن کد، و همچنین رجیستر پردازنده و تخلیه حافظه.

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

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

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

دستورالعمل‌های کد ماشین

[ویرایش]

هر پردازنده یا خانوادهٔ پردازنده، مجموعهٔ دستورالعمل کد ماشین مربوط به خود را دارد. دستورالعمل‌ها، مولد بیت‌هایی می‌باشند که توسط طراحی فیزیکی، متناظر با دستورها مختلفی برای ماشین هستند؛ بنابراین، مجموعهٔ دستورالعمل، مخصوص به دسته‌ای از پردازنده‌هاست که (تقریباً) از معماری مشابهی بهره می‌برند. طراحی‌های جانشین یا پردازندهٔ فرعی اغلب شامل تمام دستورالعمل‌های یک دستور پیشین هستند و ممکن است دستورالعمل‌های اضافی را بیافزایند. گه گاه، یک طراحی جایگزین - که مفهوم و معنی برخی کدهای دستورالعمل را تغییر خواهد داد یا قطع خواهد کرد (چون معمولاً برای اهداف جدید مورد نیاز است) - تا حدی روی سازگاری کد تأثیر می‌گذارد؛ حتی تقریباً پردازنده‌های کاملاً سازگار ممکن است برای برخی دستورالعمل‌ها رفتار کمی متفاوت نشان دهند ولی این به ندرت یک مشکل محسوب می‌شود. همچنین ممکن است سیستم‌ها در جزئیات دیگری مانند چیدمان حافظه، سیستم‌های عامل یا دستگاه‌های جانبی متفاوت باشند. از آن‌جایی که یک برنامه به شکل معمولی به چنین عواملی بستگی دارد، سیستم‌های متفاوت معمولاً یک کد ماشین اجرا نخواهند کرد، حتی وقتی نوع پردازندهٔ یکسانی استفاده شود.

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

تمام ماشین‌ها یا دستورالعمل‌های فردی، عملوندهای صریح ندارند. یک ماشین انباشتگر دارای یک عملوند چپ ترکیبی است که منتج به انباشتگر ضمنی برای بیشتر دستورالعمل‌های ریاضیاتی می‌شود. سایر معماری‌ها (مانند ۸۰۸۶ و خانوادهٔ x86) نسخه‌های انباشتگری از دستورالعمل‌های رایج دارند که در آن‌ها، انباشتگر توسط دستورالعمل‌های طولانی‌تر به عنوان یکی از رجیسترهای اصلی در نظر گرفته می‌شود. بیشتر عملوندهای یک ماشین استک، روی یک استک، به صورت ضمنی است. دستورالعمل‌های با هدف خاص نیز اغلب دارای کمبود عملوندهای صریح هستند (به عنوان مثال CPUID در معماری x86، مقادیر را در چهار رجیستر مقصد ضمنی می‌نویسد). این تمایز بین عملوندهای ضمنی و صریح، در مولدهای کد ماشین، مخصوصاً در تخصیص رجیستر و بخش‌های ردیابی محدودهٔ زنده، مهم است. یک بهینه‌ساز کد خوب می‌تواند عملوندهای ضمنی را به خوبی عملوندهای صریح - که ممکن است اجازهٔ انتشار پرتکرار، به‌هم‌آمیختن ثابت رجیسترها (یک رجیستر که حاصل یک عبارت ثابت به آن اختصاص یافته‌است با جایگزین‌کردنش با آن ثابت، آزاد می‌شود) و سایر بهبوددهی‌های کد را بدهد - را ردیابی کند.

برنامه‌ها

[ویرایش]

یک برنامهٔ رایانه‌ای یک دنباله از دستورالعمل‌هاست که توسط یک CPU اجرا می‌شوند. علی‌رغم اینکه پردازنده‌های ساده، دستورالعمل‌ها را یکی بعد از دیگری اجرا می‌کنند، پردازنده‌های ابرمقیاس‌پذیر قادر به اجرای چندین دستورالعمل به‌طور همزمان هستند.

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

زبان‌های اسمبلی

[ویرایش]

یک ترجمهٔ قابل خوانش‌تر از زبان ماشین، که زبان اسمبلی نامیده می‌شود، از کدهای حافظه‌ای برای ارجاع به دستورالعمل‌های کد ماشین به جای استفادهٔ مستقیم از مقادیر عددی دستورالعمل‌ها، بهره می‌برد. به عنوان مثال، در پردازندهٔ Zilog Z80، کد ماشین ۰۰۰۰۰۱۰۱ که باعث می‌شود CPU رجیستر پردازندهٔ B را یک واحد کاهش دهد، در زبان اسمبلی به صورت DEC B نشان داده می‌شود.

مثال

[ویرایش]

مجموعه دستورالعمل MIPS، یک مثال خاص برای یک زبان ماشین که دستورالعمل‌های آن همواره ۳۲ بیتی هستند، فراهم می‌کند. نوع کلی دستورالعمل توسط آپ‌فیلد که ۶ بیت با ارزش است، داده می‌شد. دستورالعمل‌های نوع J (پرش) و نوع I (صریح) با op مشخص می‌شوند. دستورالعمل‌های نوع R (رجیستر) شامل یک بخش اضافی funct برای تعیین دقیق عملیات هستند. بخش‌های استفاده‌شده در این انواع به صورت زیر هستند:

 6 5 5 5 5 6 bits
[op  | rs | rt | rd |shamt| funct] R-type
[op  | rs | rt | address/immediate] I-type
[op  | target address] J-type

rs ،rt و rd عملوندهای رجیستر را نشان می‌دهند، shamt یک مقدار شیفت را می‌دهد و بخش‌های address یا immediate مستقیماً حاوی یک عملوند هستند.

به عنوان مثال، جمع‌کردن رجیسترهای ۱ و ۲ و قراردادن حاصل در رجیستر ۶ به این صورت کدگذاری می‌شود:

[op  | rs | rt | rd |shamt| funct]
 0 1 2 6 0 32 decimal
 000000 00001 00010 00110 00000 100000 binary

بارگذاری یک مقدار در رجیستر ۸ که از خانهٔ حافظهٔ ۶۸ خانه بعد از خانهٔ ذکرشده در رجیستر ۳ گرفته شده‌است:

[op  | rs | rt | address/immediate]
 35 3 8 68 decimal
 100011 00011 01000 00000 00001 000100 binary

پرش به آدرس ۱۰۲۴:

[op  | target address]
 2 1024 decimal
 000010 00000 00000 00000 10000 000000 binary

رابطه برای میکرو کد

[ویرایش]

در برخی معماری‌های رایانه، کد ماشین توسط یک لایهٔ اصلی‌تر و پایه‌ای تر از برنامه‌ها که زیربرنامه‌ها نامیده می‌شوند، پیاده‌سازی می‌شود و یک رابط زبان ماشین رایج در امتداد یک خط یا خانواده از مدل‌های مختلف از رایانه با جریان داده‌های گستردهٔ متفاوت فراهم می‌کند. این کار انجام شده‌است تا انتقال برنامه‌های زبان ماشین بین مدل‌های مختلف را تسهیل کند. یک مثال از این استفاده، خانوادهٔ System/360 رایانه‌های IBM و جایگزین‌های آن‌هاست. با وجود مسیر جریان داده به پهنای ۸ تا ۶۴ بیت و بالاتر، آن‌ها یک معماری رایج در سطح زبان ماشین را در طول کل خط ارائه می‌کنند.

استفاده از یک لایهٔ میکرو کد برای پیاده‌سازی یک کپی‌کننده، رایانه را قادر می‌سازد تا معماری یک رایانه کاملاً متفاوت را ارائه کند. خط System/360 از این استفاده کرده‌است تا امکان انتقال برنامه‌ها از ماشین‌های IBM قبلی به خانوادهٔ جدید رایانه‌ها مثلاً یک کپی‌کنندهٔ IBM 1401/1440/1460 روی مدل 40 IBM S/۳۶۰ را ایجاد کند.

رابطه برای بایت‌کد

[ویرایش]

کد ماشینی نباید با «بایت‌کد» (یا عبارت قدیمی‌تر p-code) که توسط یک ترجمه‌کننده اجرا می‌شود یا برای اجرای سریع‌تر، خودش به زبان ماشین کامپایل می‌شود (به شکل مستقیم)، اشتباه شود. کد ماشین و کد اسمبلی هنگام ارجاع به بخش‌های وابسته به پلتفرمِ ویژگی‌ها یا کتاب‌خانه‌های زبان، بعضی اوقات کد محلی نامیده می‌شود.

ذخیره‌سازی در حافظه

[ویرایش]

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

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

قابلیت خوانش توسط انسان‌ها

[ویرایش]

گفته شده‌است که کد ماشین آن‌قدر غیرقابل خوانش است که دفتر کپی‌رایت ایالات متحده نمی‌تواند بفهمد که یک برنامهٔ کدگذاری‌شدهٔ خاص، کار اصلی نویسندگانش است یا خیر! (به دلیل پیچیدگی بسیار زیاد)؛ با این حال، دفتر کپی‌رایت ایالات متحده، اجازهٔ ثبت کپی‌رایت برنامه‌های رایانه‌ای را می‌دهد.

داگلاس هاف‌استادتر، کد ماشین را با کد ژنتیک مقایسه می‌کند: «نگاه‌کردن به یک برنامهٔ نوشته‌شده به زبان ماشین به شکل مبهمی قابل مقایسه با نگاه‌کردن اتم به اتم به یک مولکول DNA است».

جستارهای وابسته

[ویرایش]

منابع

[ویرایش]
    1. Such as many versions of BASIC, especially early ones, as well as Smalltalk, MATLAB, Perl, Python, Ruby and other special purpose or scripting languages.
  1. Bradley Kjell; kjell at ieee dot org. "Immediate Operand".
  2. "Managed, Unmanaged, Native: What Kind of Code Is This?". developer.com. Retrieved 2008-09-02.
  3. Pamela Samuelson (سپتامبر ۱۹۸۴). "CONTU Revisited: The Case against Copyright Protection for Computer Programs in Machine-Readable Form". 1984 (4). Duke Law Journal: 663–769. JSTOR 1372418.
  4. "Copyright Registration for Computer Programs" (PDF). US Copyright Office. August 2008. Retrieved February 23, 2014.
  5. D. Hofstadter (1980). "Gödel, Escher, Bach: An Eternal Golden Braid": 290.

جستارهای وابسته

[ویرایش]
  • Hennessy, John L.; Patterson, David A. Computer Organization and Design. The Hardware/Software Interface. Morgan Kaufmann Publishers. ISBN 1-55860-281-X.
  • Tanenbaum, Andrew S. (1990). Structured Computer Organization. Prentice Hall. ISBN 0-13-020435-8.
  • Brookshear, J. Glenn (2009). Computer Science: An Overview. Addison Wesley. ISBN 0-321-38701-5.