zoukankan      html  css  js  c++  java
  • 参数传递方法(用Delphi的汇编代码解释)

    参数传递方法

    李纬的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 https://blog.csdn.net/shuaihj/article/details/7162190
  • 相关阅读:
    内存管理 初始化(二)bootmem位图分配器建立 及 使用
    生成asm-offset
    内存管理(一)
    mongodb多表查询(附带pymongo实例)
    python3将docx转换成pdf,html文件,pdf转doc文件
    pymongo 目标计算机积极拒绝
    python中常用的推导(字典推导和列表推导)
    python2和python3的编码问题
    scrapy处理需要跟进的url
    flask上传文件时request.files为空的解决办法
  • 原文地址:https://www.cnblogs.com/findumars/p/9113424.html
Copyright © 2011-2022 走看看