c语言强化训练笔记2010/5/9

 

函数指针

下面是关于函数指针的一些资料

函数指针是指向函数的指针变量。

因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是一致的。函数指针有两个用途:调用函数和做函数的参数。函数指针的声明方法为:

数据类型标志符 (指针变量名) (形参列表);

我们通过(*(int far *)+地址)这样的代码实现了访问任意一段内存的数据,那么可以通过函数指针实现执行任意一段代码

首先在debug下用a命令在一段安全的空间中写入一段程序,然后用u命令反汇编得到这段程序的机器码

C:\minic>debug
-a 0:200
0000:0200 mov ax,b800
0000:0203 mov es,ax
0000:0205 es:
0000:0206 mov byte ptr [0690],61
0000:020B retf
0000:020C
-u 0:200
0000:0200 B800B8        MOV     AX,B800
0000:0203 8EC0          MOV     ES,AX
0000:0205 26            ES:
0000:0206 C606900661    MOV     BYTE PTR [0690],61
0000:020B CB            RETF

在c语言编写程序,将这段机器码写入到一个数组中,然后在main函数中将数组拷贝到0:200这段安全的空间中,再定义一个指向0:200的函数指针,通过调用函数指针来执行数组中的这一段程序

void (far *p)();
char a[20]={0xb8,0x00,0xb8,0x8e,0xc0,0x26,
            0xc6,0x06,0x90,0x06,0x61,0xcb};
main()
{
  int n;
  for(n=0;n<20;n++) ((char far *)0x200)[n]=a[n];
  p=(void (far *)())0x200;
  p();
}

上面这个程序并没有定义函数,而是通过函数指针调用了一段空间中的程序

可以改进这个程序,不需要将数组中的机器码拷贝到安全空间中,只要直接调用数组的首地址就可以

char a[20]={0xb8,0x00,0xb8,0x8e,0xc0,0x26,
            0xc6,0x06,0x90,0x06,0x61,0xcb};
main()
{
    void (far * p)();
    p = (long)a;
    p();
}

既然变量本质是某块内存空间的名称,那么可以省略函数指针变量p,直接使用地址来调用数组中的程序

char a[20]={0xb8,0x00,0xb8,0x8e,0xc0,0x26,
            0xc6,0x06,0x90,0x06,0x61,0xcb};
main()
{
  ((void (far *)())(long) a)();
}

还可以做的更简单

char main[20]={0xb8,0x00,0xb8,0x8e,0xc0,0x26,
            0xc6,0x06,0x90,0x06,0x61,0xc3};
posted @ 2010-05-13 10:54  石莹  阅读(537)  评论(0编辑  收藏  举报