c语言中参数列表可变的函数写法,如printf

研究了一段时间反汇编,突然发现多年以前羡慕的printf样式的函数我也会写了

如下面的这个函数(测试环境VS2008)

DWORD Fun(int n,...)       //n为参数书目,最多处理100个参数,并且每个参数要是一个4字节的变量,如DWORD/int/long/HANDLE
{
 DWORD para[100];      //最多处理100个参数,如果用动态内存方式可以处理参数数量不收限制
 for(int i=0;i<n;i++)
 {
  __asm  //从栈中的参数列表把参数复制到para数组里
  {
   lea ebx,[ebp+12]        //[ebp+12]为第1个参数(把n算做第0个参数)
   mov eax,i     
   mov edx,[ebx+eax*4] 
   lea eax,[para+eax*4]
   mov [eax],edx
  }
 }
 for(int i=0;i<n;i++)
 printf("%u/n",para[i]);  //把这些参数依次打印到屏幕
 return 7;
}

 

 

int _tmain(int argc, _TCHAR* argv[])
{
 DWORD d=Fun(10,65,3,7,88,23,11,8,9,7734,3784);  //调用这个可变参数的函数

return 0;

}

 

堆栈平衡由编译器在编译的时候控制。由于第0个参数只是简单的说明一下传递过来的参数数目没有对参数类型有任何说明,所以只能正确处理单个参数占4个字节的参数。

printf函数使用了一些其它机制来获取参数列表,单原理应该不会变:

 

int __cdecl printf (const char *format,...)  /*stdout 'PRINT', 'F'ormatted*/
{
        va_list arglist;
        int buffing;
        int retval;

        _VALIDATE_RETURN( (format != NULL), EINVAL, -1);

        va_start(arglist, format);  //能够使arglist指向盏中的参数列表

        _lock_str2(1, stdout);
        __try {

        buffing = _stbuf(stdout);

        retval = _output_l(stdout,format,NULL,arglist);

        _ftbuf(buffing, stdout);

        }
        __finally {
            _unlock_str2(1, stdout);
        }

        return(retval);
}

 

 

这些va_start,va_arg,va_end之类的东西暂时还不太会用。

 

char* arglist;
va_start(arglist, format);  //这个宏能直接得到参数列表首地址,比用一段内联汇编方便多了

 于是前面的那个函数就可以修改成如下样子:

 

DWORD Fun3(int n,...)
{
 char* arglist;
 va_start(arglist,n);
 for(int i=0;i<n;i++)
 {
  printf("%X/n",((DWORD*)arglist)[i]);
 }
 return 7788;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值