技术交流,DH讲解.
在D2010的classes中有个TBits类,这个类主要是位操作的.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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;这个属性,就是读取和设置某一位的.
那我们看看它是怎么实现的?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
//在类中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中有多少个一么?
当时我们用的方法是移位然后与,那么我们现在换个方法呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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.
http://www.cnblogs.com/huangjacky/archive/2010/01/19/1651359.html