gpt4 book ai didi

Delphi "for ... to"语句从结束值运行到开始值

转载 作者:行者123 更新时间:2023-12-03 14:49:40 25 4
gpt4 key购买 nike

我正在 Embarcadero Delphi 2010 中编写一个简单的应用程序。包含两个周期的简单代码:

procedure TForm1.Button1Click(Sender: TObject);
var
a:array [0..255] of integer;
i:integer;
k,q:integer;
begin
k:=0;
for I := 0 to 255 do
begin
a[i]:=i;
end;

for I := 0 to 255 do
begin
q:= a[i];
k:=k+q;
end;
Label1.Caption:=inttostr(k);
end;

根据 Watch List,在第二个循环中,变量“i”从值 256 开始,到 0 (256, 255, 254, ..., 0),但数组的元素是正确的 (0, 1, 2, 3 ,...)。变量“i”仅在本地声明,没有全局变量。为什么会出现这种情况?这是正常行为吗?

最佳答案

简短的回答是因为编译器优化。长答案是:

在您的 Pascal 中代码,整数I有两个(实际上是三个)目的。首先,它是循环控制变量(或循环计数器),也就是说,它控制循环运行的次数。其次,它充当数组a的索引。 。在第一个循环中,它还充当分配给数组元素的值。当编译为机器代码时,这些角色由不同的寄存器处理。

如果在编译器设置中设置了优化,编译器会创建将控制变量从起始值递减到零的代码,如果可以这样做,而不更改最终结果。之所以这样做,是因为可以避免与非零值进行比较,从而更快。

在下面对第一个循环的反汇编中,您可以看到变量 I 的作用处理为:

  • 注册 eax充当循环控制变量和值分配给数组元素
  • 注册 edx是指向数组元素的指针(增加 4(字节)每转)

反汇编:

Unit25.pas.34: for I := 0 to 255 do
005DB695 33C0 xor eax,eax // init
005DB697 8D9500FCFFFF lea edx,[ebp-$00000400]
Unit25.pas.36: a[i]:=i;
005DB69D 8902 mov [edx],eax // value assignment
Unit25.pas.37: end;
005DB69F 40 inc eax // prepare for next turn
005DB6A0 83C204 add edx,$04 // same
Unit25.pas.34: for I := 0 to 255 do
005DB6A3 3D00010000 cmp eax,$00000100 // comparison with end of loop
005DB6A8 75F3 jnz $005db69d // if not, run next turn

eax有两个作用,必须向上计数。请注意,每个循环需要三个命令来管理循环计数: inc eax , cmp eax, $00000100jnz $005db69d .

第二个循环的反汇编中,变量 I 的作用处理方式与第一个循环类似,除了 I未分配给元素。因此循环控制仅充当循环计数器并且可以向下运行。

  • 注册 eax是循环控制变量
  • 注册 edx是指向数组元素的指针(增加 4(字节)每转)

反汇编:

Unit25.pas.39: for I := 0 to 255 do
005DB6AA B800010000 mov eax,$00000100 // init loop counter
005DB6AF 8D9500FCFFFF lea edx,[ebp-$00000400]
Unit25.pas.41: q:= a[i];
005DB6B5 8B0A mov ecx,[edx]
Unit25.pas.42: k:=k+q;
005DB6B7 03D9 add ebx,ecx
Unit25.pas.43: end;
005DB6B9 83C204 add edx,$04 // prepare for next turn
Unit25.pas.39: for I := 0 to 255 do
005DB6BC 48 dec eax // decrement loop counter, includes intrinsic comparison with 0
005DB6BD 75F6 jnz $005db6b5 // jnz = jump if not zero

请注意,在这种情况下,只需要两个命令来管理循环计数: dec eaxjnz $005db6b5 .

在 Delphi XE7 中,在 Watches 窗口中,变量 I在第一个循环期间显示为递增值,但在第二个循环期间显示为 E2171 Variable 'i' inaccessible here due to optimization 。在早期版本中,我记得它显示的是递减值,我相信您已经看到了。

关于Delphi "for ... to"语句从结束值运行到开始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35475622/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com