自己書き換えコードとは
自己書き換えコードとは、実行時に自分自身の命令を変更するプログラムコードを指します。この技術は、主に
アセンブリ言語で実装されることが多く、CPUのキャッシュの特性を考慮することが重要です。また、高級言語の中にもSNOBOL4やLISPのように、この機能を組み込んでいるものもあります。さらに、
COBOLには特定の用途に使えるALTER命令が存在していました。
コンパイラでこの手法を実装することは難しいものの、CLIPPERやSPITBOLといった言語では試みられています。バッチスクリプトでは自己書き換えコードが頻繁に利用される他、
再構成可能コンピューティングもこの概念に近いものがあります。これは、
ソフトウェアと
ハードウェアの境界があいまいになることを意味しています。
自己書き換えコードの利用目的
自己書き換えコードはさまざまな目的で使用されます。以下に主な用途を挙げてみましょう。
1.
状態依存ループの最適化: 特定の状態に基づいてループの動作を効率化するために、ループの内容を変更することができます。
2.
実行時コード生成: リアルタイムグラフィックスなどの分野で、実行時またはロード時に
アルゴリズムを特化させるために用いられます。
3.
オブジェクトのインライン変化:
オブジェクトや
クロージャの状態を動的に変更するために活用されます。
4.
[サブルーチン]]呼び出しのパッチ: ダイナミックリンク[[ライブラリ]を呼び出す際に、アドレスの変更を行うことがあります。この目的では自己書き換えコードを使用することがあります。
5.
遺伝的プログラミング: 複雑な
アルゴリズムを進化させるために自己書き換えを利用したりします。
6.
コード秘密保持:
リバースエンジニアリングを防ぐために、自らのコードを隠す目的で使用されます。
7.
コンピュータウイルス対策:
アンチウイルスソフトウェアから逃れるために自己書き換えコードを用いるウイルスもあります。
コードの圧縮やメモリに総合的な制約がある場合にも、自己書き換えコードを使用することがあります。特に命令セットが非常に限られる状況では、この手法が求められることもあります。
Linuxカーネルのように、環境ごとに自己書き換えを行うことでコードの最適化を図っている場合もあり、その実装は環境ごとに異なります。
状態依存ループ最適化の例
自己書き換えコードを使用すると、特定の状態に応じた動作を効率的に書き直すことが可能です。以下に具体的な例を示します。
```plaintext
repeat N 回 {
if STATE == 1
A = A + 1
else
A = A - 1
A に関して処理をする
}
```
上記のようなループがある場合、自己書き換えコードを適用すると、次のように書き換えることができます。
```plaintext
repeat N 回 {
A = A + 1
A に関して処理をする
}
when STATEが変化した時 {
上記の + 命令を -命令に書き換える。
}
```
この手法を採用するかどうかは、ループ回数(N)が大きいか、状態の変化が頻繁かどうかによります。
自己書き換えコードへの見解
自己書き換えコードには賛否があります。理解しにくく、保守が難しくなるため、他に有効な選択肢があれば避けるべきだという意見も多くあります。また、自己書き換えは単なる実行時の操作であり、コーディング時に行われることを再現するだけではないかとも批判されます。
初期のコンピュータでは、メモリ空間を効率よく使用するためにこの技術が採用されてきました。将来的な高度な
人工知能は自己書き換え機能を持つべきだと考える人もいます。
偽装用としての自己書き換えコード
1980年代のゲームでは、コピープロテクションのために自己書き換えコードが利用されました。この技術はウイルスなどにおいても採用され、自身の存在を隠したり、ポリモルフィック(多様性のある)コードを生成することで、自己変異することが可能です。
自己書き換えの機械学習への応用
Jürgen Schmidhuberの研究では、自己書き換え可能な
アルゴリズムを持つ機械学習システムが発表されています。ユーザーが指定するフィットネス関数を使用し、有効な書き換えのみを生かす仕組みです。
セキュリティ上のリスクから、多くの
オペレーティングシステムでは自己書き換えコードが禁止されています。悪意のある第三者がコードを書き換える危険性があるためです。特に
OpenBSDのようなシステムは、