Форум: "Начинающим";
Текущий архив: 2005.10.23;
Скачать: [xml.tar.bz2];
ВнизМанипуляция битами Найти похожие ветки
← →
wnew © (2005-10-02 21:52) [0]Здравствуйте, мастера!
Есть array of Byte, необходимо считать, а также записать любой нужный бит в соответствующей ячейке массива. При этом желательно обращаться прямо к двоичному коду содержимого ячеек. Я конечно знаю, что есть такой TBits, но к сожалению не могу разобраться, как использовать этот класс. Интернет перерыл, но с тем же результатом, что и в родном хелпе в Delphi, информация скудная и нет примеров использования. Посмотрел исходник для TBits - SetBit и GetBit, но там на ассемблере - не понимаю:(
← →
begin...end © (2005-10-02 22:18) [1]> wnew © (02.10.05 21:52)
> Есть array of Byte, необходимо считать, а также записать
> любой нужный бит в соответствующей ячейке массива.
Можно и без TBits, используя обычные логические операции.
Выяснить состояние бита:
if ЧИСЛО and (1 shl НОМЕР_БИТА) <> 0
// бит под номером НОМЕР_БИТА установлен
else
// бит под номером НОМЕР_БИТА сброшен
Установить бит равным 1:
ЧИСЛО := ЧИСЛО or (1 shl НОМЕР_БИТА)
Установить бит равным 0:
ЧИСЛО := ЧИСЛО and not (1 shl НОМЕР_БИТА)
Или я неправильно понял вопрос?
← →
wnew © (2005-10-02 22:27) [2]
> begin...end © (02.10.05 22:18) [1]
> Или я неправильно понял вопрос?
Правильно, понял. Это мне подходит, спасибо.
А ещё вопрос: в исходнике фунций SetBit и GetBit есть ассемблерные команды BT - опросить бит, BTR - опросить бит и обнулить и BTS - опросить и установить в 1 - может, как-то удобно будет этим воспользоваться? Если да, то наведите:)
← →
palva © (2005-10-02 22:34) [3]Можно таким образом:
{$APPTYPE CONSOLE}
var
m: array [0..15] of Byte =
(0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0);
function TestBit(var a; n: Integer): Integer;
asm
BT [EAX],EDX
MOV EAX,0
RCL EAX,1
end;
function TestBitAndSet(var a; n: Integer): Integer;
asm
BTS [EAX],EDX
MOV EAX,0
RCL EAX,1
end;
Begin
WriteLn(TestBit(m, 49)); // 0
WriteLn(TestBit(m, 50)); // 1
TestBitAndSet(m, 49);
WriteLn(m[6]); // 7
End.
Вот еще пример:
{$APPTYPE CONSOLE}
var m: array [0..15] of Byte;
function SetBit(var a; n: Integer): Integer;
asm
BTS [EAX],EDX
end;
Begin
m[6] := 5;
WriteLn(m[6]); // 5
SetBit(m, 49);
WriteLn(m[6]); // 7
End.
← →
begin...end © (2005-10-02 22:46) [4]> wnew © (02.10.05 22:27) [2]
> может, как-то удобно будет этим воспользоваться?
Может быть. Пример установки нужного бита в переменной с помощью команд BTR и BTS я недавно давал в ветке http://delphimaster.net/view/15-1128055512/ . А вот пример выяснения значения бита в переменной типа Byte:
var
B: Byte;
asm
MOV AL, B // Или MOVZX AX, B
BT AX, 3
JNC @@1
// Третий бит в байте B равен 1
@@1:
// Третий бит в байте B равен 0
end
Понятно, что в этом случае придётся, по крайней мере, часть кода обработки полученного значения бита выполнить на ассемблере.
← →
wnew © (2005-10-02 22:49) [5]
> palva © (02.10.05 22:34) [3]
Спасибо, по Вашим примерам стало понятно использование класса TBits:)
Несколько не так, как я себе представлял. Хотя так тоже сойдёт, но было бы совсем хорошо, если бы в SetBit передавался один единственный байт, а в нём уже по номеру индекса устанавливать нужный бит, так же и для GetBit.
Хотя стоп. Кажется Вашей функции SetBit без разницы, что передавать в качестве параметра a? Можно также и один Byte, а не массив?
← →
wnew © (2005-10-02 22:53) [6]
> begin...end © (02.10.05 22:46) [4]
> Понятно, что в этом случае придётся, по крайней мере, часть
> кода обработки полученного значения бита выполнить на ассемблере.
>
Лучше, что бы полученные значения были типа Byte или Boolean, т.е. 1 или 0, True или False.
Но мне кажется, что всё уже понял, спасибо.
← →
palva © (2005-10-03 00:02) [7]Извиняюсь,
function SetBit(var a; n: Integer): Integer;
на самом деле процедура, так что стоит ее обявить как
procedure SetBit(var a; n: Integer);
← →
wnew © (2005-10-03 01:22) [8]
> palva © (03.10.05 00:02) [7]
Ничего страшного - разобрался бы:)
Я с SetBit ещё не экспериментировал, а GetBit работает.
function TPack.GetBits(Wert, Index: Integer): Boolean;assembler;
asm
MOV EAX,Wert
BT EAX,Index
SBB EAX,EAX
AND EAX,1
end;
С ассемблером ещё не приходилось сталкиваться:)
← →
Defunct © (2005-10-03 01:58) [9]> wnew ©
спасибо за вопрос ;>
Imho BT лучше не использоваться на некоторых процессорах эта команда выполняется неоправдано долго, поэтому предлагаю вот такой вариант функции GetBit:function GetBit(var Buf; Index: integer):boolean; assembler;
asm
mov ecx, edx
shr edx, 3
and cl, 7
mov al, [eax + edx]
shr al, cl
and al, 1
end;
Установку же бита и сброс можно делать двумя путями - либо масочно, либо командами BTR/BTS. Масочно будет немного быстрее на некоторых процессорах, но потребуется обращение лишнее обращение к памяти.. в общем предлагаю такой вариант:procedure SetBit(var Buf; Index: integer; Value: boolean);assembler;
asm
test cl, cl
jnz @set_bit
mov ecx, edx
shr edx, 3
and ecx, 7
btr [eax+edx], ecx
ret
@set_bit:
mov ecx, edx
shr edx, 3
and ecx, 7
bts [eax+edx], ecx
end;
Пример применения:
var A: Array[1..100] of byte;
procedure TForm1.Button1Click(Sender: TObject);
begin
A[1] := $0;
A[2] := $0;
A[3] := $0;
SetBit( A, 15, True);
if GetBit(A, 15) then
ShowMessage( "True" )
else
ShowMessage( "False" )
end;
← →
wnew © (2005-10-03 02:44) [10]
> Defunct © (03.10.05 01:58) [9]
Если Вас не затруднит, могли бы Вы описать, как работают Ваши ассемблерные вставки. По командам вроде понятно с помощью соответствующей книги, но по регистрам ничего не соображаю, что от куда берётся.
CL - это что, регистр? Почему тогда сравнивается CL с CL? Где находятся сразу передаваемые в функции параметры и куда возвращаются?
Если это противоречит правилам форума, то пожалуйста на E-MAIL wp.micheew(At)wnew.de
← →
MBo © (2005-10-03 08:14) [11]>Где находятся сразу передаваемые в функции параметры и куда возвращаются?
см. в справке Calling conventions и http://www.swissdelphicenter.ch/en/showcode.php?id=1233
На входе в функцию с модификатором register (используемым по умолчанию, т.е. если не указано stdcall и т.д.) параметры (слева направо в порядке написания) передаются в региcтрах EAX, EDX, ECX, далее - через стек. Результат - в EAX
> Почему тогда сравнивается CL с CL?
проверка на нулевое значение, устанавливается (в частности) флаг ZF, который проверяется в след. строке JNZ...
← →
Defunct © (2005-10-03 10:38) [12]wnew © (03.10.05 02:44) [10]
GetBit работает так:
вычисляет адрес байта в массиве и номер бита в байте соответственно командами:
shr edx, 3 (смещение байта в массиве)
and ecx, 7 (вычисление номера бита в байте).
далее считывает байт в регистр AL (8-ми разрядный регистр - младшие 8 бит регистра eax)
делит его (байт) на 2^(номер бита)
убирает лишние единицы командой and al, 1, результат возвращается в al.
SetBit работает так: вначале проверяется устанавливаемый бит на 0. Взависимости от его значения (0 - False/ не нуль - True) далее производится сброс или установка бита в массиве командами btr/bts. Адрес байта и номер бита вычисляются аналогично GetBit.
Index в обеих функциях является номером бита в массиве.
← →
wnew (2005-10-03 15:12) [13]
> MBo © (03.10.05 08:14) [11]
Спасибо.
> Defunct © (03.10.05 10:38) [12]
Спасибо.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2005.10.23;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.042 c