主页 > 编程资料 > Delphi >
发布时间:2015-09-22 作者:网络 阅读:130次

 

Delphi 与汇编入门

// 作者 万一

http://www.cnblogs.com/del/category/121079.html

function add(x, y: Integer): Integer;
var count: Integer;
begin
     asm
        MOV EAX, x      {把 x 值放入寄存器 EAX}
        MOV ECX, y      {把 y 值放入寄存器 ECX}
        ADD EAX, ECX    {把 EAX + ECX 的值放入 EAX}
        MOV count, EAX  {把 EAX 的值给变量 count}
     end;
     Result := count; {返回值}
     //asm 中每个语句换行即可分句, 无须 ; 在这里加上也没有问题}
end;

procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
begin
     i := add(2, 8); // EPrivilege with message Privileged instruction
     Memo1.Lines.Add(format('%d', [i]));
end;

procedure Proc(w, x, y, z:integer);
var a, b, c, d, e, f, g: Integer;
begin
     asm
        mov a, eax
        mov b, ebx
        mov c, ecx
        mov d, edx
     end;
     Form1.Memo1.Lines.Add(format('%d   %d   %d   %d',[a, b, c, d]));
end;

function Proc2(w, x, y, z: Integer): Integer;
var a, b, c, d, e, f, g: Integer;
begin
     asm
        mov a, eax
        mov b, ebx
        mov c, ecx
        mov d, edx
     end;
     //Form1.Memo1.Lines.Add(format('%d   %d   %d   %d',[a, b, c, d])); // 如果加上此句注释则返回值为 0 ,不加此句则为 11
end;

procedure TForm1.Button3Click(Sender: TObject);
var i: Integer;
begin
     Proc(11, 22, 33, 44);
     // 前三个参数通过寄存器传递, 其他参数存于栈.
     // EAX 先接受第一个参数再接受返回值, EBX ECX 接受后面两个参数.
     // 0    33   22
     i := Proc2(11, 22, 33, 44);
     Memo1.Lines.Add(format('%d', [i])); // 11
end;

procedure TForm1.Button4Click(Sender: TObject);
var i: Integer;   // 4 字节、32 位
    w: Word;      // 2 字节、16 位
    b1, b2: Byte; // 1 字节、 4 位
begin
{
              EAX 32 位
  --------------------------------
                  AX 16 位  |
                  ----------------
                  |AH 8 位|AL 8 位|
}
     := maxint;
     := 0;
     b1 := 0;
     b2 := 0;
     asm
        mov eax, i  // EAX 寄存器 返回类型 Integer、LongWord、AnsiString、Pointer、Class
        mov w, ax   // AX 寄存器 返回类型 SmallInt、Word
        mov b1, ah
        mov b2, al  // AL 寄存器 返回类型 Char、Byte
     end;
     Form1.Memo1.Lines.Add(Format('w=%d   b1=%d   b2=%d',[w, b1, b2]));
// w=65535; b1=255; b2=255 给 ecx 赋值后, cx ch cl 都有值了!

     := 8;
     := 0;
     b1 := 0;
     b2 := 0;
     asm
        mov ebx, i
        mov w, bx
        mov b1, bh
        mov b2, bl
     end;
     Form1.Memo1.Lines.Add(Format('w=%d   b1=%d   b2=%d',[w, b1, b2]));
// w=8   b1=0   b2=8

     := 60000;
     := 0;
     b1 := 0;
     b2 := 0;
     asm
        mov edx, i
        mov w, dx
        mov b1, dh
        mov b2, dl
     end;
     Form1.Memo1.Lines.Add(Format('w=%d   b1=%d   b2=%d',[w, b1, b2]));
// w=60000   b1=234   b2=96
end;

function AsmFun(x: Integer): Integer;
asm
   add eax, eax // 相当于 Result := x * 2;
   // eax 可以获取第一个参数, 同时又是函数的返回值, 所以可以如此简洁!}
end;

procedure TForm1.Button5Click(Sender: TObject);
var i: Integer;
begin
     i := AsmFun(8);
     Memo1.Lines.Add(format('%d', [i])); // 16
end;

function Fun(x: Integer): Integer;
asm
   mov ecx, &x       // 在汇编中访问 Delphi 的变量 x 可以使用 & 操作符
   dec ecx           // 汇编中的 dec 是减 1 指令, 和 Delphi 是一样的}
   mov @Result, ecx  // 在本例中去掉 @ 也可以, 暂时不知怎么回事
end;

procedure TForm1.Button6Click(Sender: TObject);
var i: Integer;
begin
     i := Fun(9);
     Memo1.Lines.Add(format('%d', [i])); // 8
end;

function Fun2(var x,y: Integer): Integer;
asm
   mov eax, x         {现在 eax 中只是 x 的地址}
   mov eax, [eax]     { [eax] 是取值, 是不是类似于 P^ ? }
   mov edx, y
   add eax, [edx]
   //mov @Result, eax {在这里, 这句可有可无}
end;


procedure TForm1.Button7Click(Sender: TObject);
var a, b: Integer;
begin
     a := 1;
     b := 8;
     a := Fun2(a, b);
     Memo1.Lines.Add(IntToStr(a)); {9}
end;

// 常量可以在汇编语句中运算
function Fun3: Integer;
const
  a = 11;
  b = 5;
asm
   mov eax, a - b
end;

//变量不可以, 方法中的参数也都属于变量

function Fun4: Integer;
var x, y: Integer;
asm
   mov x, 11
   mov y, 5
   //mov eax, x-y {不能这样使用}
   mov eax, x
   sub eax, y     {sub 是减, 就像 add 是加一样}
end;

procedure TForm1.Button8Click(Sender: TObject);
var i: Integer;
begin
     i := Fun3;
     Memo1.Lines.Add(format('%d', [i])); // 6
     i := Fun4;
     Memo1.Lines.Add(format('%d', [i])); // 6
end;

// 使用应该保护的 ebx 寄存器
function Fun5(x: Integer): Integer;
{
前面提到 32 位的寄存器有: EAX EBX ECX EDX ESP EBP ESI EDI;
其中, EAX ECX EDX 是自由使用的.
那么剩下的 EBX ESP EBP ESI EDI 五个寄存器就是应该保护的!
所谓保护, 并不是不可以使用,
而是在使用前先把其中的值寄存在另外一个地方, 用完后再恢复其值.
如果不这样做, 有可能会发生意想不到的错误.
}
asm
   push ebx // push 是入栈指令, 栈就是系统自动分配的内存
   mov  ebx, x
   inc  ebx
   mov  @Result, ebx
   pop  ebx // pop 是出栈指令, 也就是恢复 ebx 寄存器原来的值
end;

procedure TForm1.Button9Click(Sender: TObject);
var i: Integer;
begin
     i := Fun5(8);
     Memo1.Lines.Add(format('%d', [i])); // 9
end;

//十进制
function Fun6: Integer;
asm
   mov eax, 255
end;

//十进制数后面也可以加个 D(大小写无关)
function Fun7: Integer;
asm
   mov eax, 255D
end;

//二进制后面加 B(大小写无关)
function Fun8: Integer;
asm
   mov eax, 11111111B
end;

//八进制后面加 O(大小写无关)
function Fun9: Integer;
asm
   mov eax, 377O
end;

//十六进制前面加 $
function Fun10: Integer;
asm
   mov eax, $FF
end;

//十六进制也可以是后面加 H(大小写无关)
function Fun11: Integer;
asm
   mov eax, 0FFH {使用这种方法, 数字的首位不能是字母, 不然会被认为成标识符}
end;

//非汇编代码的 Delphi 只支持用 $ 表示十六进制
function Fun12: Integer;
begin
     Result := $FF;
end;

procedure TForm1.Button10Click(Sender: TObject);
begin
     with Memo1.Lines do
     begin
          Add(format('%d', [Fun6])); // 255
          Add(format('%d', [Fun7])); // 255
          Add(format('%d', [Fun8])); // 255
          Add(format('%d', [Fun9])); // 255
          Add(format('%d', [Fun10])); // 255
          Add(format('%d', [Fun11])); // 255
          Add(format('%d', [Fun12])); // 255
     end;
end;

procedure TForm1.Button11Click(Sender: TObject);
var ByteNum: Byte;
begin
{ 逻辑非 Not:
  not 1 = 0;
  not 0 = 1;
}
  //赋值 11111111B (255) 取反:
     asm
        mov al, 11111111B {eax 包含 ax; ax 包含 al; al 是 eax 的低八位}
        not al            {给 11111111 取反会得到 00000000}
        mov ByteNum, al   {把寄存器 al 中的值给变量 ByteNum}
     end;
     Memo1.Lines.Add(IntToStr(ByteNum)); {0}

逻辑或 Or:
  1 or 0 = 1;
  0 or 1 = 1;
  1 or 1 = 1;  // 逻辑异或 1 Xor 1 = 0;
  0 or 0 = 0;
}
     asm
        mov al, 10101010B {170}
        mov cl, 01010101B {85}
        or  al, cl
        mov ByteNum, al
     end;
     Memo1.Lines.Add(IntToStr(ByteNum)); {255}

逻辑与 And:
  1 and 1 = 1;
  1 and 0 = 0;
  0 and 1 = 0;
  0 and 0 = 0;
}
     asm
        mov al, 11111111B {255}
        mov cl, 11111111B {255}
        and al, cl
        mov ByteNum, al
     end;
     Memo1.Lines.Add(IntToStr(ByteNum)); {255}

{ 逻辑异或 Xor:
  1 Xor 0 = 1;
  0 Xor 1 = 1;
  1 Xor 1 = 0;  // 常用来置 0 , 与逻辑或不同:   1 or 1 = 1;
  0 Xor 0 = 0;
}

     asm
        mov al, 11111111B {255}
        mov cl, 11111111B {255}
        xor al, cl
        mov ByteNum, al
     end;
     Memo1.Lines.Add(IntToStr(ByteNum)); {0}
end;

procedure TForm1.Button12Click(Sender: TObject);
var ByteNum: Byte;
begin
     //右移 shr
     asm
        mov al, 10000000B {128}
        shr al, 1         {shr 10000000 一次会得到 01000000}
        mov ByteNum, al
     end;
     Memo1.Lines.Add(IntToStr(ByteNum)); {64; shr 相当于 ÷2}

     //左移 shl
     asm
        mov al, 00000001B {1}
        shl al, 1            {shl 一次会得到 00000010}
        shl al, 1            {shl 两次会得到 00000100}
        mov ByteNum, al
     end;
     Memo1.Lines.Add(IntToStr(ByteNum)); {4; shl 相当于 ×2}
end;

procedure TForm1.Button13Click(Sender: TObject);
var B: Byte;
    W: Word;
    C: Cardinal;
begin
     {Byte 是1字节(8位)无符号整型, 其最大值是 111111112}
     asm
        mov B, 11111111B;
     end;
     Memo1.Lines.Add(IntToStr(B)); {255}

     {Word 是2字节(16位)无符号整型, 其最大值是 11111111 111111112}
     asm
        mov W, 1111111111111111B;
     end;
     Memo1.Lines.Add(IntToStr(W)); {65535}

     {Cardinal 是4字节(32位)无符号整型, 其最大值是 11111111 11111111 11111111 111111112}
     asm
        mov C, 11111111111111111111111111111111B;
     end;
     Memo1.Lines.Add(IntToStr(C)); {4294967295}

     {它们的最小值都是 0}
end;

procedure TForm1.Button14Click(Sender: TObject);
var I: Integer;
begin
     // Integer 类型是4字节(32位)有符号整数, 最高位是符号位, 如果是正数, 符号位是 0、负数的符号位是1
     // 所以 Integer 的最大值是: 01111111 11111111 11111111 111111112
     asm
        mov I, 01111111111111111111111111111111B;
     end;
     Memo1.Lines.Add(IntToStr(I));           {2147483647}

     //有符号整数的负数等于相同正数的反码 + 1; Integer 最大值是:
     //01111111 11111111 11111111 111111112; 其反码是:
     //10000000 00000000 00000000 000000002; 反码 + 1 以后是:
     //10000000 00000000 00000000 000000012
     asm
        mov I, 10000000000000000000000000000001B;
     end;
     Memo1.Lines.Add(IntToStr(I));           {-2147483647}

     //那 Integer 的最小值是多少呢?
     //应该是: 10000000 00000000 00000000 000000002
     asm
        mov I, 10000000000000000000000000000000B;
     end;
     Memo1.Lines.Add(IntToStr(I));           {-2147483648}

     //11111111 11111111 11111111 111111112 是?
     asm
        mov I, 11111111111111111111111111111111B;
     end;
     Memo1.Lines.Add(IntToStr(I));           {-1}

     //Integer 类型的 0 在内存中是: 00000000 00000000 00000000 000000002
     asm
        mov I, 00000000000000000000000000000000B;
     end;
     Memo1.Lines.Add(IntToStr(I));           {0}

     //Integer 类型的 10010 的二进制是: 00000000 00000000 00000000 011001002
     asm
        mov I, 00000000000000000000000001100100B;
     end;
     Memo1.Lines.Add(IntToStr(I));           {100}

     //算 Integer 类型的 -10010:
     //00000000 00000000 00000000 01100100 的反码是:
     //11111111 11111111 11111111 10011011 ; 反码 + 1 以后是:
     //11111111 11111111 11111111 10011100
     asm
        mov I, 11111111111111111111111110011100B;
     end;
     Memo1.Lines.Add(IntToStr(I));           {-100}
end;

 


关键字词: