unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;implementation{$R *.dfm}{实现乘2}
function mul_int(I: Integer): Integer;
begin
  //ok
  asm
    mov edx, 2
    mul edx
    ret
  end;  {==============问题代码=============
  asm
    mov ecx, 2
    mul ecx
    ret
  end;
  ===============问题代码=============}
end;procedure TForm1.btn1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(mul_int(9)));
end;end.
问题描述:
1)用BASM实现乘2这个功能的时候,使用ECX就是出错,使用EDX正常,我查过资料,EAX、ECX、EDX都可以修改的啊。
为什么程序会出错?

解决方案 »

  1.   

    问题代码反汇编(于mul_int的begin处下端点):
    Unit1.pas.29: begin
    0045BF60 53               push ebx//编译器为何会加这句而edx的情况下却不加,这个有待进一步研究...
    Unit1.pas.39: mov ecx, 2
    0045BF61 B902000000       mov ecx,$00000002
    Unit1.pas.40: mul ecx
    0045BF66 F7E1             mul ecx
    Unit1.pas.41: ret
    0045BF68 C3               ret//返回时堆栈不平衡,即使注释掉此ret,也不会返回正确结果
    Unit1.pas.44: end;
    0045BF69 8BC3             mov eax,ebx//正确结果被ebx覆盖
    0045BF6B 5B               pop ebx
    0045BF6C C3               ret 
    我觉得在非全汇编过程中,不要出现ret指令,并且要把最后结果赋予@Result。
    所以改成这样:
    function mul_int(I: Integer): Integer;
    begin
      asm
        mov ecx, 2
        mul ecx
        mov @Result,eax
      end;
    end;
    如果用全汇编的:
    function mul_int(I: Integer): Integer;
    asm
        mov ecx, 2
        mul ecx
        ret//ret可以省略,编译器会自动加上
    end;