Delphi 汇编

1.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)。

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

附代码:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  a,b,c,d:Word;
  BYTE1:Byte;
  word1:Word;
  int1:Integer;

(*------------------------------------------------------------------------*)

function add2value(x1:Integer;x2:Integer):Integer ; (*用汇编写的函数*)
asm
  mov eax,x1;
  add eax,x2;
  mov @result,eax;    (* 返回值为 @result *)
end;

(*------------------------------------------------------------------------*)

begin

  try
    { TODO -oUser -cConsole Main : Insert code here }
    asm
      mov a,'A';
      mov b,'B';
      mov c,'C';
      mov d,'D';

    end;
      Writeln(chr(a) + chr(b) + chr(c) + chr(d));

      BYTE1 := $FF;
      Writeln(BYTE1 and $0F);
      BYTE1 := $0F;
      Writeln(BYTE1 or $F0);

      word1 := 1;
      asm
        mov ax,word1
        sal ax,1     (*左移1位*)
        mov &word1,ax
      end;

      Writeln(' i = ' + IntToStr(word1));

      int1 := add2value(12,32);
      Writeln(int1);

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

  readln;
end.

转载于:https://www.cnblogs.com/findumars/p/5034714.html

你可能感兴趣的:(Delphi 汇编)