Байтовый своппинг
Ознакомьтесь в файле помощь Delphi с функцией Swap. Но там в определении есть опечатка, правильно будет так:
function Swap(X) : word; |
Ниже приведен пример использования:
var X: Word; begin X := Swap($1234); { $3412 } end; |
на первый взгляд ничего сложного.
Для своппинга 16-битного целого или слова, используйте следующий код:
value: integer; value := swap(value); {внутренняя паскалевская функция} |
Для свапирования 32-битного длинного целого:
value: longint; value := swap(value shr 16) or (longint(swap(value and $ffff)) shl 16); |
Я не знаю какие стандарты используются для значений с плавающей точкой, но если они соответствуют типам integer и longint (это моя догадка), то можно воспользоваться следующим кодом (для double):
value: double;
block: array[0..7] of byte absolute value;
temp: byte;
for i := 0 to 3 do begin temp := block[i]; block[i] := block[7-i]; block[7-i] := temp; end; |
При использовании типа real массив должен быть 0..5 и цикл от 0 до 2; при использовании типа comp, 0..7 и от 0 до 3; для single 0..3 и от 0 до 1; для extended 0..9 и от 0 дo 4.
Вы можете переделать это в процедуру, которая получает указатель на значение и его размер, например (возможно нуждается в оптимизации и улучшении):
procedure swapper (valin: pointer; size: integer); var i: integer; temp: byte; val: ^byte; begin size := size - 1; val := valin; for i := 0 to (size div 2) do begin temp := val[i]; val[i] := val[size-i]; val[size-i] := temp; end; end; |
и затем так использовать это:
swapper (@value, sizeof(value)); |
(Это должно работать для longint, integer и пр., но swap() более эффективен.)
Обратите внимание на то, что дополнительно к своппингу байтов, вы можете делать преобразование формата (например, из Microsoft floating point в ANSI); я не знаком глубоко с темой чисел с плавающей точкой, поэтому эту тему я опущу. Качественной проверкой может служить сдиг байтов и проверку получившегося значения на другой системе, признающей формат чисел, обрабатываемый Delphi.
...у меня была аналогичная проблема: я считывал с диска TColor в формате RGB ($RRGGBB), тогда как delphi пользуется форматом BGR.
Я решил свою проблему and'ингом начального числа с маской, извлекая этим необходимые значения и "устанавливая" их в мой формат. Вот так:
color := $F03200; r := (color and $FF0000) div $010000; {должно возвратить $F0} g := (color and $00FF00) div $000100; {должно возвратить $32} b := (color and $0000FF); {должно возвратить $00} newcolor := (b * $010000) + (g * $000100) + b; |
Если это сработает, то newcolor должен содержать $0032F0.
Вы можете использовать процедуру, написанную на языке ассемблер. Например, такую:
var result : byte; asm { mov cx,8 mov ah,0 mov al,<БАЙТ В ФОРМАТ BIG ENDIAN FORMAT> @do_loop shr al,1 shl ah,1 jcc @dont_set_bit ; просто осуществляем переход (правда, я не уверен что это правильно) xor ah,1 @dont_set_bit: loop do_loop mov result,al } |
Это скорее псевдо-код (поскольку мой ассемблер сильно хромает). Если вы хотите, чтобы код был более "портативным", то воспользуйтесь вместо inline-ассемблера паскалем (где можно использовать SHL - смещения бит налево и SHR - направо). [001970]