c语言中参数列表可变的函数写法,如printf
2011-04-13 05:52
716 查看
研究了一段时间反汇编,突然发现多年以前羡慕的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;
}
如下面的这个函数(测试环境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;
}
相关文章推荐
- 【C语言】printf函数的简单实现(可变参数列表)
- 可变参数列表:简单printf函数的实现
- C语言中的可变参数函数 三个点“…”printf( const char* format, ...) 博客分类: C语言 ANSI C CC++C#D语言编程 第一篇
- C语言(函数传递可变长度的参数列表)va_arg
- 可变参数列表实现机制与printf()函数源码分析
- 创建函数利用可变参数列表的形式模拟实现printf的功能
- c语言中可变参数的原理---printf()函数
- c语言中可变参数的原理---printf()函数
- 可变参数列表的剖析以及printf函数的实现
- C语言中的可变参数-printf的实现原理 在C/C++中,对函数参数的扫描是从后向前的。C/C++的函数参数是通过压入堆栈的方式来给函数传参数的(堆栈是一种先进后出的数据结构),最先压入的参数最后出
- c语言中的函数可变参数列表相关的三个宏
- C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) . 分类: HI3531 arm-linux-Ubuntu 2013-12-16 14:19 438人阅读 评论(0) 收藏
- 可变参数列表及printf函数的实现
- C语言中的可变参数函数 三个点“…”printf( const char* format, ...)
- c语言中的函数可变参数列表相关的三个宏
- C语言_函数可变参数列表
- C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .
- C语言定义可变参数列表的函数
- c语言中可变参数的原理---printf()函数
- C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .