• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

Delphi-调侃调用方式

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

技术交流,DH讲解.

本随笔,就自己一心得+笔记,而自己水平有限,所以本文也可能是水文.哈哈
讲解前先来个表格:有条件的朋友可以看加密解密(第三版)一书,哈哈,我书还是买了一些的.

方式 传值方向 传值位置 谁来平衡堆栈 备注
_cdecl 从右到左 直接压栈 调用者 默认C++的
_stdcall 从右到左 直接压栈 函数本身 Win32 API
register 从左到右 adc寄存器然后压栈 函数本身 Delphi默认的
pascal 从左到右 直接压栈 函数本身  
safecall       同stdcall
不同调用有什么区别呢?
function TestStdcall(a,b:Integer):Integer ;stdcall;
var
  c:Integer;
begin
  c:=a+b;
  if c>2*a then
    Dec(c,b)
  else
    Dec(c,a);
  Result:=c;
end;

function TestCdecl(a,b:Integer):Integer ;cdecl;
var
  c:Integer;
begin
  c:=a+b;
  if c>2*a then
    Dec(c,b)
  else
    Dec(c,a);
  Result:=c;
end;

function TestRegister(a,b:Integer):Integer ;
var
  c:Integer;
begin
  c:=a+b;
  if c>2*a then
    Dec(C, B)
  Else
    Dec(C, A);
  Result:= C;
End;
{$R *.dfm}

Procedure TForm4.FormCreate(Sender: TObject);
Var
  C: Integer;
Begin
  C:= TestStdcall(5, 6);
  ShowMessage(IntToStr(C));
  C:= TestCdecl(5, 6);
  ShowMessage(IntToStr(C));
  C:= TestRegister(5, 6);
  ShowMessage(IntToStr(C));
End;

代码都一样,我们来看看执行时候有什么不一样的地方呢?
第一个TestStdcall:

我们看见先压6再压5,也就是从右到左压栈.函数内部:

先将栈里面的参数取出来放到ecx和edx中,最后清除栈Ret 8;
stdcall很明显了.

接下来看cdecl调用方式吧.

也是先压6再压5,但是我们看到最后面add esp,8,这个就是平衡栈了,因为我们压入了2个Integer,8个字节.
函数内部:

还是先从栈里面去参数到寄存器,最后直接ret咯.

接下来是Delphi默认的方式:

将5传入eax,6传入edx,它这里虽然现传的6,但是我们要注意寄存器的顺序应该是 eax,edx,ecx,如果还有多余的参数再压栈.
函数内部:

晕这个例子没有选好,因为参数没有用到栈,所以不存在栈平衡,我改一下...

从压栈的顺序我们再一次看出来了,是从左到右的,先压的8.

释放参数压栈用的空间,ret 8;

最后改一下,来看看Pascal调用方式,这个是Delphi1.0时候用的:

从左到右压栈的.

细心的朋友会发现这次没有讲栈里面东西取到寄存器中去,主要因为这次运算太简单了.哈哈,最后自己清除压的栈.

为什么要了解这些?
答案肯定是为了程序能够正常的工作了.这个问题...

如果声明和调用的方式不一样会怎么样?
1 走错路.如果只是从左到右和从右到左弄错了,程序能运行,只是参数a被当成参数b来用,也就是结果可能不对.
2 走上不归路.因为我们知道堆栈里面保存了函数的返回地址这些,但是如果我们调用方式不一样就可能造成堆栈被破坏了,程序无法正常返回,就会报错了.

ok,个人理解.


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
DelphiXE5forandroid图片缩放和拖动处理发布时间:2022-07-18
下一篇:
MATLAB文本注释及特殊符号的表示 - 那抹阳光1994发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap