Pascal is counting backwards not upwards? so wierd

  • A+
Category:Languages

http://rextester.com/OXRFB95557

The watch shows the counter j going down not up...any ideas why? thanks

program NEACardTrick;  {$APPTYPE CONSOLE}  uses   SysUtils,   Math;  type   Tcards = array[1..21] of string;     var    cards: Tcards = ('H A', 'H 2', 'H 3', 'H 4', 'H 5', 'H 6', 'H 7',              'S A', 'S 2', 'S 3', 'S 4', 'S 5', 'S 6', 'S 7',              'D A', 'D 2', 'D 3', 'D 4', 'D 5', 'D 6', 'D 7');    shuffledCards:Tcards;    i,j,y, x: integer;   function get_cards(var cards: array of string): Tcards;     begin       y := 1;   Repeat     Randomize;     x := RandomRange(1,21);     If cards[x] <> 'Done' then     begin       shuffledCards[y] := cards[x];       y := y + 1;       cards[x] := 'Done';     end       Until y >= 21;           result := shuffledCards; end;  procedure PrintCards(var shuffledCards: Tcards); var   j: integer; begin   for j := 1 to 21 do     writeln(shuffledCards[j]); end;  begin       get_cards(cards);   PrintCards(shuffledCards);   readln; end. 

 


Your observation in Delphi 7 regarding the j: integer variable in procedure PrintCards() is exactly as it is shown in a debugger watch. However, rest assured, the for loop works correctly.

In your code, you have given j two duties, 1) to act as a loop control and 2) to act as a index to the shuffledCards[] array.

The compiler translates your delphi code to as efficient (but, of course, correct) machine code it can. Arranging a loop so, that detecting ZF (Zero Flag) as a loop terminating condition, instead of explicit comparison with a const value, is one way to improve efficiency. Therefore, duty 1) is solved by having a decrementing loop control, register esi in this case (see disassembly below).

For the second duty, the esi register can not be used, as it counts in the wrong direction. So, another register, ebx is used for duty 2). It is setup as a pointer to the first element of the array (the element with index 1). Then at every round in the loop ebx is incremented to point to the next element.

Here's a disassembly of the PrintCards() procedure:

Project2.dpr.38: begin 0040876C 53               push ebx 0040876D 56               push esi 0040876E 57               push edi 0040876F 8BF8             mov edi,eax  Project2.dpr.39: for j := 1 to 21 do 00408771 BE15000000       mov esi,$00000015    // Initialize loop control  00408776 8BDF             mov ebx,edi          // set up pointer to array Project2.dpr.40: writeln(shuffledCards[j]); 00408778 A160934000       mov eax,[$00409360]  // loop start 0040877D 8B13             mov edx,[ebx] 0040877F E8B4B8FFFF       call @WriteOLString 00408784 E8CFA5FFFF       call @WriteLn 00408789 E8B69EFFFF       call @_IOTest  0040878E 83C304           add ebx,$04          // advance array element pointer Project2.dpr.39: for j := 1 to 21 do 00408791 4E               dec esi              // decrement loop control 00408792 75E4             jnz -$1c             // jump if not zero to loop start  Project2.dpr.41: end; 00408794 5F               pop edi 00408795 5E               pop esi 00408796 5B               pop ebx 00408797 C3               ret 

Put a break point on line 39 and then run. When stopped at line 39, call up the CPU view (View - Debug Windows - CPU or Ctrl-Alt-C). Then single step (F8) and follow the changes of the registers, to see for yourself

The debugger watch for j shows the value of esi, therefore you see the value going down from 21 to 1 (actually you can see the final 0 show up right after the last time dec esi is executed).

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: