کد خودتغییردهنده

از ویکی‌پدیا، دانشنامهٔ آزاد
پرش به ناوبری پرش به جستجو

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

این روش غالباً برای استفاده مشروط از کد تست / اشکال زدایی کد بدون نیاز به هزینه اضافی محاسباتی برای هر چرخه ورودی / خروجی استفاده می‌شود.

تغییرات ممکن است انجام شود:

  • فقط در طی راه اندازی اولیه - براساس پارامترهای ورودی است (زمانی که فرایند بیشتر به عنوان پیکربندی نرم‌افزار توصیف می شود و در اصطلاحات سخت‌افزار، به تنظیم کردن jumperها برای صفحات مدار چاپی تقریباً مشابه است). تغییر اشاره گرهای ورودی برنامه یک روش غیر مستقیم معادل خود تغییر دهندگی است، اما نیاز به وجود یک یا بیشتر مسیرهای دستورالعملی جایگزین دارد که افزایش حجم برنامه را شاهد خواهیم بود.
  • در طول اجرا ("on-the-fly") - بر اساس شرایط خاص برنامه است که در طی اجرای رسیده‌است.

در حالت دیگر، تغییرات ممکن است به‌طور مستقیم خودشان به دستورالعمل‌های کد ماشین اعمال بشوند، با پوشاندن یا جایگزینی دستورالعمل‌های جدید بر روی دستورالعمل‌های در حال حاضر (به عنوان مثال: تغییر مقایسه و branch به branch بدون شرط یا " NOP ") انجام می‌شود.

در مجموعه دستورالعمل IBM / 360 و Z / Architecture دستور EXECUTE (EX) بطور منطقی بایت دوم دستورالعمل هدف خود را با ۸ بیت کم ارزش ثبات ۱، قرار می‌دهد. این اثر خود تغییر دهندگی را نسان می‌دهد، اگر چه دستورالعمل واقعی در حافظه تغییر نمی‌کند.

کاربرد در زبان‌های سطح پایین و سطح بالا[ویرایش]

خود-تغییر دهندگی را می‌توان به روش‌های مختلفی بسته به زبان برنامه‌نویسی و پشتیبانی آن از اشاره گرها و / یا دسترسی به کامپایلر پویا یا موتورهای مترجم انجام داد:

  • پوشاندن دستورالعمل‌های موجود (یا بخشی از دستورالعمل‌هایی مانند opcode, register, flags یا آدرس) یا
  • ایجاد مستقیم دستورالعمل‌های کامل یا توالی دستورالعمل‌ها در حافظه
  • ایجاد یا تغییر عبارات کد منبع که با یک مینی کامپایل یا یک تفسیر یا ترجمه پویا صورت می‌گیرد (نگاه کنید به eval)
  • ایجاد یک برنامه کامل به صورت پویا و سپس اجرای آن

زبان اسمبلی[ویرایش]

کد خود تغییر دهندگی برای پیاده‌سازی در هنگام استفاده از زبان اسمبلی بسیار ساده است. دستورالعمل‌ها می‌توانند به‌طور پویا در حافظه ایجاد شوند (یا در موارد دیگر بر روی کدهای موجود در ذخیره‌سازی برنامه‌های محافظت نشده)، در توالی معادل با آنهایی که کامپایلر استاندارد ممکن است به عنوان کد هدف تولید کند. با پردازنده‌های مدرن، ممکن است عوارض جانبی ناخواسته بر روی حافظه نهان CPU وجود داشته باشد که باید در نظر گرفته شود. این روش اغلب برای آزمایش شرایط «اولین بار» مورد استفاده قرار می‌گیرد، همان‌طور که در این نمونه زبان اسمبلی مناسب IBM / 360 توضیح داده شده‌است. این روش با استفاده از پوشش دستور برای کاهش طول مسیر دستورالعمل به N × 1) -1) که در آن N که تعداد رکوردها در فایل است (-۱ سرباری برای انجام پوشش است)، استفاده می‌شود.

SUBRTN NOP OPENED      FIRST TIME HERE?
 * The NOP is x'4700'<Address_of_opened>
        OI    SUBRTN+1,X'F0'  YES, CHANGE NOP TO UNCONDITIONAL BRANCH (47F0...)
        OPEN   INPUT               AND  OPEN THE INPUT FILE SINCE IT'S THE FIRST TIME THRU
 OPENED GET    INPUT        NORMAL PROCESSING RESUMES HERE
       ...

کد جایگزین ممکن است شامل هر بار آزمودن «پرچم» باشد. دستور پرش بدون قید و شرط کمی سریعتر از دستور مقایسه ای است، و همچنین باعث کاهش طول مسیر کلی می‌شود. در سیستم عامل‌های بعدی برای برنامه‌هایی که در حافظه محافظت شده قرار دارند، این تکنیک نمی‌تواند مورد استفاده قرار گیرد و به جای آن از تغییر اشاره گر به زیر برنامه استفاده خواهد شد. اشاره گر در حافظه پویا قرار دارد و می‌تواند پس از گذراندن اولین مرحله برای دور زدن OPEN تغییر یابد (ابتدا باید یک اشاره گر به جای یک پرش مستقیم بارگذاری شود و به زیر برنامه ارتباط پیدا کند که N دستورالعمل را به طول مسیر اضافه می‌کند - اما یک کاهش متناظر با N برای پرش بدون قید و شرط وجود دارد که دیگر لازم نیست).

در زیر نمونه ای از زبان اسمبلی Zilog Z80 است. این کد ثبات B را از مقدار ۰ به ۵ افزایش می‌دهد. دستور مقایسه ای "CP" در هر حلقه تغییر می‌کند.

;====================================================================  ==
ORG 0H
CALL FUNC00
HALT
;====================================================================  ==
FUNC00:
LD A,6
LD HL,label01+1
LD B,(HL)
label00:
INC B
LD (HL),B
label01:
CP $0
JP NZ,label00
RET
;====================================================================  ==

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

زبانهای سطح بالا[ویرایش]

برخی از زبانهای کامپایل شده به صراحت اجازه می‌دهند کد خود را تغییر دهید. به عنوان مثال، فعل ALTER در COBOL ممکن است به عنوان دستور پرشی اجرا شود که در حین اجرای برنامه اصلاح می‌شود.[۱] یکی از روش‌های برنامه‌ریزی دسته ای استفاده از کد خودمحور است.[۲] Clipper و SPITBOL نیز امکانات را برای تغییر صریح خود فراهم می‌کنند.کامپایلر Algol در سیستم‌های B6700 یک رابط را برای سیستم عامل ارائه داد که در آن اجرای کد می‌تواند یک رشته متن یا یک فایل دیسک نام گذاری شده را به کامپایلر Algol منتقل کند و سپس قادر به فراخوانی نسخه جدیدی از یک روش بود.

با زبان‌های تفسیر شده، "کد ماشین" متن منبع است و ممکن است حساس به ویرایش بر روی on-the-fly باشد: در SNOBOL، جملات مرجع که اجرا می‌شوند، عناصر یک آرایه متنی هستند. زبان‌های دیگر مانند Perl و Python به برنامه‌ها برای ایجاد کد جدید در زمان اجرا و اجرای آن با استفاده از یک تابع eval، اجازه می‌دهند، اما اجازه تغییر در کد فعلی قابل را نمی‌دهند. تغییر غلط (حتی اگر هر کدام از ماشین‌ها واقعاً رونویسی شوند) با تغییر اشاره گرهای تابع به دست می‌آید، همان‌طور که در این مثال جاوااسکریپت داریم:

    var f = function (x) {return x + 1};

    // assign a new definition to f:
    f = new Function('x', 'return x + 2');

ماکروهای Lisp همچنین اجازه می‌دهند که کد در زمان اجرا تولید شود بدون آن که به تجزیه رشته حاوی متن برنامه نیاز باشد.

زبان برنامه‌نویسی Push یک سیستم برنامه‌نویسی ژنتیکی است که به‌طور ویژه برای ایجاد برنامه‌های خود تغییر دهنده طراحی شده‌است. در حالی که یک زبان سطح بالا نیست، زبان سطح پایینی هم در حد زبان اسمبلی نیست.[۳]

تغییر مرکب[ویرایش]

قبل از ظهور تعدادی از ویندوزها، سیستم‌های command-line ممکن است یک سیستم منو که شامل اصلاح یک اسکریپت فرمان اجرایی است را ارائه دهند. فرض کنید یک فایل اسکریپت DOS (یا "دسته ای") Menu.bat شامل موارد زیر باشد:

StartAfresh <-A خط با کولون شروع می شود
برچسب. ShowMenu.exe

پس از شروع Menu.bat از خط فرمان، دستور ShowMenu یک منو بر روی صفحه با اطلاعات کمکی ممکن، استفاده از مثال‌ها و… را ارائه می‌دهد. در نهایت کاربر یک انتخاب را انجام می‌دهد که برای اجرا نیاز به یک فرمان somename دارد: ShowMenu پس از بازنویسی فایل Menu.bat که حاوی دستورهای زیر است، وجود دارد

StartAfresh
 ShowMenu.exe
 CALL C: \ دستورها \ somename بوت
 GOTO StartAfresh

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

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

جداول کنترل[ویرایش]

مترجم‌های جدول کنترل می‌توانند در یک معنا "خود تغییر داده شده" با مقادیر داده استخراج شده از ورودی‌های جدول (به جای اینکه به‌طور خاص دسته‌بندی شده در جمله‌های شرطی به فرم "IF inputx = 'yyy'") در نظر گرفته شود.

برنامه‌های کانال[ویرایش]

بعضی از روش‌های دسترسی IBM به‌طور سنتی برنامه‌های کانال خود تغییر دهنده را استفاده می‌کنند، جایی که یک مقدار مانند آدرس دیسک، در یک ناحیه اشاره شده توسط برنامه کانال، که از طریق یک فرمان کانال بعدی برای دسترسی به دیسک استفاده می‌شود، خوانده می‌شود.

تاریخ[ویرایش]

IBM SSEC در ماه ژانویه سال ۱۹۴۸ نشان داد که توانایی تغییر دستورهایش را دارد یا در غیر این صورت با آنها دقیقاً مانند داده رفتار کند. با این حال، این قابلیت به ندرت در عمل کاربرد دارد.[۴] در اولین روزهای رایانه‌ها، کد خود تغییر دهنده اغلب برای کاهش استفاده از حافظه محدود یا بهبود عملکرد یا به هر دو دلیل استفاده می‌شد. همچنین گاهی اوقات برای پیاده‌سازی توابع زیر برنامه ای استفاده می‌شد و هنگامی برمی‌گشت که مجموعه دستورها تنها پرشی ساده یا رد شدن از دستورها برای تغییر دادن کنترل جریان، باشند. این کاربرد هنوز در برخی معماری معین ultra-RISC مناسب است، حداقل از لحاظ نظری؛ به عنوان مثال معماری one instruction set computer نیز از کد خود تغییر دهنده برای پیاده‌سازی توابع زیر برنامه، استفاده می‌کرد.

کاربرد[ویرایش]

کد خود تغییر دهنده را می‌توان برای اهداف مختلف استفاده کرد:

  • بهینه‌سازی نیمه اتوماتیک یک حلقه وابستگی حالت.
  • تولید کد زمان اجرا یا تخصص یک الگوریتم در زمان اجرا یا زمان بارگذاری (که محبوب است، به عنوان مثال در حوزه گرافیک در زمان واقعی) مانند یک ابزار مرتب‌سازی کلی - آماده‌سازی کد برای انجام مقایسه کلیدی که در یک فراخوانی خاص شرح داده شده‌است.
  • تغییر حالت فشرده یک شی، یا شبیه‌سازی ساخت و ساز در سطح بالا از کلوژرها.
  • پچ کردن آدرس زیر برنامه (اشاره گر) صدا زده شده، معمولاً به عنوان زمان بارگذاری یا مقداردهی اولیه کتابخانه‌های پویا انجام می‌شود، یا در هر فراخوانی، پچ کردن مرجع‌های داخلی زیر برنامه به پارامترهای آن، برای استفاده از آدرس‌های واقعی آنها. (به عبارت دیگر خود اصلاحی مستقیم ").
  • سیستم‌های محاسباتی تکاملی مانند برنامه‌نویسی ژنتیک.
  • پنهان کردن کد برای جلوگیری از مهندسی معکوس (با استفاده از disassembler یا debugger) یا فرار از تشخیص توسط نرم‌افزار اسکن ویروس / جاسوسی و مانند آن.
  • پر کردن ۱۰۰٪ حافظه (در بعضی از معماری‌ها) با یک الگوی نورد از تکرار opcodes، برای پاک کردن تمام برنامه‌ها و داده‌ها، یا سوزاندن سخت‌افزار.
  • فشرده سازی کد را باید در زمان اجرا فشرده و اجرا کرد، مثلاً زمانی که حافظه یا فضای دیسک محدود است.
  • برخی از مجموعه‌های دستور بسیار محدود هیچ گزینه ای ندارند، اما از کد خود تغییر دهنده برای انجام وظایف خاص استفاده می‌کنند. به عنوان مثال، یک مجموعه دستورالعمل کامپیوتری (OISC) که تنها از دستور "تفریق" و "branch-if-negative" استفاده می‌کند نمی‌تواند یک کپی غیر مستقیم (چیزی شبیه معادل "a = ** b" در C زبان) بدون استفاده از کد خود تغییر دهنده را انجام دهد.
  • راه اندازی. میکرو رایانه‌های اولیه اغلب از کد خود تعییر دهنده در بوت لودرها استفاده می‌کردند. از آنجا که بوت لودر از طریق قطعه جلو در هر دکمه پاور کلید شده بود، مهم نبود که بوت لودر خود را تغییر دهد. با این حال، حتی امروزه بسیاری از bootstrap loaderها خود را جایگزین می‌کنند و تعدادی از آنها حتی خود تغییر دهنده نیز هستند.
  • تغییر دستورها برای تحمل خطا.[۵]

بهینه‌سازی یک حلقه وابستگی حالت[ویرایش]

مثالd از Pseudocode :

repeat N times {
 if STATE is 1
 increase A by one
 else
 decrease A by one
 do something with A
}

کد خود تغییر دهنده، در این مورد، به سادگی موضوع بازنویسی حلقه مانند این است:

 repeat N times {
  ''increase'' A by one
  do something with A
  when STATE has to switch {
  replace the opcode "increase" above with the opcode to decrease, or vice versa
  }
  }

توجه داشته باشید که تعویض دو حالتی OPCode به راحتی می‌تواند به عنوان "xor var" در آدرس با مقدار" (opcodeOf (Inc) xor opcodeOf (dec " نوشته شود.

انتخاب این راه حل باید به مقدار N و فرکانس تغییر حالت بستگی داشته باشد.

تخصص[ویرایش]

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

استفاده به عنوان پوشش[ویرایش]

کد خود تغییر دهنده برای مخفی کردن کپی حفاظت دستورها در برنامه‌های مبتنی بر دیسک ۱۹۸۰ برای سیستم عامل‌هایی مانند IBM PC و Apple II استفاده شده‌است. به عنوان مثال، در IBM PC (یا سازگار)، دستور دستیابی درایو فلاپی دیسک که int 0x13 می‌باشد در تصویر برنامه اجرایی نمایش داده نخواهد شد، اما بعد از اجرای برنامه، در تصویر حافظه اجرایی نوشته می‌شود.

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

سیستم یادگیری ماشین خود ارجاعی[ویرایش]

سیستم‌های یادگیری ماشین سنتی دارای الگوریتم یادگیری ثابت و پیش برنامه‌ریزی شده برای تنظیم پارامترهایشان می باشند. با این حال، از دهه ۱۹۸۰، Jürgen Schmidhuber چند سیستم خود تغییر دهنده را با توانایی تغییر الگوریتم یادگیری خود، منتشر کرده‌است. این سیستم‌ها از خطر خودکفائی فاجعه آمیز جلوگیری می‌کنند، از این طریق اطمینان حاصل می‌کنند که خود تغییرات تنها در صورتی قابل قبول خواهند بود که با توجه به آمادگی کاربر، خطا یا عملکرد پاداش مفید باشد.[۶]

سیستم‌های عامل[ویرایش]

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

به عنوان نتیجهٔ مشکلاتی که می‌تواند توسط این سوء استفاده‌ها ایجاد شود، یک ویژگی OS به نام W ^ X (برای "نوشتن xor execute") توسعه داده شده‌است که به برنامه اجازه نمی‌دهد که هیچ صفحهٔ حافظه را هم قابل خواندن و هم قابل اجرا کند. بعضی از سیستم‌ها از یک صفحه که قابل نوشتن است جلوگیری می‌کنند تا به حالت قابل اجرا درآید، حتی اگر اجازه نوشتن حذف شود. سیستم‌های دیگر " درهای عقب " را ارائه می‌دهند که اجازه می‌دهد چندین صفحه بندی از یک صفحهٔ حافظه دارای مجوزهای متفاوت باشد. یک راه نسبتاً قابل حمل برای دور زدن W ^ X این است که یک پرونده با تمام مجوزها ایجاد کنید، سپس فایل را به حافظه دو بار نگاشت کنید. در لینوکس، می‌توان از یک پرچم حافظه مشترک SysV ناموجود استفاده کرد تا به حافظه مشترک قابل اجرا بدون نیاز به ایجاد یک فایل رسید. [نیازمند منبع] صرفنظر از موارد فوق، در سطح فراگیر، برنامه‌ها همچنان می‌توانند رفتار خود را با تغییر داده‌های ذخیره شده در جاهای دیگر تغییر دهند یا از طریق استفاده از پلی مورفیسم.

تعامل حافظهٔ نهان و کد خود تغییر دهنده[ویرایش]

در معماری‌های بدون داده‌های مرتبط و حافظه پنهان دستورالعمل (برخی از هسته‌های ARM و MIPS)، هماهنگ سازی حافظه پنهان باید به وضوح توسط کد تغییر دهنده انجام شود (حافظه پنهان دادهٔ تخلیه و حافظهٔ پنهان دستورالعمل بی‌اعتبار برای محدوده حافظه تغییر داده شده).

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

مسئله عدم اعتبار حافظهٔ پنهان در پردازنده‌های مدرن معمولاً بدین معنی است که کد خود تغییر دهنده هنوز هم سریع تر خواهد بود تنها زمانی که تغییر به ندرت رخ می‌دهد، مانند تعویض حالت درون حلقه داخلی. [نیازمند منبع] بیشتر پردازنده‌های مدرن قبل از اجرای آن، کد ماشین را بارگذاری می‌کنند، بدین معنی که اگر دستورالعملی که خیلی نزدیک اشارهگر دستورالعمل است، تغییر داده شده باشد، پردازنده متوجه نمی‌شود، بلکه کد را قبل از اینکه آن را تغییر دهد اجرا می‌کند. صف ورودی پیشفرض (PIQ) را ببینید. پردازنده‌های PC باید به کد خود تغییر دهنده را به درستی برای دلایل سازگاری عقبی انجام دهند، اما در انجام این کار بسیار دور از حالت بهینه اند.[نیازمند منبع]

هسته Synthesis Massalin[ویرایش]

سنتز هسته ارائه شده در دکتری پایان‌نامه[۷] هنری Massalin، یک کرنل Unix کوچک است که رویکرد ساختار یافته یا حتی شی گرا را به کد خود تغییر می‌دهد، جایی که کد برای تک تک quajectsها مانند filehandles ایجاد می‌شود؛ تولید کد برای کارهای خاص اجازه می‌دهد که هسته Synthesis به (به عنوان مترجم JIT ممکن است) تعدادی از بهینه‌سازی‌ها را اعمال کند مانند حذف ثابت ثابت یا مشترک زیر بیان.

هسته Synthesis بسیار سریع بود، اما به‌طور کامل در اسمبلی نوشته شده بود. عدم وجود قابلیت حمل و نقل مانع از ایده‌های بهینه‌سازی Massalin از هر هسته تولیدی شده‌است. با این حال، ساختار تکنیک‌ها نشان می‌دهد که آنها می‌توانند با یک زبان سطح بالاتری پیاده‌سازی شوند، اگرچه پیچیده‌تر از زبان‌های سطح متوسط موجود هستند. چنین زبان و کامپایلر می‌تواند اجازهٔ توسعه سریعتر سیستم عامل‌ها و برنامه‌های کاربردی را دهد.

پل هابرلی و بروس کارش با «حاشیه سازی» کد خود تغییر دهنده و بهینه‌سازی به‌طور کلی به نفع کاهش هزینه‌های توسعه مخالفت کردند.[۸]

مزایا[ویرایش]

  • می‌توان راه‌های سریع برای اجرای برنامه ایجاد کرد و برخی از شاخه‌های شرطی تکراری دیگر را کاهش داد.
  • کد خود تغییر دهنده می‌تواند کارایی الگوریتمی را بهبود بخشد.

معایب[ویرایش]

کد خودتغییر داده شده برای خواندن و نگهداری سخت‌تر است، زیرا دستورالعمل‌ها در فهرست برنامهٔ منبع، لزوماً دستورالعمل‌هایی نیستند که اجرا می‌شوند. خود تغییری که شامل تعویض اشاره گرهای عملکرد است ممکن است به صورت معکوس نباشد، اگر روشن باشد که نام توابع نامیده می‌شود، متغیرهایی برای توابع شناسایی شده‌است.

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

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

در برخی از محیط‌ها، کد خود تغییر دهنده نمی‌تواند مورد استفاده قرار گیرد، مانند موارد زیر:

  • نرم‌افزاری کاربردی که تحت یک سیستم عامل اجرا می‌شود با امنیت سخت‌افزار W ^ X نمی‌تواند دستورالعمل‌هایی را در صفحات مجاز به نوشتن. تنها سیستم عامل مجاز به هر دو دستورالعمل نوشتن به حافظه و بعد از آن دستورالعمل‌ها را اجرا کند.
  • بسیاری از میکروکنترلرهای معماری هاروارد نمی‌توانند دستورالعملهایی را در حافظه خواندن و نوشتن اجرا کنند، اما فقط دستورالعملهایی را در حافظه ای که نمی‌توان آن را نوشت، ROM یا حافظه فلشهای غیر خودپرداز.
  • یک برنامه چند رشته‌ای ممکن است چندین رشته را اجرا کند که قسمت مشابهی از کد خود تغییر دهنده را اجرا کرده باشد، احتمالاً به خطاهای محاسباتی و خرابی‌های برنامه منجر می‌شود.

جستارهای وابسته[ویرایش]

  • کارایی الگوریتمیک
  • بیانیه ایوال
  • IBM 1130 (مثال)
  • کامپایل آنی: این روش اغلب می‌تواند بسیاری از مزایای کد خود تغییر دهنده را (به جز اندازهٔ حافظه) بدون هیچ گونه معایبی به کاربر بدهد.
  • حذف کد پویا مرده
  • Homoiconicity
  • PCASTL
  • کوین (محاسبات)
  • خود تکرار
  • بازتاب (علم کامپیوتر)
  • پچ میمون: یک اصلاح برای کد اجرا است که کد منبع اصلی برنامه را تحت تأثیر قرار نمی‌دهد
  • برنامه‌نویسی توسعه پذیر: یک پارادایم برنامه‌نویسی که در آن یک زبان برنامه‌نویسی می‌تواند نحو خود را تغییر دهد
  • ویروس کامپیوتری
  • خود میزبانی

منابع[ویرایش]

  1. "The ALTER Statement". COBOL Language Reference. Micro Focus.
  2. لارس فسدال، فایل شخصی خود را تغییر دهید
  3. "Push, PushGP, and Pushpop".
  4. Bashe, C. J.; Buchholz, W.; Hawkins, G. V.; Ingram, J. J.; Rochester, N. (September 1981). "The Architecture of IBM's Early Computers" (PDF). 25 (5): 363–376. CiteSeerX 10.1.1.93.8952. doi:10.1147/rd.255.0363. The SSEC was the first operating computer capable of treating its own stored instructions exactly like data, modifying them, and acting on the result.
  5. "On Self-Modifying Code and the Space Shuttle OS – Carlos Enrique Ortiz".
  6. Jürgen Schmidhuber 's Publications on Self - Modifying Code برای سیستم‌های یادگیری ماشین‌های خود ارجاعی
  7. پال، کلتن؛ ماسالین، هنری؛ یونایدیس جان (1992). سنتز: اجرای کارآمد خدمات سیستم عامل اصلی (PDF) (Ph.D. thesis). نیویورک، نیویورک، ایالات متحده آمریکا: گروه علوم کامپیوتر، دانشگاه کلمبیا. UMI سفارش شماره GAX92-32050. آرشیو شده (PDF) از اصل در 2017-07-05 . بازیابی شده 2012-04-25 . بیایید خلاصه (2008-02-20).[۱]
  8. هابرلی، پل؛ کارش، بروس (1994-02-03). "یو نوبی بوچونی - زمینه برنامه نویسی آینده نگر". Grafica Obscura . آرشیو شده از اصل در 2017-07-04 . بازیابی شده از 2017-07-04.

پیوند به بیرون[ویرایش]