begin
  For i:=0 to 10 do 
  begin
  a:=b+C;
  d:=a+b;
  end;
  result:=d;
  end;这样的一段代码。想在delphi里面内联汇编应该怎么写。请指教。

解决方案 »

  1.   

    代码写错了。应该是begin
      For i:=0 to 10 do  
      begin
      a:=b+i;
      d:=c+b;
      end;
      result:=d;
      end;
      

  2.   

       变量
    var a,b,c,i:integer;
      

  3.   

    mov eax,c
    add eax,b
    ret
      

  4.   

    有result,应该是函数吧。function func1(var a, b, c: integer): integer;
    asm
      mov edx,[edx]
      mov ecx,[ecx]
      add,ecx,edx
      add edx,55
      mov [eax],edx
      mov eax,ecx
    end;
      

  5.   

    a b c d 的初始值是什么?
    你最好给出完整的函数体。
    另外,按照你上面个的代码,无论循环多少次 d 的值都不会变,并且a在赋值之后也没有使用过,为什么要这样?
      

  6.   

      我只是想知道for 循环在delphi用asm 的写法。所以随便写了个例子。
      

  7.   

    大致明白楼主想要什么,我写了一段汇编实现累加的程序。
    function Add(i:integer):integer;
    var
      iOut:integer;
    begin
      asm
        pushad
        cmp eax,i
        jbe @fun2
        mov eax,1
        mov ebx,0
      @fun1:
        add ebx,eax
        inc eax
        cmp eax,i
        jbe @fun1
        mov iOut,ebx
        jmp @fun3
      @fun2:
        mov iOut,0
      @fun3:
        popad
      end;
      result:=iOut;
    end;应该是你想要的。
      

  8.   

    for循环,一般用loop,然后ecx存放循环次数,循环方式就用跳转段地址吧
      

  9.   

    这个事情我做过.
    你先写个for循环,然后下断点,查看cpu,就可以看delphi是怎么写的了
      

  10.   

    mov eax, $0000000b  //$0000000b 是循环次数
    @@loop:
    //循环体,在循环体中,不要改变 eax 的值 
    dec eax
    jnz @@loop:
    相当于
    for i := 0 to 10 do
    begin
      //循环体
    end;
      

  11.   

    loop好象效率很低,所以绝大部分人都习惯性,自己dec,然后cmp/test,再用jxx指令跳转。
      

  12.   

    效率其实是一样的,但是loop只能实现减1计数,而且转移范围只能在相对指令指针-128~127范围之内,所以编译器都不喜欢用它,一般只有手工编码才用它。
      

  13.   

    ??
    @@loop
    只是一个标号啊
    后面有dec eax
    jnz @@loop
      

  14.   


    很多书上都这么说,但实际上是一种误解。
    loop慢是因为它的吞吐量低,意味着一条loop指令执行之后要过若干时钟周期(典型PIV 2~4,PM 6,Core/Core2 5,i7 4)才能再执行另一个loop指令。这样单独测试loop指令的话肯定是慢的。
    不过loop是循环控制指令,实际中不会连续使用的,一般情况下,比较这两种循环:
    1:
    mov ecx,n
    @@loop:
      ; 一段程序
      sub ecx,1   ; add ecx,-1
      jnz @@loop2:
    mov ecx,n
    @@loop:
      ; 一段程序
      loop @@loop只要这一段程序指令数不要太少,2的效率不会比1差,甚至在较新的架构下还要快一点点。
      

  15.   

    To DelphiGuy:我不是信书的,虽然不是非常明显,但还是能够测试出来。没有去深究具体原因。所以只是当成一种习惯性的写法。
      

  16.   

    http://www.agner.org/optimize/
    拿i家和a家最新的i7和k10来说:
    i7中,“Conditional jump”的µops fused domain(The number of µops at the decode, rename, allocate and retirement stages in the pipeline. Fused µops count as one.)是1,而loop的是6,sub/dec的闭着眼也能猜出来肯定是1。在i7上,一条loop顶上正常的3组了。
    k10中,Jcc的Ops(Number of macro-operations issued from instruction decoder to schedulers)是1,loop的是7,不用看sub/dec的肯定还是1。在k10上,一条loop比3组还多。而且loop还必须得用ecx寄存器,除了指令长度短点儿没别的好处。不知道你的“快一点点”的依据是什么,测试代码又是什么?loop要真那么管用,为什么现在编译器生成的代码干嘛不用指令长度更短的loop?或者直接贴gcc/icc的优化结果也行,别自己空口无凭的还让别人给证据。
      

  17.   

    你这人还真是奇怪,吃了枪药了吗?我会“自己空口无凭的还让别人给证据”,笑话。“依据是什么,测试代码又是什么?”我在17楼已经写得很清楚了,依据就是实测,你以为那“一段代码”我没写出来就是我编的?还真是幼稚。“为什么现在编译器生成的代码干嘛不用指令长度更短的loop?”,我在14楼已经写了,您的视力有问题吗?:)您对我有什么意见尽管直说,我忘记什么时候打击过您这号人了。
      

  18.   

    附一个简单的测试程序:
    {$APPTYPE CONSOLE}
    program test;uses SysUtils, Windows;const
      TestCount = 100000000;
      TestLoop = 10;  Test1Title = 'SUB/Jcc Loop';
      Test2Title = 'LOOP Loop';  ResultMsg1 = 'pass %d: %-0.5f seconds';
      ResultMsg2 = 'Average %-0.5f seconds';type
      TTestProcedure = procedure;procedure Test1;
    asm
      mov ecx,TestCount
    @@0:
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;  sub ecx,1
      jnz @@0
    end;procedure Test2;
    asm
      mov ecx,TestCount
    @@0:
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;
      shr eax,15; shr eax,15; shr eax,15; shr eax,15;  loop @@0
    end;procedure TestProc(const P: TTestProcedure; const Msg: string);
    var
      T, T1: double;
      Ticks: cardinal;
      i: integer;
    begin
      writeln(Msg);  T := 0;
      for i := 1 to TestLoop do
        begin
          Ticks := GetTickCount;
          P;
          Ticks := GetTickCount - Ticks;
          T1 := Ticks / 1000.0;
          T := T + T1;
          writeln(Format(ResultMsg1, [i, T1]));
        end;
      writeln('-------------------------');
      writeln(Format(ResultMsg2, [T / TestLoop]));
      writeln;
    end;{ main }
    begin
      TestProc(Test1, Test1Title);
      TestProc(Test2, Test2Title);
    end.
      

  19.   

    中间那段shr eax,15写别的代码也可以(注意不要用ecx),但是不能太短,怎么也得20~30条指令,也不能太长,loop指令有short跳转的限制。大致来说,在Pentium4上,多次测试的情况下,两者没有超过测试误差(毫秒级)之外的差别,在PM和Core上,使用loop指令表现出快一点的倾向(我在一个PM 1.7GHz的笔记本和一台Xeon E5335 2.0GHz服务器上做的测试),不过差距甚微,10次平均大约有几毫秒到10几毫秒的领先(1亿次循环)。
    有一点例外,在Pentium4上,如果将sub ecx,1换成dec ecx,有快一点的倾向。“不要使用loop指令”这种说法,我记得最著名的是出自Abrash的《Graphics Programming Black Book》(中译本名《图形程序开发人员指南》,我在98年买过一本),不过需要注意的是Abrash是针对Pentium及以前的处理器说的,从Pentium以来的处理器变化很大,不能死抱着“真理”不放。以我的经验,intel有一种逐步改进的倾向,在设计指标有富余的情况下,它会每次把以前的慢指令改快一点,积累一段时间,可能就焕然一新了,典型的如idiv指令。至于AMD,我一直不使用它家的产品,缺少发言权。
      

  20.   

    您这测试也太逗了吧……要测 loop vs sub/jnz,结果每段还有4*9个shr指令,这两组个要测试的指令的总执行时间都不到10%了,您这结果还有多大意义?
    把您中间的代码都换成:  shr eax, 15; db $66, $0f, $1f, $84, $00; dd $00一组12个字节和你的一行代码长度相同,µops/Ops变一半,latency变1/4,throughput在>=k8的amd平台上少一半,在intel的>=p6平台上略减。别说你不知道shr后面那堆东西是干嘛用的。枪药我是没吃过,只不过一向看不惯没证据就瞎说的,或是也不知道自己水平够不够,就敢拿所谓测试结果忽悠人的
      

  21.   

    顺便再贴一下代码改了一下之后在我的i5 750/win7 x64/2g ram/d2010运行的结果:
    SUB/Jcc Loop
    pass 1: 0.29700 seconds
    pass 2: 0.29600 seconds
    pass 3: 0.28100 seconds
    pass 4: 0.29600 seconds
    pass 5: 0.28100 seconds
    pass 6: 0.31200 seconds
    pass 7: 0.29700 seconds
    pass 8: 0.28000 seconds
    pass 9: 0.29700 seconds
    pass 10: 0.29600 seconds
    -------------------------
    Average 0.29330 secondsLOOP Loop
    pass 1: 0.71800 seconds
    pass 2: 0.70200 seconds
    pass 3: 0.70200 seconds
    pass 4: 0.70200 seconds
    pass 5: 0.70300 seconds
    pass 6: 0.71700 seconds
    pass 7: 0.70200 seconds
    pass 8: 0.70200 seconds
    pass 9: 0.71800 seconds
    pass 10: 0.70200 seconds
    -------------------------
    Average 0.70680 seconds
      

  22.   

    您的意思是单独测LOOP指令?!笑话,那还用得着测试吗?您没看见我在17楼写的吗“这样单独测试loop指令的话肯定是慢的”。我说的意思就是loop做循环控制的效率并不比SUB/Jcc差,您还能懂这个基本概念吧。中间的循环代码是一致的,循环的效率反映的就是循环控制指令的实际效果。您确实“不知道自己水平够不够”,我前面写得很清楚,您自作聪明,搞出个“自己空口无凭的还让别人给证据”,我现在给您证据了,您又扯开中间的循环代码占时间多了!建议不要再出来丢人现眼了好不好。
      

  23.   

    seamour,你从一开始(20楼)就没搞明白(或者摆着明白装糊涂)我和僵哥讨论的问题是什么,我并没有讨论loop指令本身的快慢,而是讨论的是它作为一段代码的循环控制的效率问题,这才是它的实际用途。见17楼。别的就没什么好说的了,各自保留看法吧。
      

  24.   

    看来你真的是完全不懂啊
    sub/dec+jnz跟36个shr比,总时间只占了1/18,就算能测出差异来也都不到5%了,能看出什么来?实际上由于CPU的乱序执行和分支预测,那两条指令根本一点儿就不占你的所谓调试时间,你那些“几毫秒”的差距根本就是误差。我给的版本同样是12*9字节,只不过指令换了一下,产生的下降幅度我也给出了,loop的能力差一下就显示出来了。所以说,你说那么多都是没用的,您还不如直接说div的速度跟mul一样更有意思一些(给不懂汇编的人看的:实际上div最慢能多花10倍左右的时间)。只要多来些 cache missing,现在CPU的能力保证能把它们测成一样的速度。你以为自己在那死鸭子嘴硬,懂的人就看不出来到底谁对谁错了?况且楼主的代码一共也没几条指令,只要不是miss cache,算下来连改成9条shr的开销都不到,你还在14楼说“效率其实是一样的”,睁眼说瞎话说习惯了?
      

  25.   

    我在17楼已经把表达的意思说得很清楚了,还需要再一次次教育你吗?比较您在20楼和29楼的说法,先是在那比较loop和sub/jcc本身(千万别说你没有啊),就象豆腐西施杨二嫂那样“很以为功”,跳出来打击别人,后来又改口成中间代码占时太多(那你还不是在测试loop本身吗),谁在那“死鸭子嘴硬”呢?我说的“效率其实是一样的”在17楼已经解释得很清楚了,那时候您还没发言吧?自己没看明白别人的话栽了面子,又自己树个靶子“宣布胜利”,很有趣吗?可以休矣。
      

  26.   

    不好意思,我要你的测试代码的目的也很明确,错误的结论建立在错误的实验的基础上。你以为在不到120字节内,居然有36条既不能 register rename、又不能乱序执行的指令,这种情况在实际中很常见么?你到底是想测loop还是shr?你要是说测后者,那我得说这个代码的质量很不错,能让其它代码几乎不起作用,并且每条shr都实打实的执行,不会被乱序执行之类的干扰。您搞了个极端情况当普遍情况,我“栽什么面子”啊?好像您又援引又“测试”的,就能把人家搞优化器包括intel的人都否定了似的:一帮老古董,居然还跟不上形势,还在用dec/sub+jnz而不是loop处理near跳转,难道连这么简单的优化都做不出来么?您是要教育我怎样死鸭子嘴硬么?不好意思,我不需要,错了就错了呗,也没啥大不了的,改正了以后不再犯就完了,跟您这样我才觉得掉价呢。
      

  27.   

    在实际的循环代码中,通常不会太短小,以至于前一个loop指令的延迟压住了后一个loop指令,循环主体占用的时间是主要的,所以一般情况下使用loop指令是没有问题的(但是它的使用限制条件比较多,所以编译器一般不爱用它)。这就是我在17楼解释的意思。我从来就没有否定loop指令本身慢这个事实,没错吧,见17楼(“这样单独测试loop指令的话肯定是慢的”)。
    是您非要歪曲我的意思,树立一个“我的观点”来打击我,事实上,您从一开始的动机和目的就是不端正的,您不要以为别人看不出来。和您斗嘴也没什么意思。这样吧,我为我在17楼的发言负责,您为您在20楼的发言负责,谁没看明白别人的话就跳出来打击别人,或者为保住面子歪曲别人的意思,死鸭子嘴硬,睁眼说瞎话,谁就是TMD 傻X,生孩子没P眼,这样好不好?您满意了吗?:)
      

  28.   

    说了不斗嘴的,那就稍微谈一点“技术”,否则上来就被人喷个“也不知道自己水平够不够,就敢拿所谓测试结果忽悠人的”,那就对不起观众了。注意,由于我不是处理器设计者,也无从得知某型处理器的内部具体实现,加上个人水平也有限(不怪别人喷,怪我自己),所以下述看法仅仅是我的个人推测,虽然我是经过认真思考+实测得出的结论,但是不能保证它就是对的。如果有人相信了我的结论,结果被证明是错的,因此被别人喷了,我不能承担他精神受创的责任。显而易见的事实:LOOP指令是先减计数器rcx/ecx/cx,再根据计数器的值非0还是0来判断要不要跳转,所以它的内部实现可能对转移进行了优化,获得非常高的分支预测成功率,有多高呢,应该比add/sub/cmp指令修改标志位,再配合Jcc指令的分支预测成功率要高。
    这就是为什么严格等价的循环结构,随着循环次数的增加(比如我贴的测试例子,把1亿次循环改成3亿次),出现向着有利于使用LOOP指令的循环倾斜的趋势,尽管优势不明显,但是千万不要草率就断定是“误差”(为什么很容易想明白吧)。