技术交流,DH讲解.
在D2010的classes中有个TBits类,这个类主要是位操作的.
TBits = class
private
FSize: Integer;
FBits: Pointer;
procedure Error;
procedure SetSize(Value: Integer);
procedure SetBit(Index: Integer; Value: Boolean);
function GetBit(Index: Integer): Boolean;
public
destructor Destroy; override;
function OpenBit: Integer;
property Bits[Index: Integer]: Boolean read GetBit write SetBit; default;
property Size: Integer read FSize write SetSize;
end;
这个类没有什么方法,我们看到了property Bits[Index: Integer]: Boolean read GetBit write SetBit; default;这个属性,就是读取和设置某一位的.
那我们看看它是怎么实现的?
//在类中Eax就是Self指针
procedure TBits.SetBit(Index: Integer; Value: Boolean); assembler;
asm
CMP Index,[EAX].FSize //如果Indx>=Size then 扩容
JAE @@Size
@@1: MOV EAX,[EAX].FBits
OR Value,Value
JZ @@2
BTS [EAX],Index //将Eax中第Index位赋值给CF,然后Eax第index位=1;
RET
@@2: BTR [EAX],Index //将Eax中第Index位赋值给CF,然后Eax第index位=0;
RET
@@Size: CMP Index,0 //if index <0 then Error
JL TBits.Error
PUSH Self //push [eax]
PUSH Index
PUSH ECX {Value}
INC Index
CALL TBits.SetSize
POP ECX {Value}
POP Index
POP Self
JMP @@1
end;
function TBits.GetBit(Index: Integer): Boolean; assembler;
asm
CMP Index,[EAX].FSize
JAE TBits.Error
MOV EAX,[EAX].FBits
BT [EAX],Index //将eax的第Index位赋值给CF
SBB EAX,EAX //eax - (eax + CF)
AND EAX,1 //清除Eax中的其他位
end;
这里我们发现BTR,BTS,BT,SBB等位操作符.我们之前不是算过99999中有多少个一么?
当时我们用的方法是移位然后与,那么我们现在换个方法呢?
Function _1Bits(ANum: Integer): Integer;
asm
xor edx,edx // 位数
xor ecx,ecx // 1的个数
@@nLoop:
cmp edx,32 // 循环32次
je @@nExit
bt eax,edx
jnc @@nNoInc // if CF = 0 then
inc ecx
@@nNoInc:
inc edx
jmp @@nLoop
@@nExit:
mov eax,ecx
end;
全部都是直接对位操作的.
BTR和BTS的作用如上面我注释中写的那样,但是我现在没有其他例子给大家看.TBits类很纯洁,所以可以用到其他版本中去.
我是DH.