Delphi的嵌入式汇编语言与Windows函数调用
点击次数:43 次 发布日期:2008-11-09 08:39:06 作者:源代码网
|
源代码网推荐 性能非常卓越。但是在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 源代码网推荐 源代码网供稿. |
