Delphi与汇编


======================================================
注:本文源代码点此下载
======================================================

我一直认为delphi功能与c++相比毫不逊色,提供了丰富的控件和类、全部api以及嵌入的汇编。最近小弟在把c版的huffman压缩改用delphi写时,顺便“研究”了一下delphi的位操作和嵌入式汇编,利用嵌入汇编我们可以得到高效的程序代码,完成一些delphi没有提供的底层功能。借贵报一方宝地与大家分享我的“研究”。

delphi的位操作

每个学习c的朋友都会被告之c是“中级语言”,其位操作非常方便,而pascal之流只适用于教学。但是delphi中提供了一组位操作,可别以过去对pascal的态度看delphi。

* 按位的逻辑操作:

delphi中的and、or、not可不仅仅只对逻辑表达式有作用,它们还可以操作数;

and:按位与,如:1 and 2其结果为0

or:按位或,如:1 or 2其结果为3

not:按位取反:如not 1其结果对于有符号数是-2,对于无符号数是65534

另外,还有按位异或xor:如:1 xor 2结果为3

* 移位操作

delphi提供了shl和shr进行移位左移和右移:

例如:2 shr1表示2按位右移一位结果为1。

* delphi中的数

既然有位的操作就一定涉及到数的类型:是有符号数(头一位用0和1表示正负)还是无符号数。

delphi中:shortint(8位)、smallint(16位)、longint(32位)、integer(32位)、int64(64位)是有符号数;而byte(8位)、word(16位)、longword(32位)是无符号数。它们之间可以像c一样强制转换。例如:smallint类型的-1转换成word类型就是65535。转换方法是word(-1)。

怎样,够全吧^_^!什么还不够……!?delphi还有一招,接招吧……

delphi的嵌入式汇编

delphi中提供了几乎全部常用汇编指令的支持:mov、je、jmp、cmp、shl、shr、sal、sar、pop、push、hlt……自己去查吧。至于int也能识别,不过非法操作或死机可别找我(在最早的windows95中用delphi 3似乎可以正确运行中断,但windows 95 oem、windows 98就不对了,大概是16位模块的问题,还搞不清楚)。

* 嵌入式汇编的格式

delphi是使用asm……end来标志汇编语句

如:asm

mov al,1

mov bl,al

end;

* 可操作的寄存器

delphi可用汇编管理以下寄存器:

32位寄存器eax ebx ecx edx esp ebp esi edi

16位寄存器ax bx cx dx sp bp si di

8位寄存器al bl cl dl ah bh ch dh

16位段寄存器cs ds ss es

以及协处理器寄存器堆栈 st

* 使用汇编前的工作

教汇编的老师一再强调使用汇编要保存寄存器现场(保存使用前的寄存器状态,使用push压栈和pop从栈中弹出),不过这一切对于delphi的嵌入式汇编是没有必要的(除非你自己要使用push和pop),因为delphi已经帮你做了,不必担心会使数据丢掉。

* delphi嵌入式汇编的使用方式

1.在一般函数过程中使用汇编

汇编程序段可以嵌套于其它过程中:如:

procedure tform1.button1click(sender: tobject);

var i:smallint;

begin

i:=1;

asm

mov ax,i

sal ax,1

mov &i,ax

end;

showmessage(inttostr(i));

end;

这个程序段是把16位的变量i进行左移,然后把结果用mov &i,ax语句放入i变量所在地址返回值。最后显示i 的值是2。

2.独立的汇编程序段

汇编程序段也可以单独写成函数或过程。这就涉及到参数的传递与结果的返回。首先delphi对于函数的返回有一个约定:

即:整型数据:8位的用al返回,16位的用ax返回,32位的用eax返回;

实型:用st(0)返回

指针:用eax返回

长字符串:用eax返回其所在地址

变量:可用@result返回

例如:一个用汇编的求和函数

function _sum(x, y: integer): integer;

asm

mov eax,x //把32位的数放入eax

add eax,y //进行加法运算

mov @result,eax //返回x+y

end;

一个把字符转化为大写的函数例子

function _upcase( ch : char ) : char;

asm

cmp al,`a'

jb @@exit

cmp al,`z'

ja @@exit

sub al,`a' -`a'

@@exit:

end;

值得注意的是第二个例子中,没有象第一个那样把参数用语句放到寄存器中,这是由于delphi中默认的把byte(char)类型放在al中,不需要用mov语句,但是这种函数不能是类的成员,否则结果会出错。

3.在汇编中调用其它过程

汇编语句中的call语句,可以用于调用其它过程,既可以是其它汇编程序段也可以是delphi中的标准过程:

例如:假设新建一个窗体并在上面加了一个按钮,在click事件中写入以下代码

procedure tform1.button1click(sender: tobject);

begin

showmessage(`ok');

end;

再写一个过程_x

function tform1._x(var i:smallint):integer;

asm

call button1click

end;

执行_x的结果就可以显示消息框。

* 汇编的调试

编好了程序,没错,还好,如果有错,就得用到调试工具:如变量的跟踪、断点、堆栈查看……对于汇编还可以用view菜单的debug windows的cpu窗口跟踪。

ok!就谈到这,希望对使用delphi的朋友有点帮助。(成都 阿杰)

++++++++++++++++++++++++++++++++++++++++++++

delphi嵌入式汇编一例

来源:ether's blog

用delphi写的程序,把x指针指向的4个字节次序颠倒过来:

function toulong(x: pchar): longword;

begin

result := (longword(x^) shl 24) or

(longword((x + 1)^) shl 16) or

(longword((x + 2)^) shl 8) or

(longword((x + 3)^));

end;

以下是用delphi的嵌入式汇编写法:

function toulong(x: pchar): longword;

asm

mov esi,eax

mov ax,[esi]

xchg ah,al

shl eax,16

mov ax,[esi+2]

xchg ah,al

end;

说明:默认情况下,delphi使用“register”方式,若参数在3个已内,

将分别使用eax、edx和ecx,超过3个参数部分将使用堆栈。返回参数的

存放视长度而定,例如8位用al返回,16位用ax,32位用eax,64位用用两个

32位寄存器edx:eax,其中eax是低位。

效率:本例asm大约比delphi或c快50%。


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值