موضوع مقاله: کد ماشین | مخاطب: عمومی | لحن: دانشنامه‌ای | ساختار: عنوان، مقدمه، 3 بخش، جمع‌بندی | مقاله: | # کد ماشین | مقدمه: هر دستورالعمل یک کار خاص را انجام می‌دهد، به عنوان مثال: یک بارگذاری، یک پرش یا یک عملیات ریاضیاتی روی یک واحد از داده‌ها در یک رجیستر CPU یا حافظه. | ## بخش 1: کد ماشین | هر برنامه‌ای که توسط CPU اجرا می‌شود، از مجموعه‌ای از دستورالعمل‌ها تشکیل شده‌است. کد ماشین عددی (منظور کد اسمبلی نیست) ممکن است به عنوان پایین‌ترین سطح نمایش یک برنامهٔ رایانه‌ای کامپایل‌شده، (یا سرهم‌شده) یا به عنوان یک زبان برنامه‌نویسی وابسته به سخت‌افزار اولیه در نظر گرفته شود. علی‌رغم اینکه مستقیماً امکان نوشتن برنامه‌ها به صورت کد ماشین عددی وجود دارد، مدیریت‌کردن بیت‌های تک و محاسبهٔ آدرس‌های عددی و ثابت‌ها به صورت دستی، خسته‌کننده و خطاپذیر است. به این دلیل، کد ماشین تقریباً هیچگاه برای نوشتن برنامه‌ها مورد استفاده قرار نمی‌گیرد. امروزه تقریباً تمام برنامه‌های عملی با زبان‌های سطح بالاتر یا زبان اسمبلی نوشته می‌شوند. سپس کد منبع با ابزاری مانند کامپایلرها، اسمبلرها و ارتباط‌دهنده‌ها با جنبهٔ مهم برنامه‌های ترجمه‌شده، که به کد ماشین ترجمه نشده‌اند، به کد ماشین قابل اجرا ترجمه می‌شود. با این حال، خود ترجمه‌کننده (که ممکن است به عنوان یک اجراکننده یا پردازش‌کننده دیده شود و دستورالعمل‌های کد منبع را انجام می‌دهد)، معمولاً شامل کد ماشین که مستقیماً قابل اجرا باشد (که منشأ گرفته از کد منبع اسمبلی یا زبان سطح بالاست)، است. دستورالعمل‌های کد ماشین هر پردازنده یا خانوادهٔ پردازنده، مجموعهٔ دستورالعمل کد ماشین مربوط به خود را دارد. دستورالعمل‌ها، مولد بیت‌هایی می‌باشند که توسط طراحی فیزیکی، متناظر با دستورها مختلفی برای ماشین هستند؛ بنابراین، مجموعهٔ دستورالعمل، مخصوص به دسته‌ای از پردازنده‌هاست که (تقریباً) از معماری مشابهی بهره می‌برند. طراحی‌های جانشین یا پردازندهٔ فرعی اغلب شامل تمام دستورالعمل‌های یک دستور پیشین هستند و ممکن است دستورالعمل‌های اضافی را بیافزایند. گه گاه، یک طراحی جایگزین - که مفهوم و معنی برخی کدهای دستورالعمل را تغییر خواهد داد یا قطع خواهد کرد (چون معمولاً برای اهداف جدید مورد نیاز است) - تا حدی روی سازگاری کد تأثیر می‌گذارد؛ حتی تقریباً پردازنده‌های کاملاً سازگار ممکن است برای برخی دستورالعمل‌ها رفتار کمی متفاوت نشان دهند ولی این به ندرت یک مشکل محسوب می‌شود. همچنین ممکن است سیستم‌ها در جزئیات دیگری مانند چیدمان حافظه، سیستم‌های عامل یا دستگاه‌های جانبی متفاوت باشند. از آن‌جایی که یک برنامه به شکل معمولی به چنین عواملی بستگی دارد، سیستم‌های متفاوت معمولاً یک کد ماشین اجرا نخواهند کرد، حتی وقتی نوع پردازندهٔ یکسانی استفاده شود. یک مجموعهٔ دستورالعمل کد ماشین ممکن است تمام دستورالعمل‌ها با طول یکسان را داشته باشد یا ممکن است دارای دستوالعمل‌هایی با طول متغیر باشد. | ## بخش 2: کد ماشین | شکلی که الگوها سازماندهی می‌شوند، شدیداً با معماری خاص و همچنین اغلب با نوع دستورالعمل تغییر می‌کند. بیشتر دستورالعمل‌ها یک یا بیشتر حوزهٔ آپ‌کد دارند که نوع اصلی دستورالعمل (مثلاً ریاضیاتی، منطقی، پرش و غیره) و عملیات واقعی (مانند جمع یا مقایسه) را مشخص می‌کند و سایر حوزه‌ها ممکن است نوع عملوند(ها)، مد(ها) آدرس‌دهی، آفست(ها) آدرس‌دهی، شاخص یا خود مقدار واقعی را بدهند (چنین عملوندهای ثابت گنجانده‌شده در یک دستورالعمل صریح نامیده می‌شوند). یک ماشین انباشتگر دارای یک عملوند چپ ترکیبی است که منتج به انباشتگر ضمنی برای بیشتر دستورالعمل‌های ریاضیاتی می‌شود. سایر معماری‌ها (مانند ۸۰۸۶ و خانوادهٔ x86) نسخه‌های انباشتگری از دستورالعمل‌های رایج دارند که در آن‌ها، انباشتگر توسط دستورالعمل‌های طولانی‌تر به عنوان یکی از رجیسترهای اصلی در نظر گرفته می‌شود. دستورالعمل‌های با هدف خاص نیز اغلب دارای کمبود عملوندهای صریح هستند (به عنوان مثال CPUID در معماری x86، مقادیر را در چهار رجیستر مقصد ضمنی می‌نویسد). این تمایز بین عملوندهای ضمنی و صریح، در مولدهای کد ماشین، مخصوصاً در تخصیص رجیستر و بخش‌های ردیابی محدودهٔ زنده، مهم است. یک بهینه‌ساز کد خوب می‌تواند عملوندهای ضمنی را به خوبی عملوندهای صریح - که ممکن است اجازهٔ انتشار پرتکرار، به‌هم‌آمیختن ثابت رجیسترها (یک رجیستر که حاصل یک عبارت ثابت به آن اختصاص یافته‌است با جایگزین‌کردنش با آن ثابت، آزاد می‌شود) و سایر بهبوددهی‌های کد را بدهد - را ردیابی کند. برنامه‌ها یک برنامهٔ رایانه‌ای یک دنباله از دستورالعمل‌هاست که توسط یک CPU اجرا می‌شوند. علی‌رغم اینکه پردازنده‌های ساده، دستورالعمل‌ها را یکی بعد از دیگری اجرا می‌کنند، پردازنده‌های ابرمقیاس‌پذیر قادر به اجرای چندین دستورالعمل به‌طور همزمان هستند. جریان برنامه ممکن است تحت تأثیر دستورالعمل‌های «پرش» قرار گیرد که اجرا را به جای اجرای به ترتیب، به یک دستورالعمل دیگر منتقل می‌کنند. پرش‌های شرطی بسته به شرایط در نظر گرفته می‌شوند (اجرا از یک آدرس دیگر ادامه پیدا می‌کند) یا در نظر گرفته نمی‌شوند (اجرا از دستور بعدی ادامه پیدا می‌کند). زبان‌های اسمبلی یک ترجمهٔ قابل خوانش‌تر از زبان ماشین، که زبان اسمبلی نامیده می‌شود، از کدهای حافظه‌ای برای ارجاع به دستورالعمل‌های کد ماشین به جای استفادهٔ مستقیم از مقادیر عددی دستورالعمل‌ها، بهره می‌برد. مثال مجموعه دستورالعمل MIPS، یک مثال خاص برای یک زبان ماشین که دستورالعمل‌های آن همواره ۳۲ بیتی هستند، فراهم می‌کند. دستورالعمل‌های نوع R (رجیستر) شامل یک بخش اضافی funct برای تعیین دقیق عملیات هستند. | ## بخش 3: کد ماشین | این کار انجام شده‌است تا انتقال برنامه‌های زبان ماشین بین مدل‌های مختلف را تسهیل کند. با وجود مسیر جریان داده به پهنای ۸ تا ۶۴ بیت و بالاتر، آن‌ها یک معماری رایج در سطح زبان ماشین را در طول کل خط ارائه می‌کنند. استفاده از یک لایهٔ میکرو کد برای پیاده‌سازی یک کپی‌کننده، رایانه را قادر می‌سازد تا معماری یک رایانه کاملاً متفاوت را ارائه کند. رابطه برای بایت‌کد کد ماشینی نباید با «بایت‌کد» (یا عبارت قدیمی‌تر p-code) که توسط یک ترجمه‌کننده اجرا می‌شود یا برای اجرای سریع‌تر، خودش به زبان ماشین کامپایل می‌شود (به شکل مستقیم)، اشتباه شود. کد ماشین و کد اسمبلی هنگام ارجاع به بخش‌های وابسته به پلتفرمِ ویژگی‌ها یا کتاب‌خانه‌های زبان، بعضی اوقات کد محلی نامیده می‌شود. ذخیره‌سازی در حافظه معماری هاروارد، یک معماری رایانه است که حافظهٔ آن از نظر فیزیکی و مسیرهای عبور سیگنال برای کد (دستورالعمل‌ها) و داده‌ها جداست. امروزه، بیشتر پردازنده‌ها، چنین مسیرهای عبور سیگنال جدایی را به دلایل عملکردی پیاده‌سازی می‌کنند ولی در واقع یک معماری هاروارد اصلاح‌شده را پیاده می‌کنند تا بتوانند کارهایی مانند بارگذاری یک برنامهٔ قابل اجرا از دیسک حافظه به عنوان داده و سپس اجراکردن آن را پشتیبانی کنند. معماری هاروارد با معماری ون نیومن مقایسه می‌شود که در آن داده‌ها و کدها در حافظهٔ یکسان ذخیره می‌شوند که توسط پردازنده خوانده می‌شود و به رایانه این امکان را می‌دهد تا دستورها را اجرا کند. از نقطه نظر یک پردازش، فضای کد بخشی از فضای آدرسش است که در آن، کد در حال اجرا ذخیره شده‌است. در سیستم‌های چندوظیفه‌ای، این شامل بخش کد برنامه و معمولاً کتاب‌خانه‌های اشتراکی است. در محیط چند تهدید، تهدیدهای مختلفی از یک فرایند فضای کد را با فضای داده به اشتراک می‌گذارند که سربار تعویض محتوا را به میزان چشم‌گیری در مقایسه با تعویض فرایند، کاهش می‌دهد. قابلیت خوانش توسط انسان‌ها گفته شده‌است که کد ماشین آن‌قدر غیرقابل خوانش است که دفتر کپی‌رایت ایالات متحده نمی‌تواند بفهمد که یک برنامهٔ کدگذاری‌شدهٔ خاص، کار اصلی نویسندگانش است یا خیر! (به دلیل پیچیدگی بسیار زیاد)؛ با این حال، دفتر کپی‌رایت ایالات متحده، اجازهٔ ثبت کپی‌رایت برنامه‌های رایانه‌ای را می‌دهد. | ## جمع‌بندی | داگلاس هاف‌استادتر، کد ماشین را با کد ژنتیک مقایسه می‌کند: «نگاه‌کردن به یک برنامهٔ نوشته‌شده به زبان ماشین به شکل مبهمی قابل مقایسه با نگاه‌کردن اتم به اتم به یک مولکول DNA است».