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)
您在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执行).
| 归档时间: |
|
| 查看次数: |
239 次 |
| 最近记录: |