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).