为什么德尔福"为"这样做?

use*_*150 1 delphi

Delphi XE2,简单代码:

function FastSwap(Value: uint16): uint16; register; overload;
asm
  bswap eax
  shr eax, 16
end;
...
type
  PPicEleHdr = ^TPicEleHdr;

  TPicEleHdr = packed record
    zero, size, count: word;
  end;
var
  count: integer;
  buf: TBytes;
begin
...
  peh := @buf[offs];
  count := integer(FastSwap(peh.count));
  for i := 0 to count - 1 do begin
Run Code Online (Sandbox Code Playgroud)

在这里,for我在CPU窗口中看到

UnitExtract.pas.279: for i := 0 to count - 1 do begin
0051E459 8B45DC           mov eax,[ebp-$24]
0051E45C 48               dec eax
0051E45D 85C0             test eax,eax
0051E45F 0F82CD000000     jb $0051e532
0051E465 40               inc eax
0051E466 8945AC           mov [ebp-$54],eax
0051E469 C745F400000000   mov [ebp-$0c],$00000000
Run Code Online (Sandbox Code Playgroud)

因此,当计数无效时0,test eax, eax(eax = $ FFFFFFFF之后dec eax)在jb通过Carry标志行动时不会影响Carry标志.有什么我不明白使用的东西for

Dav*_*nan 7

通过逆向工程的过程,我推断这i是一个无符号的32位整数Cardinal.因此编译器for在无符号上下文中执行循环算法.这意味着它Count-1被解释为无符号,因此您的循环从中运行0high(i).

为了充实这一点,这就是一步一步发生的事情:

  • Count$00000000.
  • Count-1被评估并具有价值$FFFFFFFF.
  • 解释为无符号整数$FFFFFFFF是2 32 -1.
  • 你的循环体执行所有值0 <= i <2 32.

例如,解决方案是使循环变量为有符号整数Integer.

切换i到类型时Integer,会发生以下情况:

  • Count$00000000.
  • Count-1被评估并具有价值$FFFFFFFF.
  • 解释为有符号整数$FFFFFFFF是-1.
  • 循环体不执行.


Mas*_*ler 7

如上所述,这将无法编译,因为您没有声明i.

但是我的通灵调试感觉说它在i某处被声明为cardinal(无符号整数),因此当它试图评估时0 - 1,它得到MAXINT而不是-1因为无符号整数不能代表负值.

你永远不应该使用无符号整数作为索引变量或for循环的边界变量,如果它们有可能变为负数的话.否则,你会收到这样的错误.实际上,您通常应该不使用无符号整数.它们看起来没那么有用(如果你需要一个高于一个大小的最大签名值的值,你可能最终需要的值高于某个时刻的两倍,所以你真正需要的是下一个更大的整数大小)它们往往会引起像这样的奇怪错误.