I was playing around a day or two ago with an xor encryption..... I had a small need to a faster way of doing it, so I went to an asm dll.
I didn't paste everything here, only whats needed. Can you make it better?
Code:
SAFEARRAYBOUND struct
cElements DWORD ? ; Number of Elements
lLbound DWORD ? ; Lower Boundary
SAFEARRAYBOUND ends
OLE_SAFEARRAY struct
cDims WORD ? ; Number of dimensions
fFeatures WORD ? ; Bitfield indicating attributes
cbElements DWORD ? ; size of an element of the array
cLocks DWORD ? ; lock counter 0=Locked
pvData DWORD ? ; Pointer to data
rgsabound SAFEARRAYBOUND <> ; Contains info for dimensions
OLE_SAFEARRAY ends
Code:
xorbytes proc msg:DWORD, key:DWORD
push ebx
push esi
push edi
push ebp
mov eax, msg
mov ebx, key
movd MM0, esp
mov edx, [eax]
mov ecx, [ebx]
mov ebp, (OLE_SAFEARRAY ptr [edx]).rgsabound.cElements
mov ebx, (OLE_SAFEARRAY ptr [ecx]).rgsabound.cElements
mov edi, (OLE_SAFEARRAY ptr [edx]).pvData
mov esi, (OLE_SAFEARRAY ptr [ecx]).pvData
cmp ebp, 0
je done
cmp ebx, 0
je done
xor ecx, ecx
mov esp, esi
add esp, ebx
jmp For_Loop
SetKeyBack:
sub esi, ebx
jmp lblCon
align 16
For_Loop:
cmp esi, esp
je SetKeyBack
lblCon:
mov al, [esi]
xor byte ptr [edi], al
add edi, 1
add esi, 1
add ecx, 1
cmp ecx, ebp
jne For_Loop
done:
movd esp, MM0
pop ebp
pop edi
pop esi
pop ebx
ret
xorbytes endp
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
For i = 1 To Len(Message)
plainchar = Asc(Mid(Message, i, 1))
pk = Asc(Mid(key, (i Mod Len(key) + 1), 1))
buffer = buffer & Chr(plainchar Xor pk)
Next i
The only difference is that I got rid of the need for "MOD" (divisons are very epensive and I always try like hell to get rid of them) and buffer as the one in asm just xors the message that is passed to it.
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
The first comparison in the for loop (cmp esi, esp), can you find an alternative to that?
As you know, comparisons are expensive and to do one for every byte of the message/key may be slowing it down.... still, you must have a massive improvement over that hideous piece of VB code (that Im sure could also be improved)
The first comparison in the for loop (cmp esi, esp), can you find an alternative to that?
As you know, comparisons are expensive and to do one for every byte of the message/key may be slowing it down.... still, you must have a massive improvement over that hideous piece of VB code (that Im sure could also be improved)
Compare instructions aren't too bad on my processor (p4):
Clocks : 0.334644
Anyway it's a lot cheaper then multiply wich is like 18 clock cycles and divide which is like 29 clock cycles.
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
Public Function XorEncode(ByVal strMessage As String, ByVal strKey As String) As String
Dim bArrMessage() As Byte, bArrKey() As Byte, bArrOutput() As Byte
Dim msgSize As Long, keySize As Long
Dim I As Long
'convert strings to byte arrays
bArrMessage = strMessage
bArrKey = strKey
msgSize = UBound(bArrMessage) 'upper bound
keySize = LenB(strKey) 'actual size (due to the way used with Mod)
'prepare output buffer
ReDim bArrOutput(msgSize)
'without Unicode string support (step by two)
For I = 0 To msgSize Step 2
'simple Xor based on given key
bArrOutput(I) = bArrMessage(I) Xor bArrKey(I Mod keySize)
Next I
'convert byte array to string
XorEncode = bArrOutput
End Function
I don't know how well this can be compared to the ASM version, but shouldn't be too bad (considering it has to do string conversions, taking that functionality out and working with pure byte arrays would make it superb).
To make this faster:
- use SafeArray trick
- with a small trick, you can get rid of extra math required to use Mod, and so result in less overall math
Public Function XorEncode2(ByVal strMessage As String, ByVal strKey As String) As String
Dim bArrMessage() As Byte, bArrKey() As Byte, bArrOutput() As Byte
Dim msgSize As Long, keySize As Long
Dim I As Long, A As Long, B As Byte
'convert strings to byte arrays
bArrMessage = strMessage
bArrKey = strKey
msgSize = UBound(bArrMessage) 'upper bound
keySize = LenB(strKey) 'actual size (due to the way used with Mod)
'prepare output buffer
ReDim bArrOutput(msgSize)
'without Unicode string support (step by two)
For A = 0 To keySize - 1 Step 2
B = bArrKey(A)
For I = A To msgSize Step keySize
bArrOutput(I) = bArrMessage(I) Xor B
Next I
Next A
'convert byte array to string
XorEncode2 = bArrOutput
End Function
Comparison on my machine (compiled, all advanced optimizations) with 100 000 iterations:
- XorEncode: 320 ms
- XorEncode2: 275 ms
- just the string conversion stuff, reserving of memory and function call: 260 ms
Note I really had a long pause between coding it, I did it because I had nothing better to do at the time
Another note for those who might come and claim using For...Next loops are slower than Do loops: in this case and use, For loops are slightly faster. No major speed difference can be gained using Do loops instead.
Edit Simplified it a bit while the speed remained the same. Edit Slight optimization, increase in overall speed by 10ms.
Public Function XorEncode2(ByVal strMessage As String, ByVal strKey As String) As String
Dim bArrMessage() As Byte, bArrKey() As Byte, bArrOutput() As Byte
Dim msgSize As Long, keySize As Long
Dim I As Long, A As Long, B As Byte
'convert strings to byte arrays
bArrMessage = strMessage
bArrKey = strKey
msgSize = UBound(bArrMessage) 'upper bound
keySize = LenB(strKey) 'actual size (due to the way used with Mod)
'prepare output buffer
ReDim bArrOutput(msgSize)
'without Unicode string support (step by two)
For A = 0 To keySize - 1 Step 2
B = bArrKey(A)
For I = A To msgSize Step keySize
bArrOutput(I) = bArrMessage(I) Xor B
Next I
Next A
'convert byte array to string
XorEncode2 = bArrOutput
End Function
Comparison on my machine (compiled, all advanced optimizations) with 100 000 iterations:
- XorEncode: 320 ms
- XorEncode2: 275 ms
- just the string conversion stuff, reserving of memory and function call: 260 ms
Note I really had a long pause between coding it, I did it because I had nothing better to do at the time
Another note for those who might come and claim using For...Next loops are slower than Do loops: in this case and use, For loops are slightly faster. No major speed difference can be gained using Do loops instead.
Edit Simplified it a bit while the speed remained the same. Edit Slight optimization, increase in overall speed by 10ms.
right now I'm doing 1,000,001 iterations at:
90-130
Reason for such a big difference is because I don't have the algorithm testing for miss-aligned data. So its running 90 on aligned bytes and 130 on unalinged. =/ You get kicked in the balls if you don't align your data when loading 4 bytes at a time.
I also need to get it running in Parallel. Get another nice little speed boast doing that. Definitely need to get rid of that 2nd loop.
Anyway we'll be some xoring mofo's if I ever get that done. Setting up the loop to do all that is the trouble.
Last edited by Maven; Dec 26th, 2004 at 02:36 AM.
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
Just for comparison between VB6 and ASM performance (though it is still possible to optimize the VB6 code but I'm too lazy to do it).
I made them as comparable as possible, working just about the same way, removed a sub call from the faster VB one (because calling a sub in VB costs too much time in benchmarking).
Just for comparison between VB6 and ASM performance (though it is still possible to optimize the VB6 code but I'm too lazy to do it).
I made them as comparable as possible, working just about the same way, removed a sub call from the faster VB one (because calling a sub in VB costs too much time in benchmarking).
Uh, but that's not optimal at all! Doing the extra StrConv just uses extra processing power for nothing. You can actually run it in the Unicode insanely fast (as you can see from the test). No need to use slow StrConv beforehand.
The thing is, the pure VB code is still pretty fast, considering how much extra coding you had to do just to make it do that simple thing. Also, there is no need for an extra DLL (which most people prefer to avoid while making their application). And the one side being, you have to be sure you're making something compatible with all processors while coding in ASM.
I'd understand this if you were making it for something that processes several megabytes of data and you'd need to do it fast. Since you are doing only simple XOR, which pretty much everyone with some knowledge can crack, I see no real point in your project except the possibility to learn ASM.
My general point being here is that you can code fast enough code with VB. I mostly wanted to do the optimized VB code after seeing you were comparing ASM to the String-mode VB6 code with Asc and Mid, which with just one call is slower than calling the ASM code million times...
Uh, but that's not optimal at all! Doing the extra StrConv just uses extra processing power for nothing. You can actually run it in the Unicode insanely fast (as you can see from the test). No need to use slow StrConv beforehand.
The thing is, the pure VB code is still pretty fast, considering how much extra coding you had to do just to make it do that simple thing. Also, there is no need for an extra DLL (which most people prefer to avoid while making their application). And the one side being, you have to be sure you're making something compatible with all processors while coding in ASM.
I'd understand this if you were making it for something that processes several megabytes of data and you'd need to do it fast. Since you are doing only simple XOR, which pretty much everyone with some knowledge can crack, I see no real point in your project except the possibility to learn ASM.
My general point being here is that you can code fast enough code with VB. I mostly wanted to do the optimized VB code after seeing you were comparing ASM to the String-mode VB6 code with Asc and Mid, which with just one call is slower than calling the ASM code million times...
I wanted to work with it in ascii for a reason actually. When using it with other ciphers you can't have the unicde in there or you would open your message up to a freq attack. Eventually I'd like to create a set of high speed crypto functions. But that I'm afraid is a long ways off. I can program in asm but I can't completely bend it to my will as of yet. There is a whole bunch of stuff you have to know in order to really optimizing the living daylights out of code. You have to worry about latency, cpu cache, memory and code alignment, register dependencies, and various other things. Anyway I've seen people who are great at it take a good c algorithm and just simply smoke it. Eventually I wanna be able to do that lol.
Well it's not really all that much code honestly, you have to remember that ASM is a one to one with machine language. As far as dlls goes, I never did have a problem using them. As long as you don't modify the interface to the dll, you don't even have to re-compile your program.
You have processor directives that keep up with what processor your code will run on. .386 for example, will run on any 32 bit processor. It's when you start using special instructions that you have to test for processors. Examples would be: MMX, SSE, SSE2, SSE3, and 3DNow, etc.
I completely dissagree about visual basic being fast enough. Ask any user in the world, it's never fast enough.
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
Actually, I just asked on IRC and everyone said something similar to "yes, Visual Basic is fast enough" Of course it depends on what you're doing, but on most needs, VB really is enough. And VB6 isn't running all that slow compared to C/C++ as the compiler of VB6 is a hacked C/C++ compiler...
Actually, I just asked on IRC and everyone said something similar to "yes, Visual Basic is fast enough" Of course it depends on what you're doing, but on most needs, VB really is enough. And VB6 isn't running all that slow compared to C/C++ as the compiler of VB6 is a hacked C/C++ compiler...
What irc channel do you hang out in?
I think many people get too hung up in a language. Languages solve different needs and one should always gard against being too conservative in their choices of languages.
Visual basic and C++ works quite a bit differently. In C++ you are responsable for a lot more then what you are in visual basic. That and a very long history of optimization by many people other then microsoft are what make C and C++ so much faster then visual basic. The same is going to be true for the .net enviroment according to Microsoft.
Speed isn't a virtue you look for in visual basic. What you do look for is how easy it is to use. When you're programming in visual basic, you really don't have any worries. Just about every single aspect of visual basic is point and click. I think some visual basic programmer would be shocked to find out how much visual basic actually does for you. That is the best thing about visual basic though and I think microsoft did a great job at it. So if I was going to say visual basic solves a need, I would say it solves the need to do some programming work quickly and easily.
If you want to do a major application though, visual basic isn't really enough.
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde