Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
14-1128424599
Андрей Жук
2005-10-04 15:16
2005.10.23
Покритикуйте


4-1124473477
Джо
2005-08-19 21:44
2005.10.23
SetParent для окон различных приложений


3-1126175918
ХиМ
2005-09-08 14:38
2005.10.23
Внешняя база данных не имеет предполагаемого формата


2-1128275543
wnew
2005-10-02 21:52
2005.10.23
Манипуляция битами


10-1105978365
Uran
2005-01-17 19:12
2005.10.23
Выгрузить страницу в отдельный файл.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский