参数传递方法

参数传递方法

李纬的InsideVCL《第一章》中提到Windows定义的回调函数

typedef LRESULT (CALLBACK*WNDPROC)(HWND,UNIT,WPARAM,LPARAM)

为了加快回调函数执行的效率,Microsoft使用了CALLBACK修饰关键词来定义WNDPROC,而CALLBACK则是定义成FAR PASCAL.

那么为什么FARPASCAL就会更快执行呢?以下为我的解释

(1)cdecl:

     通常是C/C++所使用缺省的参数传递方式,它的传递方式是由右到左,而且当被调用的函数结束之后,将会由调用函数本身来清除堆栈上的参数数据。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。

(2)stdcall:

     参数传递方式,也是由右到左,但是当被调用的函数结束之后,则是由被调用函数来清除堆栈上的参数数据,Win32API所有的输出函数都是采用此中参数传递方式

(3)pascal:

     是Delphi1.0与win16API所使用的参数传递方式,它的传递方式是由左到右,而且由被调用函数来清除堆栈上的参数数据.

(4)fastcall:(delphi下关键字为register)

     是Delphi默认所使用的参数传递方式, 主要特点就是快,因为它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈)

   注:所以在引用C++动态库中的函数时,要注意参数的传递方式,一般使用stdcall.还要注意字符串类型,C++在传递字符串时,都是采用字符指针的类型(Char *),所以你在Delphi的程序中就必须使用PCHAR类型,而不是string类型.

(5)thiscall

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

(6)naked call。

当采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。(这些代码称作 prologand epilog code,一般,ebp,esp的保存是必须的).但是naked call不产生这样的代码。naked call不是类型修饰符,故必须和_declspec共同使用。

 

汇编测试

其實。你只要寫一段下去測試。看它的 asm 就知道了。

1.触发代码

TForm1.Test1Click(1,2, 3);

  begin

0044E298 6A03              push$03

0044E29A 6A02              push$02

0044E29C 6A01              push$01

0044E29E 50                 pusheax

0044E29F E8D4FFFFFF       call TForm1.Test1

end

0044E2A4 C3               ret

0044E2A5 8D4000           lea eax,[eax+$00]

 

TForm1.Test2Click(1,2, 3);

  begin

  0044E287 6A03            push $03

  0044E289 B902000000       mov ecx,$00000002

  0044E28E BA01000000      mov edx,$00000001

  0044E293 8BC3             mov eax,ebx

  0044E295 E8CEFFFFFF      call TForm1.Test2

end

0044E2B9 C3               ret

0044E2BA 8BC0            mov eax,eax

2.函数源码 

FunctionTForm1.Test1(a, b, c: Integer): Integer; stdcall;

Begin

0044E268 55               push ebp

0044E269 8BEC            mov ebp,esp

Result := a + b + c;

0044E25B 8B450C          mov eax,[ebp+$0c]

0044E25E 034510           add eax,[ebp+$10]

0044E261 034514           add eax,[ebp+$14]

end

0044E264 5D               pop ebp

0044E265 C21000           ret $0010

 

FunctionTForm1.Test2(a, b, c: Integer): Integer; register;

Begin

0044E268 55               push ebp

0044E269 8BEC             mov ebp,esp

Result := a + b + c;

0044E26B 8D0411           lea eax,[ecx+edx]

0044E26E 034508           add eax,[ebp+$08]

end

0044E271 5D               pop ebp

0044E272 C20400           ret $0004

0044E275 8D4000           lea eax,[eax+$00]

 

這样看起來。是不是就有所差別了?

 

时间: 2024-09-30 08:41:08

参数传递方法的相关文章

Linux Debugging(三): C++函数调用的参数传递方法总结(通过gdb+反汇编)

         上一篇文章<Linux Debugging:使用反汇编理解C++程序函数调用栈>没想到能得到那么多人的喜爱,因为那篇文章是以32位的C++普通函数(非类成员函数)为例子写的,因此只是一个特殊的例子.本文将函数调用时的参数传递方法进行一下总结.总结将为C++普通函数.类成员函数:32位和64位进行总结.         建议还是读一下Linux Debugging:使用反汇编理解C++程序函数调用栈,这样本文的结论将非常容易理解,将非常好的为CoreDump分析开一个好头.而且

Android intent之间复杂参数传递方法详解_Android

本文详细讲述了Android intent之间复杂参数传递方法.分享给大家供大家参考,具体如下: Intent是Activity与Activity之间,Activity与Service之间传递参数的介质,而这两种通常实现的是Java基本对象类型和String的传递. 在实际项目中,页面之间传值,除了以上几种,经常还有传递Object对象.List类型.List<Object>类型和全局变量等等的需求.本文就是介绍怎么传递这几种类型的参数. 一.传递List<String>和List

Struts2学习笔记(5)-参数传递方法_java

参数传递即将参数传输到程序后台中,后台可能做一些处理,然后再将内容存入数据库之类嗒! 参数传递的方法较多,一一说明如下. 1.Action中直接参数法 有如下的index.jsp文件 复制代码 代码如下: <?xml version="1.0" encoding="GB18030" ?>  <%@ page language="java" contentType="text/html; charset=GB18030&

C#和asp.net中链接数据库中参数的几种传递方法实例代码_实用技巧

复制代码 代码如下: #region 参数传递方法第一种     //参数设置方法(第一种)      //SqlParameter sp = new SqlParameter("@Name", str_Name);      //SqlParameter sp2 = new SqlParameter("@Pwd", str_Pwd);      //cmd.Parameters.Add(sp);      //cmd.Parameters.Add(sp2);  #

JAVA面向对象之方法

一.方法的重载 Java允许在同一个类中定义几个同名的方法,只要这些方法具有不同的参数列表,即方法的参数类型不同,或方法参数个数不同.这种做法称为方法的重载.方法的重载包括以下几种: 1.成员方法的重载 重载方法的参数表必须不同,参数的不同主要是参数的类型.顺序.个数不同. public class MethodOverload { public int sum(int a, int b) { System.out.println("sum(int a, int b)"); retur

Java 交换两个变量的数值实现方法_java

一.参数传递方法 为解决标题问题,首先介绍参数传递方法.目前各类程序设计语言的参数传递方法主要有三种: 1.按值传递 2.按引用传递 3.按指针传递 其中按值传递表示方法(函数)接收的是调用者提供的变量的拷贝,不改变参数的值:按引用传递表示方法(函数)接收的调用者提供的变量地址:按指针传递表示方法(函数)接收的是调用者提供的指针的拷贝,不改变指针的值和地址,但可以改变指针所指向的地址. 二.Java参数传递方法 Java提供的参数传递方法,很遗憾只有一种,按值传递.也就是说,方法得到的是所有参数

在窗体间传递参数的几种常用办法

在实际开发应用中,常常需要在窗体间传递参数.常用的几种参数传递方法有如下几种: 1.使用openargs 在调用的窗体使用如下语句: docmd.openform "被调用的窗体", , , , , , "参数值" 在被调用的窗体使用me.openargs即可获取传递过来的参数 2.使用全局变量 先设置一个全局变量,例如:gstrPara, Public gstrPara as string 在调用之前传递参数值给这个全局变量 gstrPara="参数值&

java的clone实现

理解了实现clone()方法背后的所有细节后,便可创建出能方便复制的类,以便提供了一个本地副本:   //: LocalCopy.java // Creating local copies with clone() import java.util.*; class MyObject implements Cloneable { int i; MyObject(int ii) { i = ii; } public Object clone() { Object o = null; try { o

【Servlet】根据MVC思想设计用户登陆、用户注册、修改密码系统

MVC不是一种像C.JAVA的编程语言,也不是一种像Ajax,Servlet的技术,只是一种如同面向对象一样编程思想.近年来MVC一直很火,赞者批者有之,然后大篇幅的文章很多,可是简明扼要的简单MVC的例子几乎没有.在JSP领域一直向鼓风机地猛吹SSH如何如何地好,一直怒批JSP,Servlet等如何如何差.其实使用JSP+Servlet同样可以利用MVC思想来完成一个系统.下面用一个烂得不能再烂的例子,你步入网页编程必须学会的东西,登陆.注册.修改密码系统,来说明这种编程思想. 一.基本目标