__cdecl调用 C语言变参

原创 2011年01月19日 09:52:00

__cdecl调用

在C语言中,函数调用支持不定参数,例如printf函数,可以不知道参数的个数,eg:

void err_info(const char *fmt, ...)

{

va_list ap;

va_start(ap, fmt);

vfprintf(stderr, fmt, ap);

va_end(ap);

}

这是如何实现的呢?如何支持变参的呢?

下面简要介绍下__cdecl调用方式,当然还有很多其他的调用方式,不过目前用不到

函数调用需要关注的几个方面:

1、函数调用时参数是如何保存的?

2、是调用者来清理函数调用还是被调用者来清理函数调用?

3、函数调用时参数的顺序是怎样的?

4、可能会用到哪些寄存器?

先说第一个问题,这个是很容易的,大家都知道C语言中是用栈来保存函数调用时的参数的

下面再分析其他几个问题:

在__cdcel标准中规定:

1、函数调用的参数入栈顺序是从右到左,即先压栈最右边的参数,最后压栈最左边的参数

2、在函数调用结束后用调用者来清理栈

3、调用过程中一般会用到eax、ebx、ecx等寄存器

void func(int a, int b)

{

...

}

int main(void)

{

...

func(1,2);

...

}

下面以这个例子来说明:

在调用的过程中由于是从右到左入栈,所以压栈的顺序是先2后1,用汇编可以描述为:

push 2

push 1

main函数对应的汇编大概是:

push 2

push 1

call func

add esp, 8 //清理栈,因为在调用过程中esp指针向下(或者说是向低地址)移动了8个字节

ret

这是调用顺序上

基于上面的几点我们就可以理解C语言中是如何实现变参函数的调用了:

1、由于函数调用是从右到左入栈的,因此函数调用时最左边的参数是最后一个入栈的,这样就可以函数调用时最左边的参数位置了

2、由于有format的指定,每个参数的大小是可知的,例如%d表示是int型,占用4个字节等

3、根据上面的两项就可以取出函数参数了。首先根据最左边参数(此处的含义是最后一个确定参数,也就是该参数后面的参数都是可变参数)

(例如

void func(char *arg1, char *arg2, ...)

那么最左边的参数意思就是arg2,因为它是最后一个确定参数

)

的位置可以找到函数调用时最左边的参数,然后根据每个参数的大小,移动esp指针(一般是向高地址移动),就可以依次取出其他所有参数了

wiki上介绍:http://en.wikipedia.org/wiki/X86_calling_conventions

clip_image001

clip_image002

clip_image003

相关文章推荐

cdecl(C语言声明解析器)

  • 2012年11月14日 08:39
  • 32KB
  • 下载

cdecl:C语言声明分析器

有时候,C语言声明十分反人类……于是,cdecl应运而生~~~ // // main.cpp // f-cdecl // // Created by ZYJ on 2016/11/2. // ...
  • f_zyj
  • f_zyj
  • 2016年11月02日 14:54
  • 288

将C语言的声明翻译成通俗语言——cdecl

《c专家编程》中的一个程序,可以将声明翻译为通俗语言,主要运用栈,挺难的,我自己是写不出的,照着书敲了一遍。 #include #include #include #include #define...

程序比程序员更理解c语言! cdecl程序(分析c语言的声明

c语言的声明有时侯是很复杂的;比如int (*a[5])(int); 再比如:int*((*p)(int))(int);你能说明白它们的意思吗? 像这样的声明很容易把一般的程序员弄蒙逼的。 ...

c语言变参函数

C语言编程中有时会遇到一些参数个数可变的函数,例如printf()函数,其函数原型为: int printf( const char* format, ...); 它除了有一个参数form...

C语言的变参函数设计

在C语言中,函数参数的传递方式有值传和址传.值传是把实参的一个专用的、临时的复制值给被调函数中相应的形参被调用函数使用、修改这个传来的复制值,不会影响实参的值.址传则是把变量(实参)的地址传给被调函数...

C语言的那些小秘密之【变参函数的实现】

FROM: http://blog.csdn.net/bigloomy/article/details/6588354 =======================================...
  • dadoneo
  • dadoneo
  • 2013年03月05日 00:11
  • 658

C语言的变参技术-va_arg

#include     // 必须包含的头文件 int Add(int start,...)   // ...是作为占位符 {     va_list arg_ptr;    // 定义...

C语言函数变参问题

C语言是支持函数的参数个数不确定的情况,例 如我们经常用的printf()函数就是如此。 //extern void printf(const char *format,...); prin...

VA_LIST 是在C语言中解决变参问题的一组宏

VA_LIST 是在C语言中解决变参问题的一组宏 VA_LIST的用法:              (1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针        ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:__cdecl调用 C语言变参
举报原因:
原因补充:

(最多只允许输入30个字)