View Full Version : Is there a bit-shift function?
Is there a bit-shift function?
I use this on a few places, due to speed, and simplicity of code. I was just wondering if there was a function similar to this here?
In JAVASRIPT, it is done like this...
http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Bitwise_Operators
The ones I use a lot are...
a >> b
a << b
I also use a lot of 0x8
Is that a valid bit numerical representation? (Still sifting through the help, looking for bitwise operations. Ones that work on all values, not just numbers.)
Michael Clease
28-09-2008, 10:20
' Usage of the SHIFT Instruction example
' Binary Divide by 2 (no remainder)
Dim MyByte As Byte VALUE &h08 ' Initialise Byte to 8
Dim sMsg As String
sMsg += "Original Byte Value " & Hex$(MyByte,2) & $CRLF & $CRLF
SHIFT SIGNED RIGHT MyByte,1 ' Binary Divide by 2 probably quicker than a /
sMsg += " New Byte Value " & Hex$(MyByte,2) & $CRLF
MSGBOX 0, sMsg
Its all in the help file. ;)
ErosOlmi
28-09-2008, 10:28
Yes, is present.
Called SHIFT. More info at http://www.thinbasic.com/public/products/thinBasic/help/html/shift.htm
Can be used only on integer class numeric values: Byte, Word, Integer, DWord, Long, Quad
I can work with that... I just have to convert the string to a byte array. Thanks.
(Mostly I use it for making custom GIF's. Many people don't realize that each cell can have its own separate color pallet. The cheap GIF programs only allow one pallet, which is used for the whole animation.)
But it also comes in handy for ghetto encryption. (Easy to hack, but most assume that garbled text/data is actually encrypted, not just bit-shifted.)
ErosOlmi
28-09-2008, 19:11
I can work with that... I just have to convert the string to a byte array. Thanks.
Maybe you do not have to convert the string into a byte array but just over impose a byte array to the string.
thinBasic has a nice very powerful DIM ... AT functionality that let you handle the same sequence of memory in different ways.
Example
USES "Console"
'---Define a string
dim MyString as string
'---Fill it with something
MyString = "Hi there."
'---Now define a byte array of the same lenght of the string
'---and with the AT option tells thinBasic to not allocate any
'---new memory but use the same memory area of what is located
'---at the same memory pointer of the MyString variable
DIM MyByteArray(len(MyString)) as byte at strptr(MyString)
'---
dim Counter as long
for Counter = 1 to ubound(MyByteArray)
printl Counter, MyByteArray(Counter), chr$(MyByteArray(Counter))
next
waitkey
Ciao
Eros
Petr Schreiber
28-09-2008, 19:15
EDIT: Eros was faster
Hi ISAWHIM,
if you mean to get binary encoded value in string buffer to number, there are multiple ways.
Way #1 - conversion
To convert raw binary data to correct datatype, you can check out CVx family of functions.
For example, if you have 4 characters long ASCII string, you can convert it to byte values using
CVBYT( <stringHere>, <nthValue> ).
This function takes string, and converts the value.
Way #2 - memory overlay
While conversion is ok, we always need the best speed. And what is fastest? Not doing any conversion at all, just play with the way to look at memory data.
ThinBasic allows to overlay variable over other variable, even of different type.
So lets think we have again 4 character long string, encoding 4 byte values.
' -- Presume strData is that 4 character string
DIM MyByte(4) AS BYTE AT STRPTR(strData)
This will create BYTE array over memory location occupied by string. Once this line is executed, the array immediately (!) contains all values as BYTE numbers ( 0 - 255 ).
This works even to other side - if you assign values to this array element, it will update the string.
Here is little example:
Uses "Console"
DIM i AS LONG
' -- This string will contain binary encoded 4 BYTE values, just for testing
' -- The string could contain raw data from image file for example
dim strData as string = mkBYT$(1, 10, 20, 40)
PRINTL "Conversion ->"
FOR i = 1 to 4
PRINT CVBYT(strData, i)+ " "
NEXT
PRINTL
PRINTL
PRINTL "Direct overlay ->"
DIM MyByte(4) AS BYTE AT STRPTR(strData)
PRINTL "Printing iteratively:"
FOR i = 1 to 4
PRINT MyByte(i)+ " "
NEXT
PRINTL
PRINTL
PRINTL "Printing FAST:"
' -- One line of code, all array elements printed to screen
PRINTL JOIN$(MyByte, " ")
waitkey
Bye,
Petr
ErosOlmi
28-09-2008, 19:35
I was faster, You were more professional.
;)
Yea, but petr made my brain melt more...
I was thinking about using the TYPE function to set the string into a byte and string at the same time. That way I could update the byte with the new shifted value, and pull out the string on the fly. (Otherwise I would have to convert and join it back to a string. As I originally had done with small values. Not talking about your samples.)
I don't have any fancy code yet... I am still in brain-melted state from the above examples. (I was thinking about this again, since I started playing with the ZIP function, as a ghetto-protection of the compressed data. I already reverse the whole file before I zip it... and get the SHA1 FWD and REV, so I have 100% pure thumbprint of the file. There is no physical/code way to alter any piece of the file, and not change the SHA1 if it is read both ways. Even a normal CRC32 becomes unhackable from injection alteration. But anywho... Back to the topic.)
The only issue I have to overcome, is that I can not loose the shifted bit value... (Normally, a simple compare would return the value of the bit that would get lost, so it could be reset back on the other side. I know there are many ways to do that also.)
EG...
01110111 << 2 = 11011100
The first two {01} get dropped, and the last two get replaced with {00}
(But I need to put the dropped {01} back onto the other side.)
The easy way, is to just double the value...
(8bit) & (8bit) as (16bit)
01110111 & 01110111 = (0111011101110111)
Now shift
0111011101110111 << 2 = 1101110111011100
Now take the first value (8 bits) which had the left {01} pushed off, but the {01} from the following (8bits), was pushed into the value, to cause a full looped shift. (Reversing it using >> would make you want the second value, when you are attempting to restore it.)
Thus, if done in reverse... the original value is restored.
As opposed to...
11111111 << 2 = 11111100
than
11111100 >> 2 = 00111111
result
00111111 != 11111111
I know there is a machine version of this. (No clue about machine language... no samples please... You'll kill me!)
Petr Schreiber
28-09-2008, 21:36
Hmm,
I think SHIFT function works correct. The result you want I would call "rotate bits" rather than "shift bits".
I think similar terminology is used in assembly.
Well, now the time has come, Charles will shoot me if I did something wrong but I hope it is correct and I learned something from him :):
uses "Console"
Uses "Oxygen" ' -- Here is the best assembler ever :)
%myAssemblerRotLeft = 1
%myAssemblerRotRight = 2
dim i as long
dim b as byte
' -- Assembler source codes to rotate left
dim srcLeft as string = "
mov al,[#b]
rol al, 1
mov [#b],al
ret
"
' -- Assembler source codes to rotate right
dim srcRight as string = "
mov al,[#b]
ror al, 1
mov [#b],al
ret
"
' -- JIT compile assembler to native code
O2_Buf %myAssemblerRotLeft
o2_asmo srcLeft
O2_Buf %myAssemblerRotRight
o2_asmo srcRight
PRINTL "-= Testing rotate left =-"
b = 119
O2_Buf %myAssemblerRotLeft
for i = 1 to 8
printL bin$(O2_exec, 8) + $SPC(2) + bin$(b, 8) + $SPC + FORMAT$(b, "000")
next
printl
PRINTL "-= Testing rotate right =-"
b = 119
O2_Buf %myAssemblerRotRight
for i = 1 to 8
printL bin$(O2_exec, 8) + $SPC(2) + bin$(b, 8) + $SPC + FORMAT$(b, "000")
next
waitkey
If you need this functionality, I would suggest you to make suggestion in Suggest new feature ( suggest3 ).
The code above can be used meanwhile, seems to work.
( mov = put value to register, rol = rotate left, ror = rotate right )
Petr
Charles Pegge
28-09-2008, 21:59
Petr got there before me. :)
This example shows 32 bit rotation - rotating to the right by 4 places
If you want it to do this on a single byte then it is
ror byte [#vv],4
there is also
shl - shift left
shr - shift right
sar - shift arithmetic right (preserving sign)
and
rol - rotate left
rcr rotate through carry right
rcl rotate through carry left
uses "OXYGEN"
dim vv as long
dim src as string
src="
ror [#vv],4
ret
"
'END OF SRC
o2_asmo src
if len(o2_error) then
msgbox 0,o2_error()+o2_view (src)
stop
end if
vv=2
o2_exec
msgbox 0,"0x"+hex$(vv)
Wow...
I haven't even gotten that far yet.
I don't think that has enough wide-range use to take up valuable function in the core. (Seems like it might just add dead weight. Being unused by a majority of users.)
But those codes would make great samples or snippets in the help-files.
(Again, I am lost on the machine codes, but I would assume they are the fastest.)
Michael Hartlef
29-09-2008, 05:53
I don't think that has enough wide-range use to take up valuable function in the core. (Seems like it might just add dead weight. Being unused by a majority of users.)
Oxygen is not part of the core. It is a module developed by Charles. So it doesn't add weight but gives raw execution power to the people who need it and know how to use it. I'm very happy that Charles keeps going on with the development. I'm pretty sure that our current thinStudio project will use it.
??? what is thinStudio...
(I was talking about the round-about bit-shift being low use. Since the function is so small, just adding one of those would do the trick. I am not sure what is involved in making a whole new function. Seems it would take more than the sample-codes, for data-checking of passed values, to determine how to shift in a round-about method.)
That would make a neat Obfuscate trick. (Keeping the decrypted code in memory, but shifted so it only makes sense to the thinBASIC program. Where it would normally keep the translated code in raw form in memory. Might not work for all the code in memory, but I am sure that some of it could be bit-shifted until needed. Using a bit-mask would help too. Then they could not do a RAM-DUMP, and see our source. Well, they could, but it would take longer. Mess with them, use random bit-shifting and random bit-masks.)
(Not sure if that is within the scope of this project.)
I do know I would use it...
If it did STRING, and/or FILE. (Again, If it did one, a little code on our end, could make it work for both.)
Michael Hartlef
29-09-2008, 07:28
??? what is thinStudio...
(I was talking about the round-about bit-shift being low use. Since the function is so small, just adding one of those would do the trick. I am not sure what is involved in making a whole new function. Seems it would take more than the sample-codes, for data-checking of passed values, to determine how to shift in a round-about method.)
Ahh, ok. I thought you ment the Oxygen assembler module. Sorry, my fault.
thinStudio is a group of thinBasic user/developer who work on a game for a contest on a different website right now.
Charles Pegge
29-09-2008, 12:55
Using the latest thinBasic 1.7 with the latest Oxygen. It is possible to write assembled functions like this:
uses "OXYGEN"
dim v1,v2 as long
o2_buf 1 : o2_asmo " mov eax,[esp+4] : mov ecx,[esp+8] : rol eax,cl : ret 8 "
declare function ROL (byval v as long, byval n as long ) as long at o2_buf 1
o2_buf 2 : o2_asmo " mov eax,[esp+4] : mov ecx,[esp+8] : ror eax,cl : ret 8 "
declare function ROR (byval v as long, byval n as long ) as long at o2_buf 2
if len(o2_error) then msgbox 0,o2_error()+o2_view (src) : stop
v1=ROR 1,2 ' rotate number, places to the right
v2=ROL 1,2 ' rotate number, places to the left
msgbox 0,"&h"+hex$(v1)+$cr+"&h"+hex$(v2)
Michael Clease
29-09-2008, 13:30
Prynhawn da Charles,
I have never been interested in using Oxygen because I never liked the instruction set (nothing personal to you charles) but that last example was an interesting Idea.
If I can pick certain commands and wrap them in a function thats quite useful, i wouldnt want the extra speed that Oxygen offers just some of its commands.
thanks for that.
Charles Pegge
29-09-2008, 14:41
Hi Michael, Croeso!
If all goes well, Oxygen will support Basic syntax in a few week's time. Assembler is quite a lot to learn. But I have grown up with it.
Here is a bit rotation procedure for a whole string of any length:
uses "OXYGEN"
dim src as string
dim s as string
src= "
push edi
mov edi,[esp+8]
mov edi,[edi]
mov edx,[edi-4] ' length
mov eax,edx
(
dec edx ' does not affect carry flag
jl exit ' start with the final byte and work back
rcr byte [edi+edx],1 ' rotate carry right
repeat
)
' insert final carried bit
(
jae exit ' no carry
cmp eax,0
jle exit ' null string
or byte [edi+eax-1],0x80
)
pop edi
ret 4
"
o2_buf 1 : o2_asmo src : declare sub RORS ( s as string ) at o2_buf 1
if len(o2_error) then msgbox 0,o2_error()+o2_view (src) : stop
s="bit rotate the whole string one place to the right"
RORS s
msgbox 0,s
Charles Pegge
29-09-2008, 14:57
To verify correct operation here is RORS and its complementary twin ROLS cancelling each other out:
uses "OXYGEN"
dim src as string
dim s as string
src= "
push edi
mov edi,[esp+8]
mov edi,[edi]
mov edx,[edi-4] ' length
mov eax,edx
(
dec edx ' does not affect carry flag
jl exit ' start with the final byte and work back
rcr byte [edi+edx],1 ' rotate carry right
repeat
)
' insert final carried bit
(
jae exit ' no carry
cmp eax,0
jle exit ' null string
or byte [edi+eax-1],0x80
)
pop edi
ret 4
"
o2_buf 1 : o2_asmo src : declare sub RORS ( s as string ) at o2_buf 1
src= "
push edi
mov edi,[esp+8]
mov edi,[edi]
mov edx,[edi-4] ' length
mov eax,edx
(
dec edx ' does not affect carry flag
jl exit ' start with the first byte and work forward
rcl byte [edi],1 ' rotate carry left
inc edi
repeat
)
' insert final carried bit
(
jae exit ' no carry
cmp eax,0
jle exit ' null string
sub edi,eax
or byte [edi],0x1
)
pop edi
ret 4
"
o2_buf 2 : o2_asmo src : declare sub ROLS ( s as string ) at o2_buf 2
if len(o2_error) then msgbox 0,o2_error()+o2_view (src) : stop
s="bit rotate the whole string one place to the right"
RORS s
ROLS s
msgbox 0,s
Charles Pegge
29-09-2008, 17:05
By using an outer loop the string bits can be rotated several places in one call
uses "OXYGEN"
dim src as string
dim s as string
src= "
push edi
mov ecx,[esp+12]
(
dec ecx
jl exit
mov edi,[esp+8]
mov edi,[edi]
mov edx,[edi-4] ' length
mov eax,edx
(
dec edx ' does not affect carry flag
jl exit ' start with the final byte and work back
rcr byte [edi+edx],1 ' rotate carry right
repeat
)
' insert final carried bit
(
jae exit ' no carry
cmp eax,0
jle exit ' null string
or byte [edi+eax-1],0x80
)
repeat
)
pop edi
ret 4
"
o2_buf 1 : o2_asmo src : declare sub RORSN ( s as string, byval n as long ) at o2_buf 1
src= "
push edi
mov ecx,[esp+12]
(
dec ecx
jl exit
mov edi,[esp+8]
mov edi,[edi]
mov edx,[edi-4] ' length
mov eax,edx
(
dec edx ' does not affect carry flag
jl exit
rcl byte [edi],1 ' rotate carry left
inc edi
repeat
)
' insert final carried bit
(
jae exit ' no carry
cmp eax,0
jle exit ' null string
sub edi,eax
or byte [edi],0x1
)
repeat
)
pop edi
ret 4
"
o2_buf 2 : o2_asmo src : declare sub ROLSN ( s as string, byval n as long ) at o2_buf 2
if len(o2_error) then msgbox 0,o2_error()+o2_view (src) : stop
s="bit rotate the whole string one place to the right"
RORSN s,5
ROLSN s,5
msgbox 0,s