首页 | 社区 | 博客 | 招聘 | 文章 | 新闻 | 下载 | 读书 | 代码
亲,您未登录哦! 登录 | 注册

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

打印文章

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

本栏文章均来自于互联网,版权归原作者和各发布网站所有,本站收集这些文章仅供学习参考之用。任何人都不能将这些文章用于商业或者其他目的。( Pfan.cn )

编程爱好者论坛

本栏最新文章