6月
13
2007
分類:
最近更新:
2007-06-13
無聊之下寫的程式,把程式碼當資料...
前些日子閱讀《沒有時間的世界》,書中說,圖靈 的圖靈機概念,最偉大的貢獻在於「把程式當資料儲存」的想法。我一時無聊,又想起了以前在 DOS 時代的記憶,就寫了一段 C 語言程式,把程式碼當資料複製,然後再去執行那段被複製的程式碼。
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
void funcA() {
puts("hello\n");
}
void funcB() {}
int main() {
void (*pfV)();
size_t contextLength = (size_t)funcB - (size_t)funcA;
printf("context length: %x\n", contextLength);
pfV = (void(*)()) malloc(contextLength);
memcpy((void*)pfV, (void*)funcA, contextLength);
printf("%x\n", funcA);
for (int i = 0; i < 16; ++i) {
printf("%x,", ((char*)funcA)[i]);
}
puts("\n");
printf("%x\n", pfV);
for (int i = 0; i < 16; ++i) {
printf("%x,", ((char*)pfV)[i]);
}
puts("\n");
funcA();
(*pfV)(); //segment exception
return 0;
}
這個程式在現代的作業系統中應該是無法執行到結束的... 因為現代的作業系統都實踐了記憶體節區保護的概念,當程式試圖將 ip (指令指標) 指向一段標記為資料區的記憶體位址時,就會擲出系統性錯誤而中止程式執行。現在一般要改用系統呼叫才能做這件事;用 C 標準庫不允許這麼做。
不過在 DOS 時代,這段程式技巧卻相當普遍。在 640K + EMS/XMS 的限制下,幾乎有點資歷的程序員都會用這一招實現動態載入程式碼的功能。
樂多舊網址: http://blog.roodo.com/rocksaying/archives/3461127.html