为什么德尔福“为”这样做?

时间:2013-05-23 13:17:04

标签: 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

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

所以当count为0时,无法正常工作,test eax, eaxdec eax之后的eax = $ FFFFFFFF)不会影响Carry标志而jb通过Carry标志行事。 关于使用for

,我有什么不明白的地方吗?

2 个答案:

答案 0 :(得分:7)

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

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

  • Count$00000000
  • Count-1已经过评估,其值为$FFFFFFFF
  • 解释为无符号整数$FFFFFFFF为2 32 -1。
  • 你的循环体执行所有值0< = i< 2 32

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

当您将i切换为Integer类型时,会发生以下情况:

  • Count$00000000
  • Count-1已经过评估,其值为$FFFFFFFF
  • 解释为有符号整数$FFFFFFFF为-1。
  • 循环体不会执行。

答案 1 :(得分:7)

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

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

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

相关问题