• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Delphi的嵌入式汇编语言与Windows函数调用_Delphi

delphi 搞代码 4年前 (2018-08-09) 175次浏览 已收录 0个评论

  Delphi是一种基于Pascal的面向对象的可视化程序设计工具,功能强大,编译速度极快,
  性能非常卓越。但是在Delphi中,却不像c语言一样能方便地利用函数指针,对已知地址
  的函数进行调用。
  
    如在Windows环境中用C语言编程,经常碰到如下形式的函数调用:
  
   …
  
   FARPROC lpGetversion;
  

http://www.gaodaima.com/?p=65738Delphi的嵌入式汇编语言与Windows函数调用_Delphi

   …
  
   lpGetversion=GetProcAddress(hinst,"getVersion");
  
   (*lpGetversion)();
  
   …
  
    而在Delphi中,对用GetProcAddress获得的32位函数地址,如果采用类似C语言的
  形式调用函数指针,便会在编译时碰到错误,根本无法通过。如:
  
   例1 直接地址调用,错误是91号;
  
   lpGetversion; { error 91 ″:=″ expected}
  
   例2 带空参数直接地址调用,错误是91号;
  
   lpGetversion(); { error 91 ″:=″ expected}
  
   例3 间接地址调用,错误是43号;
  
   lpGetversion^; { error 43 iiiegal assignment}例4 带空参数间接地址调用,错误是43号;
  
   (lpGetversion^)(); { error 43 iiiegal assignment}
  
    在Windows系统的编程实践中,如钩子(HOOK)函数的编写和某些未公开的函数的
  调用等,必须用函数指针来调用函数,那么该怎么调用呢?
  
    答案是必须采用嵌入式汇编语言来调用函数指针,因为在Delphi的Help中,明确指
  出:The only use for procedural pointer is to pass it to an assembly language routine or to use it in  
  a inline statement。所以,如果我们获得了DLL中的函数地址,想利用它来调用该函数,只
  需在程序中插入一小段很简单的汇编程序,就能调用了。举例如下:
  
    …
  
    var {声明函数指针lpGetVersion}
  
    lpGetVersion :TFARPROC;
  
    …
  
    lpGetVersion:=getProcAddress(GetModuleHandle(′kernel′),′getversion’);
  
    if lpGetVersion=nil then exit; {获得模块kernel 中的函数getVersion的指针lpGetVersion}
  
    ….
  
    asm {用汇编形式调用函数getVersion}
  
    call lpGetVersion {不用;  用; 也可以}
  
    end;  
  
    … 
  
     现举一个简单的例子,在按钮上单击一下,利用汇编语言调用getversion函数得到
  Windows和DOS 的版本号:
  
    unit Getveru;
  
    interface
  
    uses
  
    SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  
    Forms, Dialogs, StdCtrls;
  
    type
  
    TForm1 = class(TForm)
  
     Button1: TButton;
  
     Label1: TLabel;
  
     Label2: TLabel;
  
     Label3: TLabel;
  
     procedure Button1Click(Sender: TObject);
  
    private
  
     { Private declarations }
  
    public
  
     { Public declarations }
  
    end;
  
    var
  
    Form1: TForm1;
  
    implementation
  
    {R *.DFM}
  
    procedure TForm1.Button1Click(Sender: TObject);
  
    var
  
    lpGetVersion:TFARPROC;
  
    version:longint;
  
    versionLowWord:word;
  
    versionHighWord:word;
  
    begin
  
    lpGetVersion:=getprocAddress(GetModuleHandle  
  
    (′kernel′), ′getversion′);  
  
    {GETVERSION 函数在模块 KERNEL中}
  
    {lpGetVersion 存放GETVERSION 的地址}
  
    if lpgetVersion=nil then exit;
  
    label1.caption:=intTostr(selectorof(lpgetversion))
  
    +’:’ +intTostr(offsetof(lpgetversion));{取32位地址的高16位用selectorof}
  
    {取32位地址的低16位用offsetof }
  
    asm {嵌入式汇编语言标记}
  
    call lpgetversion
  
    mov versionLowWord,ax
  
    {ax寄存器放Windows版本号}
  
    mov versionHighWord,dx  
  
    {dx寄存器放DOS版本号}
  
    end;
  
  
  
    label2.caption:=′Windows Version ′+
  
    intTostr(lobyte(versionLowWord))
  
    +′.′+intTostr(hibyte(versionLowWord)); {取16位 2进制数 的低8位用lowbyte}  
  
    {取16位 2进制数 的高8位用hibyte}  
  
    label3.caption:=′MS-DOS Version ′+
  
     intTostr(hibyte(versionHighWord))
  
     +′.′+intTostr(lobyte(versionHighWord));
  
    end;
  
    end 

欢迎大家阅读《Delphi的嵌入式汇编语言与Windows函数调用_Delphi》,跪求各位点评,若觉得好的话请收藏本文,by 搞代码


喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址