Page 1 of 2
Bits manipulation
Posted: Sun May 12, 2013 7:10 pm
by Poshu
Heya!
I needed a few macro to manipulate bits, because of a big fat array that was eating memory away.
Code: Select all
EnableASM
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Macro SetBit(Integer,bit)
MOV eax, Integer
MOV ebx, bit
BTS eax, ebx
MOV Integer,eax
EndMacro
Macro ResetBit(Integer,bit)
MOV eax, Integer
MOV ebx, bit
BTR eax, ebx
MOV Integer,eax
EndMacro
Macro ToggleBit(Integer,bit)
MOV eax, Integer
MOV ebx, bit
BTC eax,ebx
MOV Integer, eax
EndMacro
Procedure.b GetBit(Integer, bit)
MOV ebx, bit
BT Integer, ebx
SETC al
ProcedureReturn
EndProcedure
Macro ReadBit(Integer, bit,Result)
MOV ebx, bit
BT Integer, ebx
SETC al
MOV Result,al
EndMacro
CompilerElse
Macro SetBit(Integer,bit)
MOV rax, Integer
MOV rbx, bit
BTS rax, rbx
MOV Integer,rax
EndMacro
Macro ResetBit(Integer,bit)
MOV rax, Integer
MOV rbx, bit
BTR rax, rbx
MOV Integer,rax
EndMacro
Macro ToggleBit(Integer,bit)
MOV rax, Integer
MOV rbx, bit
BTC rax,rbx
MOV Integer, rax
EndMacro
Macro ReadBit(Integer, bit,Result)
MOV rbx, bit
BT Integer, rbx
SETC al
MOV Result,al
EndMacro
Procedure.b GetBit(Integer, bit)
MOV rbx, bit
BT Integer, rbx
SETC al
ProcedureReturn
EndProcedure
CompilerEndIf
Self explanatory, except maybe ReadBit and GetBit which are basically the same function in different flavor (depending on your coding style, the macro is faster but the procedure is more readable).
Re: Bits manipulation
Posted: Sun May 12, 2013 8:09 pm
by thyphoon
Merci ! c'est plus pratique que ce que je faisais !!

Re: Bits manipulation
Posted: Sun May 12, 2013 8:21 pm
by davido
Very nice! Thank you for sharing.
I'll learn a lot, too.
Re: Bits manipulation
Posted: Mon May 13, 2013 1:59 am
by rsts
Nice. Thanks for sharing.
Re: Bits manipulation
Posted: Mon May 13, 2013 8:41 am
by Kelebrindae
Most useful indeed.
Thank you very much, Poshu!
Re: Bits manipulation
Posted: Mon May 13, 2013 4:24 pm
by Helle
For the 'Procedure.b GetBit(Integer, bit)' use e.g. for 64-bit
Code: Select all
Procedure.b GetBit(Integer, bit)
MOV rbx, bit
XOR rax,rax ;set RAX to zero
BT Integer, rbx
SETC al
ProcedureReturn
EndProcedure
'SETC al' set only AL and in the return-value (EAX/RAX) is only AL 0 or 1. PB ignored '.b'.
BTW: With
makes PB nonsense.
Re: Bits manipulation
Posted: Tue May 14, 2013 6:36 am
by skywalk
BitGet() Macro without ASM...
Code: Select all
Macro BinX(x, nBits=16)
"%" + RSet(Bin(x), nBits, "0")
EndMacro
Macro HexX(x, nBits=16)
"$" + RSet(Hex(x), nBits, "0")
EndMacro
Macro ML_BITGET(x, bit) ; x.i, 0-based bit position
; Returns val of binary at bit pos, instead of ProcedureReturn 0 or 1
; Debug ML_BITGET(33,6) ; = 0: ; Debug ML_BITGET(33,0) ; = 1: ; Debug ML_BITGET(33,5) ; = 32
((x) & (1 << (bit)))
EndMacro
Define x.i = 225
Debug "225 Dec = " + RSet(Str(x),9)
Debug "BinX(225) Bin = " + BinX(x ,8)
Debug "BitGet(225,5) Bin = " + BinX(ML_BITGET(x,5),8)
Debug "BitGet(225,5) Hex = " + HexX(ML_BITGET(x,5),8)
Debug "BitGet(225,5) Dec = " + RSet(Str(ML_BITGET(x,5)),9)
Re: Bits manipulation
Posted: Mon May 20, 2013 1:46 pm
by Harry0
First post in a long time!
I have an issue with trying to convert this code to use ASM in different fashion.
Probably due to something stupid I am doing (or not doing) BUT I can't see it.
Given the above code I have been trying to use the alternative calling nomenclature (code example below):
Code: Select all
;
; from URL: http://www.purebasic.fr/english/viewtopic.php?f=12&t=54608
;
Define TargetByte.i = 225
EnableASM
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
CompilerElse
;
;Test code below, first comment out this section then
;
Macro _M_ToggleBit(ByteTarget, bit)
mov rax, ByteTarget
mov rbx, BIT
btc rax, rbx
mov ByteTarget, rax
EndMacro
;
; Put this code in to play (take out the ';')
;
; Macro _M_ToggleBit(ByteTarget, bit)
; !mov rax, [p.v_#ByteTarget] ;(line of error)
; !mov rbx, [p.v_#BIT]
; !btc rax, rbx
; !mov [p.v_#ByteTarget], rax
; EndMacro
CompilerEndIf
Macro _M_BinX(x, nBits=(SizeOf(Integer)*8))
"%" + RSet(Bin(x), nBits, "0")
EndMacro
Macro _M_HexX(x, nBits=(SizeOf(Integer)*8))
"$" + RSet(Hex(x), nBits, "0")
EndMacro
Macro _M_ML_BITGET(x, bit) ; x.i, 0-based bit position
; Returns val of binary at bit pos, instead of ProcedureReturn 0 or 1
; Debug ML_BITGET(33,6) ; = 0: ; Debug ML_BITGET(33,0) ; = 1: ; Debug ML_BITGET(33,5) ; = 32
((x) & (1 << (bit)))
EndMacro
;Define TargetByte.i = 225
Debug "TargetByte = 225 Dec = " + RSet(Str(TargetByte),9)
Debug "_M_BinX(225) Bin = " + _M_BinX(TargetByte ,8)
Debug "_M_BitGet(225,5) Bin = " + _M_BinX(_M_ML_BITGET(TargetByte,5),8)
Debug "_M_BitGet(225,5) Hex = " + _M_HexX(_M_ML_BITGET(TargetByte,5),8)
Debug "_M_BitGet(225,5) Dec = " + RSet(Str(_M_ML_BITGET(TargetByte,5)),9)
Debug "Other tests"
TargetByte = 245
Debug "TargetByte = 245 Dec = " + RSet(Str(TargetByte),9)
Debug "_M_BinX(TargetByte) Bin = " + _M_BinX(TargetByte ,8)
Debug "_M_ToggleBit(TargetByte,6):"
_M_ToggleBit(TargetByte,6)
Debug "_M_BinX(TargetByte) Bin = " + _M_BinX(TargetByte ,8)
Debug "Value of TargetByte Dec = " + RSet(Str(TargetByte),9)
The code as is work fine.
But when I try to put the second version in to play I get an error "undefined symbol" at the Line of error noted above.
What am I doing wrong?
Harry0
Re: Bits manipulation
Posted: Mon May 20, 2013 3:41 pm
by jassing
maybe because the constant isn't defined?
Re: Bits manipulation
Posted: Mon May 20, 2013 3:57 pm
by Harry0
Jassing,
The line of code '[p.v_#ByteTarget]' is not defining a constant but the nomenclature for how to use concatenation in a Macro ([p.v_#ByteTarget] turns in to [p.v_<PB Var>] instead of [p.v_ByteTarget]).
This is how you pass a PB variable to in-line assembler when using the ! directive (direct call of an ASM directive).
It is described in the docs/help file under 'ASM'.
I have used this method in my other programs without a problem, so I know the technique is valid (but have issues in this one case!?!?!?!?).
Hope that clarifies things!
Harry0
Re: Bits manipulation
Posted: Tue May 21, 2013 5:06 am
by jassing
thank you for explaining it.
Re: Bits manipulation
Posted: Tue May 21, 2013 5:08 am
by Demivec
Harry0 wrote:Probably due to something stupid I am doing (or not doing) BUT I can't see it.
Harry0 wrote:; !mov rax, [p.v_#ByteTarget] ;(line of error)
IMHO, the variable being referenced in the macro must be a parameter ('p.v_') of a procedure. You are using it with a variable local to the main block of code. I think that would be require it to be !mov rax, [v_#ByteTarget].
Re: Bits manipulation
Posted: Tue May 21, 2013 2:34 pm
by Harry0
Demivec,
WOW, learn something new everyday!!!!
So..... What did I learn from this?
1. When using ASM the following must be used:
1.a. The nomenclature of '[v.<PB_VAR>] is used for variables defined/used in the main section of code (not in a procedure)
1.b. The nomenclature of '[p_v.<PB_VAR>] is used for variables defined/used in a procedure section of code
1.c. The name of the variable must match the case of the variable when defined/first used
1.d. You can not pass a value to ASM code when it is expecting a variable
Thank you Demivec for the help and have a great day!
Harry0
Re: Bits manipulation
Posted: Tue May 21, 2013 2:39 pm
by Demivec
Harry0 wrote:Thank you Demivec for the help and have a great day!
Your welcome.

Re: Bits manipulation
Posted: Fri May 24, 2013 1:27 pm
by Psychophanta
I use these, in 2 flavours for your choose; Procedure or Macro:
Procedures:
Code: Select all
Procedure Setbit(n.l,*addr.byte)
*addr+n/8:*addr\b|1<<(n%8)
EndProcedure
Procedure Resbit(n.l,*addr.byte)
*addr+n/8:*addr\b&((1<<(n%8))!$FF)
EndProcedure
Procedure.b Getbit(n.l,*addr.byte)
*addr+n/8:If *addr\b&1<<(n%8):ProcedureReturn 1:EndIf:ProcedureReturn 0
EndProcedure
Macros:
Code: Select all
Macro SetbitMacro(n,a)
PokeB(a#+n#/8,PeekB(a#+n#/8)|1<<(n#%8))
EndMacro
Macro ResbitMacro(n,a)
PokeB(a#+n#/8,PeekB(a#+n#/8)&((1<<(n#%8))!$FF))
EndMacro
Macro GetbitMacro(n,a)
(1&Val(Trim(Bin(PeekB(a#+n#/8)&1<<(n#%8),#PB_Byte),"0")))
EndMacro
By the way:
With these functions and macros you can Set, Reset, or Get the 'n'th bit (starting by 0), counting from the memory address passed in the 2nd parameter.