2013-05-23 3 views
1

Delphi XE2, простой код:Почему Delphi «для» действует так?

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 

так, когда счетчик не 0 ничего работает должным образом, test eax, eax (EAX = $ FFFFFFFF после dec eax) не затрагивающий флаг Carry, в то время как jb действующий флаг Carry. Есть ли что-то, что я не понимаю об использовании for?

+2

FWIW этому вопросу было бы легче ответить, если бы вы предоставили полный код. В этом случае мы с Мэйсоном смогли сделать вывод из asm, что ваше целое не указано. Тем не менее, всегда лучше предоставлять полную программу, как можно короче. –

+0

Весь источник довольно большой: извлечение бонусных данных из файлов 'tiff' из папки, но ответы ниже были полезны. – user2091150

+1

Да, конечно, весь источник большой. Вот почему вы сократили его до полного компилируемого 10-ти линейного образца. Это все, что вам нужно, чтобы продемонстрировать эту проблему. Это всегда платит за это. –

ответ

7

Посредством процесса обратной инженерии я заключил, что i является целым числом без знака, 32 бит, Cardinal. Поэтому компилятор выполняет арифметику цикла for в неподписанном контексте. Это означает, что Count-1 интерпретируется как беззнаковое, и поэтому ваш цикл работает от 0 до high(i).

Чтобы конкретизировать это, это то, что происходит шаг за шагом:

  • Count является $00000000.
  • Count-1 оценивается и имеет значение $FFFFFFFF.
  • Интерпретируется как целое число без знака $FFFFFFFF is 2 -1.
  • Ваш корпус цикла выполняется для всех значений 0 < = i .

Решение состоит в том, чтобы сделать вашу переменную цикла целым числом со знаком, например Integer.

При переключении i быть типа Integer, происходит следующее:

  • Count является $00000000.
  • Count-1 оценивается и имеет значение $FFFFFFFF.
  • Интерпретируется как целое число со знаком $FFFFFFFF is -1.
  • Тело цикла не выполняется.
+0

Также спасибо, к сожалению, я не могу отметить 2 сообщения в качестве ответа. – user2091150

+0

Но вам не нужно выбирать Мейсона! ;-) И это было абсолютно предназначено как шутка !!!! Выбирайте то, что вы предпочитаете. –

+0

Хорошо :) ваш ответ более расширенный :) Я думал, что компилятор решает по типу 'count' (у меня были такие проблемы раньше: компилятор игнорирует такие вещи, как' v: = byte (someint); '), поэтому не уделяйте достаточного внимания' i' типа. – user2091150

7

Как написано, это не скомпилируется, так как у вас нет декларации для i.

Но мое психические отладки чувство говорит, что i объявлен где-то в качестве cardinal (целого числа без знака), и, таким образом, когда он пытается оценить 0 - 1, он получает MAXINT вместо -1, так как целые числа без знака не могут представлять отрицательные значения.

Вы не должны использовать целые числа без знака как индексную переменную или ограничивающие переменные цикла for, если есть вероятность, что они могут пойти отрицательно. В противном случае вы получите такие ошибки. На самом деле, вы, вероятно, просто не должны использовать целые числа без знака в целом.Они не так полезны, как они выглядят (если вам нужно значение выше максимального знакового значения для размера, вполне вероятно, что вам в конечном итоге потребуется значение, превышающее вдвое больше, чем в какой-то момент, так что вам действительно нужно следующий больший целочисленный размер), и они, как правило, вызывают такие странные ошибки, как этот.

+0

О, право, "i: dword;". Благодарю. – user2091150

Смежные вопросы