Dict.CN 在线词典, 英语学习, 在线翻译

学海苦作舟,书山勤为径

留下点回忆

常用链接

统计

积分与排名

Denoise

English study

Web技术

数据压缩

一些连接

最新评论

Windows中C函数是什么?

 

C语言中函数就是一些代码的集合,实现相对单一的功能;应该有名称、参数、返回值。实际上函数应该是能够从调用程序中接受输入,处理一定的逻辑,并最终能返回到调用程序的一段代码的集合。

本主要讨论windowsC函数如何实现的;主要包括:函数调用约定、参数传递和返回。

调用约定

Windows中默认使用的cdecl调用约定,又叫C调用约定(不加任何修饰就是这种约定)。cdecl的调用约定意味着:

1) 参数从右向左压入堆栈

2) 函数自身不清理堆栈;调用者负责清理,因此这种调用约定允许参数不固定

3) 函数名自动加前导的下划线

 

例如:函数

Void TestFun(int a,int b);

等价于:

Void __cdecl TestFun(int a,int b);

 

如果有段代码调用上面的函数,例如:

TestFun(1,2);

那么转变为汇编的就是:

Push 2

Push 1

Call TestFun

Add esp 8          ;2个参数

 

假设esp的指针在调用函数之前为20,那么上面代码行对应的esp的值为:

Push 2               ;esp =16

Push 1               ;esp=12

Call TestFun     ;esp=8

Add esp 8          ;esp=20

其中call指令会修改esp的值,即将函数的返回地址进栈。

 

WINAPIstdcallcdecl不同之处TestFun自己修改堆栈;上面函数的汇编代码是:

Push 2

Push 1

Call TestFun

 

 

参数传递

C函数的参数传递都是通过堆栈来进行的。还是针对上面的函数来画一下堆栈的内容:

 

ßESP

返回地址

低地址

1(参数a

 

2(参数b

 

 

 

 

高地址

调用者将参数ab放到堆栈中;一旦进入函数体,函数需要读取这些参数并进行处理。读取函数的方式就是通过ESP的偏移来完成。

Mov eax, [esp+4]     ;a的值

Mov ebx,[esp+8]      ;b的值

 

如果在进入函数取参数之前先要保存某些寄存器,例如:

Push eax

那么esp的基地址发生了变化就是esp+4,从而取ab的值就变成:

Mov eax,[esp+8]          ;a的值

Mov ebx,[esp+12]        ;b的值

 

函数返回

函数返回分为两个部分:返回值的设置和返回调用者的位置。

返回值

一般函数的返回值都是通过eax这个寄存器传递给调用者的,因此如果函数有返回值都在eax中。但对于浮点数使用ST0而不是EAX寄存器。

 

因此函数体中在RET之前,需要做的是:

MOV EAX, XXX          ;XXX返回值

 

在调用者中取返回值的做法就是:

MOV [ret], EAX         ;ret存放返回值的变量

如果返回值超过4个字节,高位放在EDX中。

 

函数返回

对于C约定的函数返回通过RET来完成。需要做的就是从堆栈中读取返回地址,然后修改EIP寄存器的位置;ESP的值加4,即从堆栈中把返回值POP出来。

 

对于STDCALL的约定,需要给RET传递一个参数,参数的内容为传递进来的参数占用堆栈的大小,目的是通过RET指令来修改ESP的栈顶位置;恢复到调用前的位置。

 

不管上面约定,最后EIP指向调用者调用该函数的下一行指令。

posted on 2008-10-18 00:07 笨笨 阅读(1835) 评论(0)  编辑 收藏 引用 所属分类: 编码


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理