• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Delphi与汇编

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
转自:http://blog.csdn.net/hugoon/archive/2007/02/08/1504966.aspx


 

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

  Delphi的位操作

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

  * 按位的逻辑操作:

  Delphi中的ANDORNOT可不仅仅只对逻辑表达式有作用,它们还可以操作数;

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

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

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

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

  * 移位操作

  Delphi提供了SHLSHR进行移位左移和右移:

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

  * Delphi中的数

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

  Delphi中:Shortint8位)、Smallint16位)、Longint32位)、Integer32位)、Int6464位)是有符号数;而Byte8位)、Word16位)、Longword32位)是无符号数。它们之间可以像C一样强制转换。例如:Smallint类型的-1转换成Word类型就是65535。转换方法是Word(-1)。

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

  Delphi的嵌入式汇编

  Delphi中提供了几乎全部常用汇编指令的支持:MOVJEJMPCMPSHLSHRSALSARPOPPUSHHLT……自己去查吧。至于INT也能识别,不过非法操作或死机可别找我(在最早的Windows95中用Delphi 3似乎可以正确运行中断,但Windows 95 OEMWindows 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的嵌入式汇编是没有必要的(除非你自己要使用PushPop),因为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 Iax语句放入I变量所在地址返回值。最后显示I 的值是2

  2.独立的汇编程序段

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

  即:整型数据:8位的用AL返回,16位的用AX返回,32位的用EAX返回;

  实型:用ST0)返回

  指针:用EAX返回

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

  变量:可用@Result返回

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

  function _Sum(X, Y: Integer): Integer;

   asm

  MOV EAX,X //32位的数放入EAX

  ADD EAX,Y //进行加法运算

  MOV @Result,EAX //返回XY

   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 WindowsCPU窗口跟踪。

  OK!就谈到这
-----------------------------------
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个已内,
将分别使用eaxedxecx,超过3个参数部分将使用堆栈。返回参数的
存放视长度而定,例如8位用al返回,16位用ax32位用eax64位用用两个
32
位寄存器edx:eax,其中eax是低位。


效率:本例asm大约比delphic50%



鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
matlab绘制心形函数发布时间:2022-07-18
下一篇:
【转载】手把手教你用C#调用MATLAB函数 - GIS_Zhou发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap