2005年09月01日
C言語のmain関数を変数として定義
なんとなく思いついたのでやってみた.C 言語で書いたプログラムの(ブートストラップ後の)エントリポイントは main 関数なわけだけど,アセンブラレベルでは結局のところ call main して main というラベルにとんでいるだけ.ということは,main は別にC言語の関数ではなく変数でもよい(main というラベルが作られる).これを実証するコードは以下のとおり.
こいつは HelloWorld を表示するが,main は関数でなく変数である.
#include <stdio.h>
int f()
{
printf("HelloWorld!\n");
return 0;
}
int main[] = {0xB8909090, (int)f, 0x9090E0FF};
/*
int main = 0xB8909090;
int main2 = (int)f;
int main3 = 0x9090E0FF;
*/
/*
struct main {
int m1; int m2; int m3;
} main = {0xB8909090, (int)f, 0x9090E0FF};
*/
main の定義をコメントアウトしている形(構造体,複数個の連続した変数)にしても動く.原理としては main というラベルに飛ばされてくるので,そこに関数本体である f へのジャンプを行うマシン語を埋め込んで f へジャンプさせる.ジャンプのコードはi386で
90 NOP 90 NOP 90 NOP B8 XXXXXXXX MOVE EAX, f FF E0 JMP EAX 90 NOP 90 NOP
とかけるので,これらのマシン後が実行されるように main 変数に値を入れている.
ついでに C++ 版も.
#include <cstdio>
struct main {
int ins[5];
static int f() {
puts("HelloWorld!");
return 0;
}
} main = {0xB8909090, (int)(main::f), 0xE0FF};
- Comments: 0
- TrackBack (Close): -