跳至主要内容

【转】WIN32编程必知:__stdcall,__cdecl,__fastcall,thiscall,na

被这些修饰关键字修饰的函数,其参数都是从右向左通过堆栈传递的(__fastcall的前面部分由ecx,edx传),
函数调用在返回前要清理堆栈,但由调用者还是被调用者清理不一定。
1、_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,
自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。 int f(void *p) -->> _f@4(在外部汇编语言里可以用这个名字引用这个函数)
2、C调用约定(即用__cdecl关键字说明)(The C default calling convention)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数vararg的函数(如printf)只能使用该调用约定)。另外,在函数名修饰约定方面也有所不同。 _cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加上下划线前缀。
是MFC缺省调用约定。
3、__fastcall调用的主要特点就是快,因为它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈),在函数名修饰约定方面,它和前两者均不同。__fastcall方式的函数采用寄存器传递参数,VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数。
4、thiscall仅仅应用于"C++"成员函数。this指针存放于CX/ECX寄存器中,参数从右到左压。thiscall不是关键词,因此不能被程序员指定。
5、naked call。 当采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。
(这些代码称作 prolog and epilog code,一般,ebp,esp的保存是必须的).
但是naked call不产生这样的代码。naked call不是类型修饰符,故必须和_declspec共同使用。
关键字 __stdcall、__cdecl和__fastcall可以直接加在要输出的函数前。它们对应的命令行参数分别为/Gz、/Gd和/Gr。缺省状态为/Gd,即__cdecl。
要完全模仿PASCAL调用约定首先必须使用__stdcall调用约定,至于函数名修饰约定,可以通过其它方法模仿。还有一个值得一提的是WINAPI宏,Windows.h支持该宏,它可以将出函数翻译成适当的调用约定,在WIN32中,它被定义为__stdcall。使用WINAPI宏可以创建自己的APIs。
2)名字修饰约定
1、修饰名(Decoration name)
"C"或者"C++"函数在内部(编译和链接)通过修饰名识别。修饰名是编译器在编译函数定义或者原
型时生成的字符串。有些情况下使用函数的修饰名是必要的,如在模块定义文件里头指定输出"C++"重载函数、构造函数、析构函数,又如在汇编代码里调用"C""或"C++"函数等。
修饰名由函数名、类名、调用约定、返回类型、参数等共同决定。
2、名字修饰约定随调用约定和编译种类(C或C++)的不同而变化。函数名修饰约定随编译种类和调用约定
的不同而不同,下面分别说明。
a、C编译时函数名修饰约定规则:
__stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个"@"符号和其参数的字节数,
格式为_functionname@number。
__cdecl调用约定仅在输出函数名前加上一个下划线前缀,格式为_functionname。
__fastcall调用约定在输出函数名前加上一个"@"符号,后面也是一个"@"符号和其参数的字节数,
格式为@functionname@number。
它们均不改变输出函数名中的字符大小写,这和PASCAL调用约定不同,PASCAL约定输出的函数名无任何修饰且全部大写。
b、C++编译时函数名修饰约定规则:
__stdcall调用约定:
1、以"?"标识函数名的开始,后跟函数名;
2、函数名后面以"@@YG"标识参数表的开始,后跟参数表;
3、参数表以代号表示:
X--void ,
D--char,
E--unsigned char,
F--short,
H--int,
I--unsigned int,
J--long,
K--unsigned long,
M--float,
N--double,
_N--bool,
....
PA--表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以"0"代替,一个"0"代
表一次重复;
4、参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前

5、参数表后以"@Z"标识整个名字的结束,如果该函数无参数,则以"Z"标识结束。
其格式为"?functionname@@YG*****@Z"或"?functionname@@YG*XZ",例如
int Test1(char *var1,unsigned long)-----"?Test1@@YGHPADK@Z"
void Test2() -----"?Test2@@YGXXZ"
__cdecl调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YA"。
__fastcall调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YI"。
VC++对函数的省缺声明是"__cedcl",将只能被C/C++调用.

评论

此博客中的热门博文

【转】smb协议栈使用示例

/*  * * uncdownload.c  * *  * * Utility for downloading files from SMB shares using libsmbclient  * *  * * Copyright(C) 2006 Sophos Plc, Oxford, England.  * *  * * This program is free software; you can redistribute it and/or modify it under the terms of the  * * GNU General Public License Version 2 as published by the Free Software Foundation.  * *  * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without  * * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  * * See the GNU General Public License for more details.  * *  * * You should have received a copy of the GNU General Public License along with this program; if not,  * * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  * *  * */ # include < sys / types . h > # include < sys / time . h > # include ...

【转】Ether Types

Ether Types (last updated 2008-09-09) NOTE: Please see [RFC5342] for current information and registration procedures. This registry will be revised soon and will be replaced with up-to-date information. Many of the networks of all classes are Ethernets (10Mb) or Experimental Ethernets (3Mb). These systems use a message "type" field in much the same way the ARPANET uses the "link" field. If you need an Ether Type, contact: IEEE Registration Authority IEEE Standards Department 445 Hoes Lane Piscataway, NJ 08854 Phone +1 732 562 3813 Fax: +1 732 562 1571 Email: <ieee-registration-authority& ieee.org > http://standards.ieee.org/regauth/index.html The following list of EtherTypes is contributed unverified information from various sources. Another list of EtherTypes is maintained by Michael A. Patton and is accessible at: <URL: http://www.cavebear.com/CaveBear/Ethernet/ > <URL: ftp://ftp.cavebear.com/pub/Ethernet-codes > Assign...

【转】udp编程实例

UDP通讯实例 2008-04-29 15:30:05 / 个人分类: linux C编程 UDP协议的几点好处: 1.UDP不要求保持一个连接; 2.UDP没有因接收方认可收到数据包(或者当数据包没有正确抵达而自动重传)而带来的开销; 3.设计UDP的目的是用于短应用和控制信息; 4.在一个数据包接一个数据包的基础上,UDP要求的 网络 带宽比TCP更小。 UDP的几个缺点: 1.程序员必须创建代码检测传输错误并进行重传(如果应用程序要求这样做); 2.程序员必须把大数据包分片。 code: <1> /* * sender.c--UDP protocol example */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> int port = 6789; int main() {     int socket_descrīptor;     int iter = 0;     char buf[80];     struct sockaddr_in address;     /* Initialize socket address structure for Interner Protocols */     bzero(&address, sizeof(address)); // empty data structure     address.sin_family = AF_INET;     address.sin_addr.s_addr = inet_addr("127.0.0.1");     address...