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, eax
(dec eax
之后的eax = $ FFFFFFFF)不会影响Carry标志而jb
通过Carry标志行事。
关于使用for
答案 0 :(得分:7)
通过逆向工程的过程,我推断i
是无符号的32位整数Cardinal
。因此编译器在无符号上下文中执行for
循环算法。这意味着Count-1
被解释为无符号,因此您的循环从0
运行到high(i)
。
为了充实这一点,这就是一步一步发生的事情:
Count
是$00000000
。Count-1
已经过评估,其值为$FFFFFFFF
。$FFFFFFFF
为2 32 -1。解决方案是使循环变量成为有符号整数,例如Integer
。
当您将i
切换为Integer
类型时,会发生以下情况:
Count
是$00000000
。Count-1
已经过评估,其值为$FFFFFFFF
。$FFFFFFFF
为-1。答案 1 :(得分:7)
如上所述,这将无法编译,因为您没有i
的声明。
但是我的通灵调试感觉说i
在某处被称为cardinal
(无符号整数),因此当它试图评估0 - 1
时,它会得到MAXINT
而不是-1
,因为无符号整数不能表示负值。
你永远不应该使用无符号整数作为索引变量或for
循环的边界变量,如果它们有可能变为负数的话。否则,你会收到这样的错误。实际上,您通常应该不使用无符号整数。它们看起来没那么有用(如果你需要一个高于一个大小的最大签名值的值,你可能最终需要的值高于某个时刻的两倍,所以你真正需要的是下一个更大的整数大小)它们往往会引起像这样的奇怪错误。