zoukankan      html  css  js  c++  java
  • 参数传递方法(Delphi1.0与win16API使用pascal方法,即从左到右)

    参数传递方法
    李维的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]

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

    http://blog.csdn.net/shuaihj/article/details/7162190

  • 相关阅读:
    Ubuntu在下面LAMP(Linux+Apache+MySQL+PHP) 开发环境的搭建
    直接插入排序、折半插入排序、Shell排序、冒泡排序,选择排序
    java插入字符串
    bash,bg,bind,break,builtin,caller,compgen, complete,compopt,continue,declare,dirs,disown,enable,eval,exec,expo
    socket用法
    org.jsoup.select.Selector
    达达技术
    CentOS 6.4 文件夹打开方式
    shell加法
    shell统计
  • 原文地址:https://www.cnblogs.com/findumars/p/5345762.html
Copyright © 2011-2022 走看看