Delphi - 循环的秘密
技术交流,DH讲解.
哈哈,我承认我是标题党.
最近看天书夜读里面是对C语言的代码反汇编,不错,可惜Delphi没有这样的书,那我们自己动手吧.
首先进入For循环了.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Function TestFor( a, b: Integer ): Integer ; Var I: Integer ; Begin Result := a + b ; For I := 0 To 49 Do Result := Result + I ; End ; {$R *.dfm} Procedure TForm1 . btn1Click( Sender: TObject ) ; Begin ShowMessage( IntToStr( TestFor( 1 , 2 ) ) ) ; End ; |
反汇编代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 | Unit4 . pas .28 : Result := a + b ; 00523AE0 03D0 add edx,eax //执行a+b,但是我很奇怪为什么不用add eax,edx 这样最后就不用执行那句mov eax,edx了,节约一句 Unit4 . pas .29 : For I := 0 To 49 Do 00523AE2 33C0 xor eax,eax //清除eax,来充当I这个循环变量 Unit4 . pas .30 : Result := Result + I ; 00523AE4 03D0 add edx,eax //累计和,并把循环变量+1,这里就是循环体的执行代码 00523AE6 40 inc eax Unit4 . pas .29 : For I := 0 To 49 Do 00523AE7 83F832 cmp eax, $32 //边界比较,不等于就跳回去,继续执行循环体代码. 00523AEA 75F8 jnz $00523ae4 //看来还是再写个函数来看看 Unit4 . pas .31 : End ; 00523AEC 8BC2 mov eax,edx 00523AEE C3 ret |
对比书中C的反汇编代码,Delphi反汇编出来的代码很精简,虽然声明了局部变量,但是函数直接用寄存器代替了.很好.
书中C循环体先直接用Jmp跳过去与临界变量比较,然后再来看是否执行循环体,而改变循环变量它用了add eax,1,然后再把eax传给栈上面的I.
后来我尝试改成0 to -1 Delphi编译器会识别出来,然后不会添加任何循环代码到函数中去的.
接下来是do循环,也就是Repeat
1 2 3 4 5 6 7 8 9 10 11 | function TestRepeat(a,b: Integer ): Integer ; var I: Integer ; begin Result:=a + b; I:= 0 ; repeat Result:= Result + I; Inc(I); until I = 50 ; end ; |
反汇编代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Unit4 . pas .30 : Result:=a + b; 00523AE0 03D0 add edx,eax Unit4 . pas .31 : I:= 0 ; 00523AE2 33C0 xor eax,eax Unit4 . pas .33 : Result:= Result + I; 00523AE4 03D0 add edx,eax Unit4 . pas .34 : Inc(I); 00523AE6 40 inc eax Unit4 . pas .35 : until I = 50 ; 00523AE7 83F832 cmp eax, $32 00523AEA 75F8 jnz $00523ae4 Unit4 . pas .36 : end ; 00523AEC 8BC2 mov eax,edx 00523AEE C3 ret |
我们发现反汇编代码和For是一样的.
这段代码就和VC反编译出来的差不多了,先执行循环体然后再比较边界.
好,看看while呢?
1 2 3 4 5 6 7 8 9 10 11 12 | Function TestWhile(A, B: Integer ): Integer ; Var I: Integer ; Begin Result:= A+ B; I:= 0 ; While I< 50 Do Begin Result:= Result+ I; Inc(I); End ; End ; |
反汇编代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Unit4 . pas .38 : Result:= A+ B; 00523AE0 03D0 add edx,eax Unit4 . pas .39 : I:= 0 ; 00523AE2 33C0 xor eax,eax Unit4 . pas .42 : Result:= Result+ I; 00523AE4 03D0 add edx,eax Unit4 . pas .43 : Inc(I); 00523AE6 40 inc eax Unit4 . pas .40 : While I< 50 Do 00523AE7 83F832 cmp eax, $32 00523AEA 7CF8 jl $00523ae4 Unit4 . pas .45 : End ; 00523AEC 8BC2 mov eax,edx 00523AEE C3 ret |
我晕,居然还是一样的.也就是Delphi里面3种循环执行效率是一样的吧.
而VC同样是先初始化循环变量,然后无条件跳转到边界检测,然后才执行循环体代码.
循环就这么多,以后该是条件判断
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步