トップページ⇒tech
97コメント24KB

自分自身を書き換えるプログラム

■ このスレッドは過去ログ倉庫に格納されています
0001kimuraNGNG
ちょっと疑問に思ったことがあるので、質問させていただきます。
それは、自分自身のソースコードを書き換えるプログラムについてなのですが……

あるプログラムの n 行目に、次のような個所があり、(FOR ループによる繰り返し等で)何度も処理されるものとします。

IF T=0 THEN {処理A} ELSE {処理B}

そして、プログラムのスタート時には、T=0 なのですが、プログラムを処理していく中で、T=1 となり、T の値は、二度と 0 には、戻らないものとします。

すると、IF 〜 THEN の条件判定処理にかかるコストをなくすため、ソースコードの n 行目には、プログラムの設計時には、単に、

{処理A}

と、書いておいて、プログラムを実行していく中で、T=1 となった時点で、n 行目を、

{処理B}

と、書き換えたいのです。

-----------------

該当個所の処理(この例では、IF 〜 THEN の条件判定処理)にかかるコストが無視できるほど小さいものであれば、こんなことは考えなくていいのでしょうが、
そうでない場合は、自分自身のソースコードを書きかえるプログラム(コンパイラ言語であれば、書き換えた後、再コンパイルしなければなりませんが……)というのは、現実性があるのでしょうか?


まとめると、
「自分が実行中のフローチャートを、自ら書き換えるプログラム」
の可能性について、お聞きしたいのです。
0002デフォルトの名無しさんNGNG
         ∧_∧
         < `ш´>  >>1 お前の感じている感情は精神疾患の一種だ。
       _φ___⊂)     しずめる方法は俺が知っている。俺に任せろ
      /旦/三/ /|
    | ̄ ̄ ̄ ̄ ̄|  |
    | 流鬱百円 |/
0003デフォルトの名無しさんNGNG
3GET
0004デフォルトの名無しさんNGNG
アセンブラ時代にはよくやったなー。
0005デフォルトの名無しさんNGNG
無限ループのこと?
0006デフォルトの名無しさんNGNG
コボラー?
0007デフォルトの名無しさんNGNG
>>4
今でもたまにやります。
x86じゃないけど。
0008デフォルトの名無しさんNGNG
自分自身を書き換えなくても、イベント駆動型のプログラミングとやってること
同じじゃん。
0009デフォルトの名無しさんNGNG
lisp の方がいいよ。
0010デフォルトの名無しさんNGNG
C なら関数ポインタの出番だろう。
0011デフォルトの名無しさんNGNG
だからオペレーティングシステムはいろんなプログラムを実行できるわけであって...以下略
0012デフォルトの名無しさんNGNG
>>1はVBでOSを作る気か?
0013bloomNGNG
http://homepage.mac.com/ayaya16/
0014デフォルトの名無しさんNGNG
恐怖の自己増殖オートマトンですね。
発案者の天才ノイマンですら作れませんでした。
1には無理です。
0015デフォルトの名無しさんNGNG
なんでこんなに安いの???

http://ime.nu/ime.nu/www.net-de-dvd.com/
0016デフォルトの名無しさんNGNG
自分を書き換えるプログラムか〜・・・
面白そう。
絶対不可能じゃないと思うけど・・・。

インタプリンタ系スクリプトで、コンパイルした実行プログラムはメモリに常駐。
必要があれば、ソースを編集。 再コンパイルでメモリ常駐。
こんな感じで作れそう。

・・・・って、ウイルス作るのか?
0017デフォルトの名無しさんNGNG
MD5Hashが合うようにコードを書き換えるウィルス、、とか
0018デフォルトの名無しさんNGNG
Windows上ではコード領域を書き換えようとすると例外が起こる
0019デフォルトの名無しさんNGNG
機械語、Lisp、Forthあたりでは普通のテクニックかと。
0020デフォルトの名無しさんNGNG
>>18
VirtualProtect使えば問題なし
0021デフォルトの名無しさんNGNG
φ(.. ) 書き書き
0022あぼーんNGNG
あぼーん
0023デフォルトの名無しさんNGNG
10年前からウイルスの自己書き替え進化を待ってるんだが。
まだなのか。もう待ちくたびれたぞ!
0024デフォルトの名無しさんNGNG
prologなんかも自己書き換えがデフォルトだな。
0025デフォルトの名無しさんNGNG
>>23
あるウィルスにウィルスが感染して新しいウィルスが誕生したってのはあったらしい
0026デフォルトの名無しさんNGNG
>>25
こえ〜!
0027山崎渉NGNG
     ∧_∧
ピュ.ー (  ^^ ) <これからも僕を応援して下さいね(^^)。
  =〔~∪ ̄ ̄〕
  = ◎――◎                      山崎渉
0028デフォルトの名無しさんNGNG
より存在し続けるために、などと言ってみるテスト
0029デフォルトの名無しさんNGNG
糞スレ

↑
0030デフォルトの名無しさんNGNG
プログラマを書き換えて性能アップを図るプログラムを開発希望
0031デフォルトの名無しさんNGNG
このスレを書き替えて良スレにしてほしい
0032デフォルトの名無しさんNGNG
>>18
そうだよね。基本的にコード領域は書き換えられない。
でも変数にコードぶっこんで、それをコールするようにしとけば
実行時に変数を書き換えることで実現可能。
Cマガに載ってて試したよ。

処理内容が予め分かっているのならDLLを切り替えるので十分だと思ふ。
関数ポインタよりニュアンスが近いかと
0033デフォルトの名無しさんNGNG
Cマガってそんなしょうもないテクニックが載っているんだ。
0034デフォルトの名無しさんNGNG
なんで誰も「単発質問スレ立てるな」といわないの?
0035デフォルトの名無しさんNGNG
>>1
そういう時はさ
ループを2つ用意しておいて

for(i=0;i<n;i++) ・・・ { ・・・処理A・・・ if T<>0 then break;}
for(i<n;i++) ・・・ { ・・・処理B・・・ }

と T=0になったら最初のループをブレークしてしまえばいいんだよ。
もちろん T というフラグを作らずに、T= 0以外にするような条件が出来た時にブレークすればいい
0036デフォルトの名無しさんNGNG
ま、ストラテジパターンマンセーってことで。
0037デフォルトの名無しさんNGNG
1.IFくらい気にしない
2.関数ポインタにしておいて必要に応じて差し替える
3.functorにしておいて(以下略
4.その他

>>18
>Windows上ではコード領域を書き換えようとすると例外が起こる

自前の領域なら大丈夫。

int main()
{
  int   x = 0;
  BYTE  *code = (BYTE *)malloc(64);
  
  code[0] = 0xB8;    // mov eax
  code[1] = 0x64;    // 100
  code[2] = 0x00;
  code[3] = 0x00;

  code[4] = 0x00;
  code[5] = 0xC3;    // ret

  // 関数ポインタにキャストして実行してやると x = 100になる
  x = (*((int (*)(void))&code))();

  printf( "x = %d\n", x );

  free( code );
  return 0;
}
0038デフォルトの名無しさんNGNG
>>37
mallocを使う必要があるの?
0039デフォルトの名無しさんNGNG
■自分自身を書き換えるプログラム

1.早寝、早起きをする。
2.暴食暴飲をさける。
3.運動をする。
4.身の回りを整理整頓する。
5.廊下は走らない。
0040デフォルトの名無しさんNGNG
>>39
実行時エラーのヨカン
0041デフォルトの名無しさんNGNG
>>40

この時間まで起きてれば、1.でエラーですね。

面目ない
0042デフォルトの名無しさんNGNG
>>41
いや、面白くない
0043デフォルトの名無しさんNGNG
lisp の方がいいよ。
0044デフォルトの名無しさんNGNG
女を侵す。
女を犯す。
女を冒す。
0045デフォルトの名無しさんNGNG
男を侵す。
男を犯す。
男を冒す。
0046デフォルトの名無しさんNGNG
>>1
メモリ容量や速度に極端な制限がある、
昔のコンピュータならそないな事するケースがあった
と聞くが。

高階関数、リフレクション、項書き換えシステム
・・・ってなあたりかな、おなじみの関連分野は。
あと最近だと
アスペクト指向で、Cross-cutting concernsの括り出し/追加に、
コンパイル・コードを直接編集する手法が使われたり、
Apache Jakarta プロジェクトにバイト・コード編集ライブラリが出てたり、
ってな話題もあったな。結構継続的に研究されてる概念のよかーん
0047デフォルトの名無しさんNGNG
まあ >>1 の問題の解法としては >>35 を改良する方が余程よいだろう
0048デフォルトの名無しさんNGNG
漏れ的には >>37 の方が萌え だな
0049デフォルトの名無しさんNGNG
てか、>>37そのまま動くか?少しぐぐってみたら、
windowsならAPIのVirtualProtect使わなきゃならんってあったんだけど。
0050_NGNG
http://homepage.mac.com/hiroyuki44/
0051デフォルトの名無しさんNGNG
>>49 >>20
0052デフォルトの名無しさんNGNG
自分自身でカキまくる、おサルスレはここですか?
0053デフォルトの名無しさんNGNG
「本当のプログラマーはPascalを使わない」読んだ時は感激したな。
まあ今の保護された状況では無理だが。ring0に突入すれば可能か?
もう一回読みたいんだが、どこかにソースないかな?日本語では
なさそうなんだが…
0054デフォルトの名無しさんNGNG
http://www.genpaku.org/realprogrammerj.html
005553NGNG
>>54
サンクス。でも昔読んだのと違うなぁ。配列の添え字をマイナスに
して自己書き換えする話が消えてる。古いビット探してみるかな。
0056山崎 渉NGNG

 __∧_∧_
 |(  ^^ )| <寝るぽ(^^)
 |\⌒⌒⌒\
 \ |⌒⌒⌒~|         山崎渉
   ~ ̄ ̄ ̄ ̄
0057山崎 渉NGNG

 __∧_∧_
 |(  ^^ )| <寝るぽ(^^)
 |\⌒⌒⌒\
 \ |⌒⌒⌒~|         山崎渉
   ~ ̄ ̄ ̄ ̄
0058デフォルトの名無しさんNGNG
>>54
感動!
0059山崎 渉NGNG
(^^)
0060デフォルトの名無しさんNGNG
x = (*((int (*)(void))&code))();
ここがよくわからない…
0061デフォルトの名無しさんNGNG
スレタイしか読んでないけどオーバーレイですか?なつかしいですね。
0062デフォルトの名無しさんNGNG
>>60
引数voidで返り値intの関数ポインタとしてcodeをキャストしそれを呼ぶ。
で、xに値が返ってくる。
おけ?
0063デフォルトの名無しさんNGNG
// お前らインラインアセンブラ教えてくだちい!
__asm {
0064デフォルトの名無しさんNGNG
  HLT
}
0065 ◆chuouI0.kM NGNG
// お前らインラインアセンブラ教えてくだちい!
__asm {

0066しゃーねーな〜♪NGNG
xor eax, eax; eax = 0
0067Delフサギコ ◆A6VzDeLphI NGNG
    ∧,,∧  >>53どのあたりに感動するん?
   ミ,,゚Д゚彡
    ミ つ旦)~~
  〜と,,,~),,~)  あれって、
http://itpro.nikkeibp.co.jp/free/ITPro/OPINION/20020904/1/
この記事と同じ風な逆説記事なんだけど…
0068デフォルトの名無しさんNGNG
>>67
その記事、ほんとに日経のヤシが書いてんのか?ネタかとオモタ
0069Delフサギコ ◆A6VzDeLphI NGNG
           _________
   ∧,,∧   / 皆様の評価
  ミ,,゚Д゚彡 <  も見てあげてください。
   ミ つ旦)~~ \ 
 @ミ   ミ     ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   ∪''∪
0070デフォルトの名無しさんNGNG
>>67
そいつは懐かしい記事だな。
今、真島はどうしているのだ?
0071デフォルトの名無しさんNGNG
これもあったねー
http://www.sodan.org/~knagano/emacs/emacs21-emacs20-antinews-j.html
0072デフォルトの名無しさんNGNG
再帰...
0073山崎 渉NGNG
    (⌒V⌒)
   │ ^ ^ │<これからも僕を応援して下さいね(^^)。
  ⊂|    |つ
   (_)(_)                      山崎パン
0074デフォルトの名無しさんNGNG
lisp の方がいいよ。
0075デフォルトの名無しさんNGNG
C#でも
http://plaza.harmonix.ne.jp/~fakira/turedure/cprog_03.htm#031022
0076デフォルトの名無しさんNGNG
ほう
0077デフォルトの名無しさんNGNG
AをBに書き換える。

書き換えるBもプログラムの中にあらかじめおいてあるなら、
書き換えるよりジャンプしたほうがいい予感がする。
0078デフォルトの名無しさんNGNG
昔は使ったテクニックだが、今はやらないな。
組み込み用だとROMはコード書き換えできないし、
マルチタスクOSだと保護例外に引っかかるから。
0079デフォルトの名無しさんNGNG
>x = (*((int (*)(void))&code))();

素直にx=100;と書いたほうが早いだろ
0080デフォルトの名無しさんNGNG
>>37
>   x = (*((int (*)(void))&code))();

&code → codeだな.
0081デフォルトの名無しさんNGNG
>>78
マルチタスクと保護例外は関係ないだろう。
0082デフォルトの名無しさんNGNG
なんか、自分自身のコードを出力するプログラムを思い出した。
0083デフォルトの名無しさんNGNG
x86 WinNT系ならできるぞ。
code、data属性を持つディスクリプタ・・・(ry
0084デフォルトの名無しさんNGNG
Selector Base Limit Type DPL Size Gran Pres
-------- -------- -------- ---------- --- ------- ---- ----
0018 00000000 ffffffff Code RE Ac 3 Big Page P
0020 00000000 ffffffff Data RW Ac 3 Big Page P

XPのGDTの一部。
確かにコードデータ関係なく配置できるようだけど、これって
ユーザープログラムからもカーネル部分にアクセスできるじゃん。
って実際は出来ないんだけど。どうやって保護してるんだろう?
0085デフォルトの名無しさんNGNG
ページフレームについて調べてみましょう
0086PielNGNG
perl -i myself.pl myself.pl
0087デフォルトの名無しさんNGNG
>>1
もっと高レベルな言語では、それは自己反映計算(reflection)とかいう
やつで、昔は結構はやっていたらしい。
今は、画期的な応用がないということで、かなり廃れている。
javaでは文字列から動的にメソッドだとかクラスだとかの実体を取り出す
ことができるけど、その機能はreflectionを極めて限定して実現した
ものだといえる。CLOSとかいうlisp系の言語やsmalltalkでは、java
よりも極端なreflectionの機能があって、>>1のようなことができると
思うけども、詳しくは知りましぇ〜ん。
0088デフォルトの名無しさんNGNG
リフレクションならJavaScriptやUnixのシェルスクリプトなんかで普通に使うよ。
というか、無意識にやってる人が多いはず
0089デフォルトの名無しさんNGNG
>>88
>Unixのシェルスクリプトなんかで普通に使うよ

具体例が思いつかないけど、どんなの?
0090デフォルトの名無しさんNGNG
コンピュータネットワークの講義で教授が言ってたけど、昔のメモリが貴重な時代は
実行中にコードを生成するのがなんたらとか語ってたな
0091デフォルトの名無しさんNGNG
>>90
今でも多いよ、そもそもOSそのものが、自己書き換えプログラムそのものとも言えるし。
0092デフォルトの名無しさんNGNG
自己書き換は
書き換える事よりもデータとプログラムは等価であるとして
データと同じメモリー上にプログラムをデータとして置いてしまったノイマンが天才的と思う。
ノイマン型コンピュータの前提を崩すのはそう簡単ではないね。
これがなければOSも実現しなかったか?
個人的にはプログラムを作るプログラムに興味あり。
以下プログラムを作るプログラムを作るプログラムを作るプログラムを作るプログラムとかとか
0093デフォルトの名無しさんNGNG
Z80の時代ならアセンブラのコードを少なくするために頻繁にやってたな。
PUSHを利用して自分自身を完全に消し去るコードとかもかけたし。
LDIRだとうまくいかなかった記憶が。

>>37が面白そう。
実行中は自分自身を暗号化しているウイルス、とか書いたら面白そうやね。
0094デフォルトの名無しさんNGNG
>>93
「ポリモルフィック型のウイルス」とかいって、ウイルスチェッカを欺く
ために、実行前はコード中の悪意のある部分は暗号化されているんだけど、
実行時にその部分を復元してjumpして実行する、というのがあるらしい。
0095デフォルトの名無しさんNGNG
参考書籍
http://www.cqpub.co.jp/hanbai/books/36/36781.htm
0096デフォルトの名無しさんNGNG
>>95
それは、「自分自身を呼び出すプログラム」。
一応、突っ込んどく。
0097デフォルトの名無しさんNGNG
クラック防止でも昔使われたテクやね。
今は知らないや。
■ このスレッドは過去ログ倉庫に格納されています