帕斯卡倒计数而不是向上?太奇怪了

Top*_*les 3 delphi delphi-7

http://rextester.com/OXRFB95557

手表显示计数器j没有下降...任何想法为什么?谢谢

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.
Run Code Online (Sandbox Code Playgroud)

Tom*_*erg 6

您在Delphi 7中对j: integer变量的观察与procedure PrintCards()调试器手表中显示的完全一致.但是,请放心,for循环正常工作.

在你的代码中,你有j两个职责,1)充当循环控件,2)充当shuffledCards[]数组的索引.

编译器将您的delphi代码转换为有效(但当然是正确的)机器代码.因此,安排一个循环,检测ZF(零标志)作为循环终止条件,而不是与const值进行显式比较,是提高效率的一种方法.因此,通过esi在这种情况下使用递减循环控制寄存器来解决占空比1)(参见下面的反汇编).

对于第二个任务,esi不能使用寄存器,因为它指的是错误的方向.因此,另一个寄存器ebx用于职责2).它被设置为指向数组的第一个元素的指针(索引为1的元素).然后在循环中的每一轮ebx递增以指向下一个元素.

这是PrintCards()程序的反汇编:

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
Run Code Online (Sandbox Code Playgroud)

在第39行放置一个断点,然后运行.在第39行停止时,调用CPU视图(查看 - 调试Windows - CPU或Ctrl-Alt-C).然后单步(F8)并按照寄存器的变化,自己查看

调试器手表j显示的值esi,所以你看到的值从21到1下降(实际上你可以看到最终的0,显示了最后一次后立即dec esi执行).