Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.10.23;
Скачать: CL | DM;

Вниз

Манипуляция битами   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.051 c
1-1128261565
SergP.
2005-10-02 17:59
2005.10.23
Разные результаты компрессии CompressBuf и TCompressionStream


14-1128022479
lookin
2005-09-29 23:34
2005.10.23
CSKA-MIDT


14-1127891845
pasha_golub
2005-09-28 11:17
2005.10.23
Инет в Одессе


3-1126093577
stud
2005-09-07 15:46
2005.10.23
сортировка в dxMemData


3-1126086871
Term
2005-09-07 13:54
2005.10.23
как в ХП для FB1.5 получить аналогичный результат