zoukankan      html  css  js  c++  java
  • Delphi代码中嵌入ASM代码(简单明了)

    前言

      Delphi作为一个快速高效的开发平台,使用的人越来越多,但熟悉在Delphi代码中嵌入ASM代码的程序员我想不多,因为这方面的资料太少了,另一方面,它还需要有基本的汇编语言知识,关於汇编语言的教程,那实在太多了,如果你对汇编语言不熟的话,建议你下载相交的教程先读读。因此,本文假定您已经熟悉了汇编语言。
      (注,下文中的函数与过程统称为函数。)


    一.如何在Delphi程序中增加一段汇编代码?
      很简单,用asm...end把你的汇编代码封装起来,再把它放到你需要它的位置.这个需要它的位置可以是函数的begin与end之间,也可以是Program的begin与end之间,当然,好可以是initialization与end之间或finalization与end之间,一句话,任何可以放Delphi执行代码的地方。
      
      范例1:对变量X实现逻辑循环右移8位,它告诉您如何在过程程中插入一段asm代码。

      procedure Tform1.Button1Click(Sender: TObject);
      var
       X:DWORD;
      begin
       X:=$FF000000;
       ShowMessage(format('移位前: %.8X',[X]));
       asm
        MOV EAX, X
        ROR EAX, 8
        MOV X, EAX
       end;
       ShowMessage(format('移位後: %.8X',[X]));
      end;

      怎麽样,是不是很简单? 

    二.如何在汇编代码中调用函数?

      首先,需要讲一下函数的调用方式。

      在Delphi中,函数的调用方式有五种,分别是register,pascal,cdecl,stdcall以及safecall,最常用的是register及stdcall方式.如何区别这五种方式,它们之间依据三个方面来区分,第一是参数传递顺序(Parameter Order),第二是堆栈清除方(Clean-up),第三是是否以寄存器来传递参数(Passes parameters in registers?).您可以在Delphi Help中找到相关资料。

      Delphi中默认的参数传递方式是register,即不加方式声明的情况下,都是register方式.register方式的参数传递顺序是从左到右,由被调用者来清除堆栈,并且使用寄存器来传递参数。如何使用寄存器来传递参数呢?第一个参数使用EAX,第二个参数使用EDX,第三个参数使用ECX,第四个及以后的参数使用堆栈来传递,并且这些使用堆栈的参数是从左到右入栈的。

      stdcall是Windows的默认参数传递方式,它不使用寄存器来传递参数,这种方式下参数的传递顺序是从右到左,即最后一个参数第一个入栈,依次向前,按倒序入栈。

      范例2:用asm代码调用MessageBox函数,它告诉您如何在asm中调用stdcall方式的函数。
      procedure Tform1.Button2Click(Sender: TObject);
      var
       sztitle:string;
       szCaption:string;
      begin
       sztitle:='您好!';
       szCaption:='这是一个在内嵌汇编中调用stdcall类型函数的例子.';
       asm
        PUSH MB_OK+MB_ICONINformATION
        PUSH sztitle
        PUSH szCaption
        PUSH 0
        CALL MessageBox
       end;
      end;

      先来看看MessageBox函数的声明:
        function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
      这个函数的调用方式是stdcall,参数必须从右到左入栈,所以我们先将uType参数入栈,范例中该参数的值是MB_OK+MB_ICONINformATION,即PUSH MB_OK+MB_ICONINformATION,然后再将lpCaption,lpText,hWnd依次入栈.最后才使用CALL指令调用MessageBox函数。

      范例3:用asm代码调用register方式的函数.StrLen的声明为:function StrLen(const Str: PChar): Cardinal; 它的调用方式是默认的register方式.
      procedure Tform1.Button3Click(Sender: TObject);
      var
       Str:PChar;
       iLen:Integer;
      begin
       Str:='abcdefghijklm';
       asm
        MOV EAX, Str    //用EAX传递第一个参数
        CALL StrLen
        MOV iLen,EAX
       end;
       ShowMessage(IntToStr(iLen));
      end;

    http://websoso.bokee.com/4693792.html

    http://blog.csdn.net/yanjiaye520/article/details/6285267

  • 相关阅读:
    设计模式开篇——7大设计原则
    MySQL MVCC专题
    Spring常考的面试题
    HashMap常考面试题
    Equals和==的比较
    高并发编程
    一文读懂JVM
    scala实现定时任务的方法
    PLAY2.6-SCALA(十二) 表单的处理
    PLAY2.6-SCALA(十一) 模板常用场景
  • 原文地址:https://www.cnblogs.com/findumars/p/5272661.html
Copyright © 2011-2022 走看看