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?
通过逆向工程的过程,我推断这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.如上所述,这将无法编译,因为您没有声明i.
但是我的通灵调试感觉说它在i某处被声明为cardinal(无符号整数),因此当它试图评估时0 - 1,它得到MAXINT而不是-1因为无符号整数不能代表负值.
你永远不应该使用无符号整数作为索引变量或for循环的边界变量,如果它们有可能变为负数的话.否则,你会收到这样的错误.实际上,您通常应该不使用无符号整数.它们看起来没那么有用(如果你需要一个高于一个大小的最大签名值的值,你可能最终需要的值高于某个时刻的两倍,所以你真正需要的是下一个更大的整数大小)它们往往会引起像这样的奇怪错误.
| 归档时间: |
|
| 查看次数: |
211 次 |
| 最近记录: |