Visual C++中函数调用方式浅探

库存管理系统项目部署方案(基于jdk8) 不需要安装到服务器,运维本地安装就行,主要是用来编译前端代码的。构建完成后将dist文件夹复制到服务器内。 阅读详情

 

函数调用的几个概念:_stdcall,_cdecl(c declare)....                

 

 

  左通过栈传递,被调用的函数在返回前清理传送参数的内存栈,但不同的是函数名的修饰部分(关于函数名的修饰部分在后面将详细说明)。     

 

  _stdcall是Pascal程序的缺省调用方式,通常用于Win32   Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在

 

函数名后加上"@"和参数的字节数。     

 

  2、C调用约定(即用__cdecl关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函

 

数只能使用该调用约定)。另外,在函数名修饰约定方面也有所不同。     

 

  _cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。

 

VC将函数编译后会在函数名前面加上下划线前缀。是MFC缺省调用约定。     

 

  3、__fastcall调用约定是“人”如其名,它的主要特点就是快,因为它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参

 

数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈),在函数名修饰约定方面,它和前两者均不同。     

 

  _fastcall方式的函数采用寄存器传递参数,VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数。     

 

  4、thiscall仅仅应用于“C++”成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定。     

 

  5、naked   call采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。naked 

 

  call不产生这样的代码。naked   call不是类型修饰符,故必须和_declspec共同使用。     

 

  关键字   __stdcall、__cdecl和__fastcall可以直接加在要输出的函数前,也可以在编译环境的Setting.../C/C++   /Code   Generation项选择。当加在输出函数前的关键字

 

与编译环境中的选择不同时,直接加在输出函数前的关键字有效。它们对应的命令行参数分别为/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++调用.     

 

  CB在输出函数声明时使用4种修饰符号     

  //__cdecl     

  cb的默认值,它会在输出函数名前加_,并保留此函数名不变,参数按照从右到左的顺序依次传递给栈,也可以写成_cdecl和cdecl形式。     

  //__fastcall     

  她修饰的函数的参数将尽肯呢感地使用寄存器来处理,其函数名前加@,参数按照从左到右的顺序压栈;    

  //__pascal     

  它说明的函数名使用Pascal格式的命名约定。这时函数名全部大写。参数按照从左到右的顺序压栈;     

  //__stdcall     

  使用标准约定的函数名。函数名不会改变。使用__stdcall修饰时。参数按照由右到左的顺序压栈,也可以是_stdcall;     

 

  我们知道在进行函数调用时,有几种调用方法,分为C式,Pascal式。在C和C++中C式调用是缺省的,除非特殊声明。二者是有区别的,下面我们用实例说明一下:   

 

  1.   __cdecl   :C和C++缺省调用方式   

  例子:   

  void   Input(   int   &m,int   &n);/*相当于void   __cdecl   Input(int   &m,int   &n);*/   

  以下是相应的汇编代码:   

  00401068   lea   eax,[ebp-8]   ;取[ebp-8]地址(ebp-8),存到eax   

  0040106B   push   eax   ;然后压栈   

  0040106C   lea   ecx,[ebp-4]   ;取[ebp-4]地址(ebp-4),存到ecx   

  0040106F   push   ecx   ;然后压栈   

  00401070   call   @ILT+5(Input)   (0040100a);然后调用Input函数   

  00401075   add   esp,8   ;恢复栈   

 

  从以上调用Input函数的过程可以看出:在调用此函数之前,首先压栈ebp-8,然后压栈ebp-4,然后调用函数Input,最后Input函数调用结束后,利用esp+8恢复栈。由此可见,在C

 

语言调用中默认的函数修饰_cdecl,由主调用函数进行参数压栈并且恢复堆栈。   

  下面看一下:地址ebp-8和ebp-4是什么?   

  在VC的VIEW下选debug   windows,然后选Registers,显示寄存器变量值,然后在选debug   windows下面的Memory,输入ebp-8的值和ebp-4的值(或直接输入ebp-8和-4),看一下这

 

两个地址实际存储的是什么值,实际上是变量   n   的地址(ebp-8),m的地址(ebp-4),由此可以看出:在主调用函数中进行实参的压栈并且顺序是从右到左。另外,由于实参是相

 

应的变量的引用,也证明实际上引用传递的是变量的地址(类似指针)。   

  总结:在C或C++语言调用中默认的函数修饰_cdecl,由主调用函数进行参数压栈并且恢复堆栈,实参的压栈顺序是从右到左,最后由主调函数进行堆栈恢复。由于主调用函数管

 

理堆栈,所以可以实现变参函数。另外,命名修饰方法是在函数前加一个下划线(_).   

 

  2.   WINAPI   (实际上就是PASCAL,CALLBACK,_stdcall)   

  例子:   

  void   WINAPI   Input(   int   &m,int   &n);   

  看一下相应调用的汇编代码:   

  00401068   lea   eax,[ebp-8]   

  0040106B   push   eax   

  0040106C   lea   ecx,[ebp-4]   

  0040106F   push   ecx   

  00401070   call   @ILT+5(Input)   (0040100a)   

  从以上调用Input函数的过程可以看出:在调用此函数之前,首先压栈ebp-8,然后压栈ebp-4,然后调用函数Input,在调用函数Input之后,没有相应的堆栈恢复工作(为其它的函数

 

调用,所以我没有列出)   

  下面再列出Input函数本身的汇编代码:(实际此函数不大,但做汇编例子还是大了些,大家可以只看前和后,中间代码与此例子无关)   

 

  39:   void   WINAPI   Input(   int   &m,int   &n)   

  40:   {   

  00401110   push   ebp   

  00401111   mov   ebp,esp   

  00401113   sub   esp,48h   

  00401116   push   ebx   

  00401117   push   esi   

  00401118   push   edi   

  00401119   lea   edi,[ebp-48h]   

  0040111C   mov   ecx,12h   

  00401121   mov   eax,0CCCCCCCCh   

  00401126   rep   stos   dword   ptr   [edi]   

  41:   int   s,i;   

  42:   

  43:   while(1)   

  00401128   mov   eax,1   

  0040112D   test   eax,eax   

  0040112F   je   Input+0C1h   (004011d1)   

  44:   {   

  45:   printf("/nPlease   input   the   first   number   m:");   

  00401135   push   offset   string   "/nPlease   input   the   first   number   m"...   (004260b8)   

  0040113A   call   printf   (00401530)   

  0040113F   add   esp,4   

  46:   scanf("%d",&m);   

  00401142   mov   ecx,dword   ptr   [ebp+8]   

  00401145   push   ecx   

  00401146   push   offset   string   "%d"   (004260b4)   

  0040114B   call   scanf   (004015f0)   

  00401150   add   esp,8   

  47:   

  48:   if   (   m<1   )   continue;   

  00401153   mov   edx,dword   ptr   [ebp+8]   

  00401156   cmp   dword   ptr   [edx],1   

  00401159   jge   Input+4Dh   (0040115d)   

  0040115B   jmp   Input+18h   (00401128)   

  49:   printf("/nPlease   input   the   first   number   n:");   

  0040115D   push   offset   string   "/nPlease   input   the   first   number   n"...   (0042608c)   

  00401162   call   printf   (00401530)   

  00401167   add   esp,4   

  50:   scanf("%d",&n);   

  0040116A   mov   eax,dword   ptr   [ebp+0Ch]   

  0040116D   push   eax   

  0040116E   push   offset   string   "%d"   (004260b4)   

  00401173   call   scanf   (004015f0)   

  00401178   add   esp,8   

  51:   

  52:   if   (   n<1   )   continue;   

  0040117B   mov   ecx,dword   ptr   [ebp+0Ch]   

  0040117E   cmp   dword   ptr   [ecx],1   

  00401181   jge   Input+75h   (00401185)   

  00401183   jmp   Input+18h   (00401128)   

  53:   

  54:   for(i=1,s=0;i<=n;i++)   

  00401185   mov   dword   ptr   [ebp-8],1   

  0040118C   mov   dword   ptr   [ebp-4],0   

  00401193   jmp   Input+8Eh   (0040119e)   

  00401195   mov   edx,dword   ptr   [ebp-8]   

  00401198   add   edx,1   

  0040119B   mov   dword   ptr   [ebp-8],edx   

  0040119E   mov   eax,dword   ptr   [ebp+0Ch]   

  004011A1   mov   ecx,dword   ptr   [ebp-8]   

  004011A4   cmp   ecx,dword   ptr   [eax]   

  004011A6   jg   Input+0A3h   (004011b3)   

  55:   s=s+i;   

  004011A8   mov   edx,dword   ptr   [ebp-4]   

  004011AB   add   edx,dword   ptr   [ebp-8]   

  004011AE   mov   dword   ptr   [ebp-4],edx   

  004011B1   jmp   Input+85h   (00401195)   

  56:   if   (   m   >=   s   )   

  004011B3   mov   eax,dword   ptr   [ebp+8]   

  004011B6   mov   ecx,dword   ptr   [eax]   

  004011B8   cmp   ecx,dword   ptr   [ebp-4]   

  004011BB   jl   Input+0AFh   (004011bf)   

  57:   break;   

  004011BD   jmp   Input+0C1h   (004011d1)   

  58:   else   

  59:   printf("   m   <   n*(n+1)/2,Please   input   again!/n");   

  004011BF   push   offset   string   "   m   <   n*(n+1)/2,Please   input   agai"...   (00426060)   

  004011C4   call   printf   (00401530)   

  004011C9   add   esp,4   

  60:   }   

  004011CC   jmp   Input+18h   (00401128)   

  61:   

  62:   }   

  004011D1   pop   edi   

  004011D2   pop   esi   

  004011D3   pop   ebx   

  004011D4   add   esp,48h   

  004011D7   cmp   ebp,esp   

  004011D9   call   __chkesp   (004015b0)   

  004011DE   mov   esp,ebp   

  004011E0   pop   ebp   

  004011E1   ret   8         

 

  最后,我们看到在函数末尾部分,有ret   8,明显是恢复堆栈,由于在32位C++中,变量地址为4个字节(int也为4个字节),所以弹栈两个地址即8个字节。   

  由此可以看出:在主调用函数中负责压栈,在被调用函数中负责恢复堆栈。因此不能实现变参函数,因为被调函数不能事先知道弹栈数量,但在主调函数中是可以做到的,因为

 

参数数量由主调函数确定。   

  下面再看一下,ebp-8和ebp-4这两个地址实际存储的是什么值,ebp-8地址存储的是n   的值,ebp   -4存储的是m的值。说明也是从右到左压栈,进行参数传递。   

 

  总结:在主调用函数中负责压栈,在被调用函数中负责弹出堆栈中的参数,并且负责恢复堆栈。因此不能实现变参函数,参数传递是从右到左。另外,命名修饰方法是在函数前

 

加一个下划线(_),在函数名后有符号(@),在@后面紧跟参数列表中的参数所占字节数(10进制),如:void   Input(int   &m,int   &n),被修饰成:_Input@8   

  对于大多数api函数以及窗口消息处理函数皆用   CALLBACK   ,所以调用前,主调函数会先压栈,然后api函数自己恢复堆栈。   

 

  如:   

  push   edx   

  push   edi   

  push   eax   

  push   ebx   

  call   getdlgitemtexta   

  你可以想一下,这几个寄存器中存的都是什么?   

 

  参考:msdn   

  例子为在VC6.0下debug模式下的Win32   Console反汇编代码。

 

  另:__declspec(dllexport)   声明一个导出函数,一般用于dll中   

        __declspec(dllimport)   声明一个导入函数,一般用于使用某个dll的exe中  

  附DLL里的一个.h

  #ifdef TESTDLL_EXPORTS

  #define TESTDLL_API __declspec(dllexport)//declare   special/specific

  #else

  #define TESTDLL_API __declspec(dllimport)

  #endif

 

 

大厂校招:星宸科技嵌入式面试及参考答案(5万字长文) 当一个新的硬件设备被插入系统时,内核会发送一个设备事件通知 udev,udev 会根据设备的属性和规则,为该设备创建一个合适的设备文件。通过去除不必要的驱动程序、禁用不需要的功能、选择合适的内核配置选项、优化内核编译选项和定制内核模块等方法,可以减小内核的大小和复杂性,提高系统的性能和稳定性。上半部通常是在中断关闭的情况下执行的,以确保中断处理的原子性。处理碎片化内存是内存管理中的一个重要问题,可以采用内存压缩、内存池管理、伙伴系统、首次适应算法和最佳适应算法等方法来减少内存碎片的产生,提高内存的利用率。 阅读详情

相关推荐

Zynq 【SDK裸机开发之PS】——DDR的内存分配使用详解

Zynq如果跑操作系统的话,内存管理的工作都会交给系统来操作,但是如果是裸机的话,则需要自己对DDR3的内存进行管理。

shizhibuyi1234的博客 7379

c++函数调用

函数完成任务后,如果有数值需要返回,则在声明函数时,在函数名前写好返回值类型。通常函数名以“动词+名词”的方式命名,中间以一个下划线隔开(C\C++风格)有时,一个函数还需要传入一些参数,参数列表写在函数名后的一对小括号中。一个函数就是完成一项任务的独立代码块,它以名字作为整个代码块的代表。即使没有参数需要传入,函数名后的小括号也不能省略。如果不需要返回任何值,则在函数名前写 void。参数列表是用逗号隔开的,每个参数都要注明其类型。

黑白无常的博客 1万+

从原理到实践:详解双目散斑结构光的生成与优化

本文深入解析了双目散斑结构光的生成原理与优化实践,详细介绍了散斑结构光的抗干扰性、空间编码技术及其在三维视觉中的应用。通过对比不同生成方法和技术路线,提供了参数调优指南和工程实现细节,帮助开发者掌握高效、精准的散斑生成技术。

weixin_42521856的博客 593

C++怎么调用类中的函数

在C++中,可以通过创建类的对象来调用类中的函数。

wangmengmeng99的博客 2198

SAP CO-PA数据传送避坑指南:销售开票与FI/MM记账的日常配置实操(含KEKF/KE4I/KEI2)

本文深入解析SAP CO-PA数据传送中的常见配置问题,特别是销售开票与FI/MM记账环节的实操避坑指南。通过KEKF/KE4I/KEI2等关键配置点的详细说明,帮助用户避免数据失真和重复记录,提升获利能力分析的准确性。文章结合实战案例,揭示官方文档未提及的'数据黑洞'形成机制,为SAP顾问提供实用的排雷手册。

weixin_26905487的博客 391

逆向工程实战:手把手教你破解药监局网站的动态数据加载机制(Python+Chrome开发者工具)

本文详细介绍了如何利用Python和Chrome开发者工具逆向破解药监局网站的动态数据加载机制。通过分析Ajax请求、解析JSON响应数据以及处理动态参数,帮助开发者高效采集动态加载内容,适用于爬虫开发与数据分析场景。

weixin_30832143的博客 68

VC++调用外部库函数的方法

做项目的时候,很多情况下都需要用到客户所提供的库,因为每个公司代码里识别的函数参数不相同,导致客户提供的库不能直接使用,需要再封装一层进行转化。 VC++调用外部函数其实非常的方便,因为VC++本身就可以新建一个dll项目,同时也提供获取库的函数,使用向导来新建,十分快捷。 步骤 1、使用VC++创建一个新的win32项目,然后向导里面选择dll工程。这里可以不使用空目录,让VC++自动建立一个dllmain.cpp文件。 2、在工程目录文件下(即自己工程的.cpp文件),添加外部API的接口函数,这里有

初音骑士的博客 2169

YOLO系列算法改进 | 自研篇 | C3k2融合SEFN空间增强前馈网络模块 | 去模糊和提升图像细节特征,精度涨点!| WACV 2025

YOLO系列算法改进 | 自研篇 | C3k2融合SEFN空间增强前馈网络模块 | 去模糊和提升图像细节特征,精度涨点!| WACV 2025 (以YOLO26最新目标检测模型为基础,C3k2融合SEFN空间增强前馈网络模块改进Backbone)

2502_91881744的博客 239

[c++] WINAPI

int WINAPI WINMain 中,WINAPI含义 在windef.h头文件中有如下定义: #define WINAPI __stdcall #define APIENTRY WINAPI 函数的调用方式有两种一种是PASCAL调用方式,另一种是C调用方式 使用PASCAL调用方式,函数在返回到调用者之前将参数从栈中删除,使用C调用方式,参数的删除是调用者完成的。...

XIEXINGHUA2010的博客 1388

杰理SDK入门教程(五):按键使用配置

摘要 杰理SDK提供IO按键和AD按键两种方案。IO按键通过GPIO电平检测实现,配置时需要设置板级宏定义和硬件连接,默认使用PB1引脚。AD按键基于ADC电压采样,通过电阻分压区分按键,需配置功能使能、硬件通道和键值适配。按键功能通过修改SDK中的key_table文件实现。两种方案适用于不同硬件场景,开发者可根据需求选择。

qq_42014563的博客 777

基于STM32L4XX、HAL库的DP83822 以太网收发器(PHY)驱动程序设计

一、简介:DP83822是德州仪器(TI)推出的一款低功耗、高性能10/100Mbps以太网物理层收发器(PHY)。它具有以下主要特性:支持10BASE-T和100BASE-TX以太网标准低功耗设计,适合嵌入式应用MII/RMII接口,方便与微控制器连接内置自检和诊断功能支持自动协商和手动配置工业级温度范围(-40°C至+85°C)

zhusl6688的博客 528

VC++中的函数调用惯例

导读:   我们知道在进行函数调用时,有几种调用方法,主要分为C式,Pascal式.在C和C++中C式调用是缺省的,类的成员函数缺省调用为_stdcall。二者是有区别的,下面我们用实例说明一下:   1. __cdecl :C和C++缺省调用方式   例子:   void Input( int &m,int &n);/*相当于void __cdecl Input(int &m,int &

yingfox的专栏 892

三菱FX5U-PLC建立CClink的IO通讯

最新需要用三菱的FX5U的PLC搭建一个CClink通讯,PLC做主站,控制CClink从站的IO,下面2个输入模块AJ65SBTB1-32D,两个输出模块AJ65SBTB1-32T。3、在右侧的部件,选择网络模块:FX5-CCL-MS,CC-link主站模块。依次把加入两个AJ65SBTB1-32D,两个AJ65SBTB1-32T。7、基本设置,网络配置设置,链路刷新设置,设置好下面参数,应用。6、基本设置,网络配置设置,CC-Link配置设置。8、部件选择,模块,右键,添加模块标签。

wzz418550729的博客 1002

Visual C++中函数调用方式浅探

Visual C++中函数调用方式浅探 我们知道在进行函数调用时,有几种调用方法,分为C式,Pascal式。在C和C++中C式调用是缺省的,除非特殊声明。二者是有区别的,下面我们用实例说明一下:1. __cdecl :C和C++缺省调用方式  例子:void Input( int &m,int &n);/*相当于void __cdecl Input(int &m,int &n);*/  

Flyincloud的专栏 944

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Visual C++中函数调用方式浅探 (转)

Visual C++中函数调用方式浅探 (转)[@more@]Visual C++中函数调用方式浅探 我们知道在进行函数调用时,有几种调用方法,分为C式,Pascal式。在C和C++中C式调用是缺省的,除非特殊声明。二者是有...

csd3176的博客 82

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【C++ MFC+opencv】打开文件夹中的图片并在picture控件中显示

void CmyImageDlg::OnBnClickedButtonImg() { // TODO: 在此添加控件通知处理程序代码 CString m_strPicPath; //弹出选择图片对话框 CFileDialog dlg(true,_T("*.bmp"),NULL,OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,_T(

u014077175的专栏 5271

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

__cdecl __fastcall与 __stdcall

__cdecl __fastcall与 __stdcall 调用约定: __cdecl __fastcall与 __stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数弹出栈,3)以及产生函数修饰名的方法。 1、__stdcall调用约定:函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存

sankt的专栏 2308

Visual C++中的几种函数调用方式

(本文中所有汇编代码均采用Intel语法,即dest在左边)C++中的函数被编译成汇编代码的时候,必须遵循一定的规范,如参数怎么传递,栈指针怎么增减。Visual C++中,一共有5种情况:1.__cdecl2.__stdcall3.__fastcall4.__thiscall默认情况下,是__cdecl。__cdecl 和__stdcall的区别是:__cdecl是调用者清理栈,而__s...

weixin_30765505的博客 272

VC++线程函数内怎么调用外部函数

VC++线程函数内怎么调用外部函数 1。把外部函数做成静态函数,就可以直接调用了。2。把外部函数所在的对象通过线程函数参数传到线程里面来,这样线程里可以使用此对象及其函数了。 转载于:https://www.cnblogs.com/2018shawn/p/9399356.html...

diaomo9737的博客 466

VC函数调用方式

 在windef.h头文件中有如下定义     #define   WINAPI             __stdcall     #define   APIENTRY         WINAPI         VC有两种函数调用方式   一种是__stdcall,另一种是__cdecl     函数的调用方式有两种一种是PASCAL调用方式,另一种是C调用方式     使用PASCAL调用...

WOXHLY的专栏 413

VC 在调用main函数之前的操作

在C/C++语言中规定,程序是从main函数开始,也就是C/C++语言中以main函数作为程序的入口,但是操作系统是如何加载这个main函数的呢,程序真正的入口是否是main函数呢?本文主要围绕这个主题,通过逆向的方式来探讨这个问题。本文的所有环境都是在xp上的,IDE主要使用IDA 与 VC++ 6.0。为何不选更高版本的编译器,为何不在Windows 7或者更高版本的Windows上实验呢?我...

Masimaro的专栏 1297
上一篇: c#多线程教学(5):Case 学习多线程
下一篇: linux安装软件详细解答 rpm tar.gz tar.z tar.bz2 tar.tgz .deb .bin
MagicxiaoZ
博客等级 码龄19年 5粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值