使用Delphi的basm (2006-11-30 21:49:51)
分类:Type Code
delphi
bbs/keylife/iblog_show.asp?xid=25303
由于Delphi是基于真正编译器的编程环境,因此可以把汇编语言代码嵌入Object Pascal的过程和函数中。这种能力主要得益于Delphi内建了汇编程序(BASM)。在
学习BASM之前,首先应该清楚在Delphi程序中什么时候需要用汇编语言。虽然,能嵌入汇编语言代码是很让人兴奋的事情;但有时,使用BASM也会变成坏事。不过,如果能遵守下列的BASM的规则,就会写出更好、更简捷而且更可移植的代码。
◆. 只要能够利用Object Pascal 语言实现的事情就不要用汇编语言完成。例如:
不要用汇编语言编写串口通信的例程,因为Win32 API提供了串口
通信的函数。
◆. 不要过分依赖汇编语言来优化程序。汇编语言代码虽然比Object Pascal 语言代码稍快一些,但在可读性和可维护性上要差许多。另外,
Delphi的优化编译器能使代码更优化,其效果并不亚于手工编写的汇编语言代码。
◆. 应该总是对汇编语言代码进行注释。因为,代码可能会被别的
程序员阅读;而且,在没有注释的情况下,即使自己读起来也会感到困难。
◆. 不要使用BASM来访问机器硬件。虽然Windows95/98对此宽容些,但Windows NT对此绝对禁止。
◆. 尽量把汇编语言代码封装在Object Pascal语言的过程或函数中。这样会使代码可读性更强,并且更易于移植到其他开发平台。
一、BASM是如何
工作的
在Delphi程序中使用汇编语句要比想像的简单。事实上,它只需要先键入关键字asm,然后直接输入汇编语句,最后加上end就行了。如下面代码所示:
var
i: integer;
begin
i := 0;
asm
mov eax, i
inc eax
mov i, eax
end;
{i现在已加1}
end;
以上程序片断声明了一个变量i并把初始化为0。然后,将变量i移至寄存器eax中,把这个寄存器加上1后,再把寄存器的值返还给变量i。示例不仅演示了BASM是多么容易使用,而且还
演示了汇编语句中如何访问Pascal的变量。
二、简易的参数访问
不仅访问全局变量以及过程或函数中声明的局部变量是非常容易的,而且,访问传递给过程或函数的参数也同样很方便。
请看下列代码:
procedure Foo(I: Integer);
begin
{一些代码}
asm
mov eax, I
inc eax
mov I, eax
end;
{I现在已加1}
{其他代码}
end;
直接通过参数的名称来访问参数的能力是很重要的,这样就不需要再通过ebp寄存器了。在一般的汇编语言过程中,必须用[ebp+4]代表I。
注意当使用BASM去访问一个传递给过程的参数时,可以只利用它的名称访问,而不需要通过ebp寄存器的偏
移来访问。这使代码更易于维护。
三、var 声明的参数
记住,如果一个参数是在一个函数或过程参数
列表中被用var声明的,它实际上是一个指针而不是值。这就是说,如果要在汇编代码中引用这个参数,一定要明确,它是一个32位的指针而不是一个值。
下面代码片断中阐述了如何利用汇编代码访问用var声明的变量:
procedure Foo(var I: Integer);
begin
{一些代码}
asm
mov eax, I
inc d
word ptr [eax]
end;
{I现在已加1}
{其他代码}
end;
四、Register 调用约定
在Object Pascal函数和过程中默认的调用约定是Register。利用这种方法传递参数可以使代码更加优化。因为编译器把头三个3 2位参数分别用eax、edx和ecx寄存器来传递。参看下面声明:
function BlahBlah(I1, I2, I3: Integer): Integer;
可以认为参数I1的值被存储在eax中,I2在edx中,I3在ecx中。
再看另一个声明:
procedure TSomeObject.SomeProc(S1, S2: PChar);
这里参数S1的值被存储在eax中,S2在edx中,隐含的self参数被存储在ecx中。
★注:根据我的经验,在一个对象的过程中,隐含的self参数是存储在eax中的;
而S1在edx中,S2在ecx中。
五、全汇编过程
Object Pascal中允许用关键字asm取代