参数传递方法(用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]
這样看起來。是不是就有所差別了?
参数传递方法(用Delphi的汇编代码解释)的更多相关文章
- 浅析VS2010反汇编 VS 反汇编方法及常用汇编指令介绍 VS2015使用技巧 调试-反汇编 查看C语言代码对应的汇编代码
浅析VS2010反汇编 2015年07月25日 21:53:11 阅读数:4374 第一篇 1. 如何进行反汇编 在调试的环境下,我们可以很方便地通过反汇编窗口查看程序生成的反汇编信息.如下图所示. ...
- 使用WinDbg获得托管方法的汇编代码
概述:有时候,我们需要查看一个托管方法的汇编指令是怎么样的.记得在大学的时候,我们使用gcc -s和objdump来获得一个c程序代码的汇编指令.但是对于.NET程序来说,我们肯定无法轻松地获得这些内 ...
- 参数传递方法(Delphi1.0与win16API使用pascal方法,即从左到右)
参数传递方法李维的InsideVCL<第一章>中提到Windows定义的回调函数typedef LRESULT (CALLBACK*WNDPROC)(HWND,UNIT,WPARAM,LP ...
- GCC 嵌入汇编代码
The format of basic inline assembly is very much straight forward. Its basic form is 基本汇编嵌入格式如下: asm ...
- 关于调用约定(cdecl、fastcall、、thiscall) 的一点知识(用汇编来解释)good
函数调用规范 当高级语言函数被编译成机器码时,有一个问题就必须解决:因为CPU没有办法知道一个函数调用需要多少个.什么样的参数.即计算机不知道怎么给这个函数传递参数,传递参数的工作必须由函数调用者 ...
- linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...
- 在汇编代码中调用C函数
对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard),ATPCS主要是定义了函数呼叫时参数 ...
- GCC生成的汇编代码
假设我们写了一个C代码文件 code.c包含下面代码: int accum = 0; int sum(int x, int y){ int t = x + y; accum += t; return ...
- 理解ATL中的一些汇编代码(通过Thunk技术来调用类成员函数)
我们知道ATL(活动模板库)是一套很小巧高效的COM开发库,它本身的核心文件其实没几个,COM相关的(主要是atlbase.h, atlcom.h),另外还有一个窗口相关的(atlwin.h), 所以 ...
随机推荐
- es6 --- Generator 函数
第一部分,ES6 中的 Generator 在 ES6 出现之前,基本都是各式各样类似Promise的解决方案来处理异步操作的代码逻辑,但是 ES6 的Generator却给异步操作又提供了新的思路, ...
- Statement和ResultSet
statement.prepareStatement.callableStatement的使用 1.带?参数的使用prepareStatement.这也是使用最多的. 2.不带参数,例如查所用,不需要 ...
- 【DRF版本】
目录 使用内置的URLPathVersioning类 使用自定义的版本控制类 首先,我们开发的项目会有多个版本. 其次,我们的项目版本会随着更新越来越多,我们不可能因出了新版本就不维护旧版本了. 那么 ...
- 交换工资 SQL
- 用Ngen指令加快C#程序的启动速度
用Ngen指令加快C#程序的启动速度 由于C#是使用实时 (JIT) 编译器编译原始程序集.因此第一次运行C#程序(或Dll)时,程序的启动非常慢.为了提高用户的体验,可以用Microsoft的供的本 ...
- 构建自己的AngularJS - 作用域和Digest(一)
作用域 第一章 作用域和Digest(一) Angular作用域是简单javascript对象,因此你能够像对其它对象一样加入属性.然而,他们也有一些额外的功能:用于观測数据结构的变化.这样的观察能力 ...
- LinearLayout-控件不显示
今天Mms遇到了一个问题,布局如下 <RelativeLayout android:layout_width="match_par ...
- 比较s+=4;和s=s+4;的不同
1.s=s+4: public class Test { public static void main(String[] args){ short s=3; // s=s+4; //描述 资源 路径 ...
- java DSA Signature Sign And Verify
SignatureSignAndVerify import java.security.KeyPair; import java.security.KeyPairGenerator; import j ...
- node:json与csv互转
[单个文件的转化] 1.安装json2csv模块将json转成csv jsonToCSV.js var fs = require('fs'); const Json2csvParser = r ...