The short answer is due to compiler optimization. Long answer:
In Pascal code, the integer I has two (actually three) goals. Firstly, it is the control variable of the cycle (or cycle counter), that is, it determines how many times the cycle starts. Secondly, it acts as an index of array a . And in the first loop, it also acts as the value assigned to the elements of the array. When compiled into machine code, these roles are processed by different registers.
If optimization is specified in the compiler settings, the compiler creates code that reduces the control variable from the initial value to zero, if possible, without changing the final result. This happens because comparison with a non-zero value can be avoided, thereby accelerating.
The next time you disassemble the first loop, you will see that the roles of variable I treated as:
- The
eax register acts as a loop control variable, and the value is assigned to array elements - Register
edx - pointer to an array element (with the addition of 4 (bytes) per move)
disassembly:
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
Since eax has two roles, it must count up. Note that to control the loop, three commands are required for each loop: inc eax , cmp eax, $00000100 and jnz $005db69d .
When disassembling the second cycle, the roles of the variable I processed similarly in the first cycle, except that I not assigned to the elements. Therefore, loop control only works as a loop counter and can be started down.
- Register
eax - loop control variable - Register
edx - pointer to an array element (with the addition of 4 (bytes) per move)
disassembly:
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
Note that in this case, only two commands are needed to control the loop counts: dec eax and jnz $005db6b5 .
In Delphi XE7, in the Clock window, the variable I displayed during the first cycle as increasing values, but in the second cycle E2171 Variable 'i' inaccessible here due to optimization . In earlier versions, I remember that it showed decrement values, which I think you see.