1

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(eax = $FFFFFFFF after dec eax) は、キャリー フラグによって動作している間、キャリー フラグに影響を与えませんjb。の使用について理解できないことはありforますか?

4

2 に答える 2

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 です。
  • ループ本体は実行されません。
于 2013-05-23T13:23:39.510 に答える
7

書かれているように、 の宣言がないため、これはコンパイルされませんi

しかし、私の精神的なデバッグ感覚は、が(符号なし整数)iとしてどこかで宣言されていると言います。cardinal0 - 1MAXINT-1

for符号なし整数が負になる可能性がある場合は、インデックス変数またはループの境界変数として絶対に使用しないでください。そうしないと、このようなエラーが発生します。実際、通常は符号なし整数を使用しないほうがよいでしょう。それらは見た目ほど有用ではありません (サイズの最大符号付き値よりも高い値が必要な場合、ある時点でその 2 倍よりも高い値が必要になる可能性が高いため、本当に必要なのは次に大きい整数サイズ)、このような奇妙なバグを引き起こす傾向があります。

于 2013-05-23T13:25:25.030 に答える