编程之巧

作者在 2013-04-26 10:13:40 发布以下内容
编程之巧

 

  灵巧的程序像含蓄的诗歌,需要仔细领悟,用心去体会,茅塞顿开后方能回味无穷。真乃会当临绝顶,一览众山小!同样是求pi,但是只有简单的四行C代码却能打印出pi的前800位的程序定会让我们大开眼界[5]

int a=10000,b,c=2800,d,e,f[2801],g;
main(){
for(;b-c;)f[b++]=a/5;
for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)
for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);
}

  黑客们不会墨守陈规,他们不断地创新,寻找更巧的方法来解决同样的问题。曾经流行编写这样一种程序,它能够打印它自己的全部代码。程序员们努力寻找最短的这种程序。这虽然没多大实际用处,但是充满了挑战性,黑客们把这当作乐趣。看看下面的程序[6]是多么怪异。

char *f="char *f= %c%s%c;main(){printf(f,34,f,34,10);} %c";
main(){printf(f,
34,f,34,10);}

  计算机编程吸引人的很大一部分在于它需要高超的技巧,也正是这些技巧才使我们看到了美,从中得到了乐趣。而且,我发现,当限制增加时,技巧将会更高,乐趣也会随之增加。来写这样一段程序,让它在屏幕上打印1~1000之间的数字。这对于一个新手来说也是小菜一碟,一个for 循环就搞定。好,我们加一个限制,不许使用任何循环。这时你得动一番脑筋了,不过你还是会想到用递归可以完成。不错,我们再加一个限制,也不许用递归。这可能把你难住了,你可能会认为不可能有这样的程序,那看看下面的程序吧:

#include <stdio.h>
#define A(x) x;x;x;x;x;x;x;x;x;x;
int main (void)
{
int n = 1;
A(A(A(printf (
"%d ", n++))));
return 0;
}

  既没有用循环,也没有用递归,而是使用了宏!我们常常惊讶于世界各地著名的Warez组织推出的64k3D动画,那么小的程序,往往有难以想象的效果。它们把64k的限制和汇编的威力运用到了极限,这种技术让人叹为观止。64k似乎并没有限制住其艺术性,反而起了促进作用。并且,当你对系统有足够的了解时,乐趣将会更多。因为你可以使用技巧和系统开玩笑了,欺骗它,作弄它,甚至攻击它。看下面的程序:

void main() {
int x;
x =
0;
x =
1;
printf(
"%dn",x);
}

  想一想,如何才能让程序跳过“x=1;”这一句而在屏幕上打印0?如果你对系统堆栈了解的话,你可能会给出类似下面的程序[7]

void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
int *ret;
 
ret = buffer1 +
12;
(*ret) +=
8;
}
 
void main() {
int x;
 
x =
0;
function(
1,2,3);
x =
1;
printf(
"%dn",x);
}

  它利用了调用函数时堆栈的变化,改变函数的返回地址,跳过了“x=1;”这一句而直接执行下面的printf!它成功的欺骗了系统!如果把返回地址改成你预先放置的一段代码的首地址,那么你将会劫持系统,让它运行你的那段代码。如果那段代码足够巧,你将能获得系统的完全控制权!这也是缓冲区溢出的基本原理。我想,这种技巧将会让你兴奋不已,丝毫不亚于陶醉在自己诗里的诗人。我们已经看到:巧妙产生美,并与之形成艺术的雏形。
个人分享 | 阅读 1604 次
文章评论,共2条
yctchxf
2013-04-28 17:04
1
我视乎还没有那个能力看懂的哇……
机器王者
2013-05-20 21:29
2
打印1~1000数字那段代码如何运行啊
游客请输入验证码