'Subject: Tiny Encryption Algorithm (TEA) 'Author: Code Michael Ritter, Algo http://vader.brad.ac.uk/tea/tea.shtml 'CoAuthor: Portions taken PowerBasic Forums 'Origin: mike@cogni.to 'Ver/Date: 2002_11_06 v0.02 'Notes: Based on TEA algo at http://vader.brad.ac.uk/tea/tea.shtml ' MMX Code based on asm algo's at Power Basic forums. I do not ' know who the authors were so please notify me and I will ' add credit here. This routine is MMX enabled. In production ' code you should make sure you have a MMX capable processor. ' I wrote this to work on larger data sets and long continuous ' bit streams. This routine overwrites the source buffer as it ' processes the data. The passed source buffer must be 8 bytes or ' greater long or the routine will fail. If you need to pad data ' that is less than 8 bytes long, see the TEA_PAD8 function or ' macro for help aligning the data. '------------------------------------------------------------------------------ FUNCTION TEA_ENC_MMX ALIAS "TEA_ENC_MMX" (BYVAL pSrc AS DWORD, BYVAL pKey AS DWORD, _ BYVAL nLoops AS DWORD, BYVAL Length AS DWORD) EXPORT AS LONG 'Function Takes ' pSrc - pointer to the string that will be encoded ' pKey - pointer to the string that holds the keyword ' nLoops - the number of passes on the data ' Length - the length of the data to encode ' 'Function Returns ' long - %FALSE on error, %TRUE on success ' 'Notes: encode using TEA Cipher. This function takes a 8 byte ' aligned buffer and performs the TEA encoding algo ' on it. The source buffer is replaced with the result ' of the encode. #REGISTER NONE 'do not allow pb to register vars 'save registers, get source and destination buffers, get key ptr !pushad 'save registers !mov esi, pSrc 'pointer to source buffer into esi !mov edx, pKey 'pointer to keyword into edx 'take care of 8 byte boundry !mov ecx, Length 'length of buffer into ecx !cmp ecx, 8 'check if less than 8 bytes long !jl EX 'jump to LOB if we have less than 8 bytes 'check 8 byte boundry and get loop counter !mov eax, ecx 'copy length into eax !shr ecx, 3 'integer divide ecx by 8 for quotient !push ecx 'temporarily store ecx (quotient) value !shl ecx, 3 'integer multiply ecx (quotient) by 8 !sub eax, ecx 'subtract. length - (quotient*8) = remainder !pop ecx 'eax now has remainder and ecx has 8 byte boundry loop count. !cmp eax, 0 'compare eax (remainder) with 0 !jne EX 'jump not equal exit. data is not aligned to 8 bytes. FL: 'For Loop !movd mm0, [esi + 4] 'move data at esi + 4 into mm0 (eax) !mov ebx, nLoops 'nLoops into ebx !movd mm6, [esi] 'move data at esi into mm6 (y) !xor edi, edi 'clear edi !movq mm7, mm0 'copy of mm0 into mm7 (z) IFL: 'inner for loop. encrypt the data here using nLoops passes !movq mm1, mm0 'copy mm0 (eax) into mm1 (ebx) !pslld mm0, 4 'packed shift left logical mm0 4 bits !psrld mm1, 5 'packed shift right logical mm1 5 bits !pxor mm0, mm1 'packed xor mm0 with mm1 (eax, ebx) !paddd mm0, mm7 'packed add doublewords mm0 with mm7 (z) !mov eax, edi 'copy edi into eax !and eax, 3 'logical and eax with 3 for key entry !movd mm2, [edx + eax * 4] 'move portion of key into mm2 !movd mm3, edi 'value of edi into mm3 !paddd mm2, mm3 'add mm3 to mm2 !pxor mm0, mm2 'xor mm0 with mm2 !paddd mm0, mm6 'add mm6 to mm0 !movq mm6, mm0 'store result in mm6 (y) !add edi, &h9E3779B9??? 'add delta value to edi !movq mm1, mm0 'copy mm0 into mm1 !pslld mm0, 4 'packed shift left logical mm0 4 bits !psrld mm1, 5 'packed shift right logical mm1 5 bits !pxor mm0, mm1 'packed xor mm0 with mm1 !paddd mm0, mm6 'packed add double words mm0 with mm6 (y) !mov eax, edi 'copy edi into eax !shr eax, 11 'shift eax right 11 bits !and eax, 3 'logical and eax with 3 for key entry !movd mm2, [edx + eax * 4] 'move portion of key into mm2 !movd mm3, edi 'value of edi into mm3 !paddd mm2, mm3 'add mm3 to mm2 !pxor mm0, mm2 'xor mm0 with mm2 !paddd mm0, mm7 'add mm0 to mm7 (z) !movq mm7, mm0 'store result into mm7 (z) !dec ebx 'decriment nLoops (innerloop) counter !jnz IFL 'jump not zero inner for loop !psllq mm7, 32 'packed shift left logical mm0 32 bits !por mm6, mm7 'packed or mm6 with mm7 !movq [esi], mm6 'move result back into esi !add esi, 8 'move to next quad !dec ecx 'decriment loop counter !jnz FL 'jump not zero for loop !mov function[0], 1& 'set success condition EX: 'exit function !emms 'empty mmx state !popad 'restore registers END FUNCTION '----------------------------------------------------------------------------------- FUNCTION TEA_DEC_MMX ALIAS "TEA_DEC_MMX" (BYVAL pSrc AS DWORD, BYVAL pKey AS DWORD, _ BYVAL nLoops AS DWORD, BYVAL Length AS DWORD) EXPORT AS LONG 'Function Takes ' pSrc - pointer to the string that will be decoded ' pKey - pointer to the string that holds the keyword ' nLoops - the number of passes on the data ' Length - the length of the data to decode ' 'Function Returns ' long - %FALSE on error, %TRUE on success ' 'Notes: decode using TEA Cipher. This function takes a 8 byte ' aligned buffer and performs the TEA decoding algo ' on it. The source buffer is replaced with the result ' of the decode. the buffer should be aligned to eight ' byte boundry from already being processed by the ' encode algo. #REGISTER NONE 'do not allow pb to register vars 'save registers, get source and destination buffers, get key ptr !pushad 'save registers !mov esi, pSrc 'pointer to source buffer into esi !mov edi, pKey 'pointer to keyword into edi 'take care of 8 byte boundry !mov ecx, Length 'length of buffer into ecx !cmp ecx, 8 'check if less than 8 bytes long !jl EX 'jump to LOB if we have less than 8 bytes 'check 8 byte boundry and get loop counter !mov eax, ecx 'copy length into eax !shr ecx, 3 'integer divide ecx by 8 for quotient !push ecx 'temporarily store ecx (quotient) value !shl ecx, 3 'integer multiply ecx (quotient) by 8 !sub eax, ecx 'subtract. length - (quotient*8) = remainder !pop ecx 'eax now has remainder and ecx has 8 byte boundry loop count. !cmp eax, 0 'compare eax (remainder) with 0 !jne EX 'jump not equal exit. data is not aligned to 8 bytes. FL: 'For Loop !movd mm1, [esi] 'move data at esi into mm0 (eax) !mov ebx, nLoops 'nLoops into ebx !movq mm6, mm1 'copy mm1 into mm6 (y) !mov eax, &h9E3779B9??? 'move delta into eax !mul ebx 'multiply ebx with eax !mov edx, eax 'copy eax into edx !movd mm7, [esi + 4] 'move data at esi + 4 into mm7 (z) IFL: 'inner for loop. encrypt the data here using nLoops passes !movq mm0, mm1 'copy mm1 (y) into mm0 !pslld mm0, 4 'packed shift left logical mm0 4 bits !psrld mm1, 5 'packed shift right logical mm1 5 bits !pxor mm0, mm1 'packed xor mm0 with mm1 !paddd mm0, mm6 'packed add double words mm0 with mm6 (y) !mov eax, edx 'copy edx into eax !shr eax, 11 'shift eax right 11 bits !and eax, 3 'logical and eax with 3 for key entry !movd mm2, [edi + eax * 4] 'move portion of key into mm2 !movd mm3, edx 'value of edx into mm3 !paddd mm2, mm3 'add mm3 to mm2 !pxor mm0, mm2 'xor mm0 with mm2 !movq mm1, mm7 'copy mm7 into mm1 !psubd mm1, mm0 'sub mm0 to mm1 !movq mm7, mm1 'store result into mm7 (z) !sub edx, &h9E3779B9??? 'subtract delta value to edx !movq mm0, mm1 'copy mm1 into mm0 !pslld mm0, 4 'packed shift left logical mm0 4 bits !psrld mm1, 5 'packed shift right logical mm1 5 bits !pxor mm0, mm1 'packed xor mm0 with mm1 (eax, ebx) !paddd mm0, mm7 'packed add doublewords mm0 with mm7 (z) !mov eax, edx 'copy edx into eax !and eax, 3 'logical and eax with 3 for key entry !movd mm2, [edi + eax * 4] 'move portion of key into mm2 !movd mm3, edx 'value of edx into mm3 !paddd mm2, mm3 'add mm3 to mm2 !pxor mm0, mm2 'xor mm0 with mm2 !movq mm1, mm6 'move mm6 into mm1 !psubd mm1, mm0 'sub mm0 to mm1 !movq mm6, mm1 'store result in mm6 (y) !dec ebx 'decriment nLoops (innerloop) counter !jnz IFL 'jump not zero inner for loop !psllq mm7, 32 'packed shift left logical mm0 32 bits !por mm6, mm7 'packed or mm6 with mm7 !movq [esi], mm6 'move result back into esi !add esi, 8 'move to next quad !dec ecx 'decriment loop counter !jnz FL 'jump not zero for loop !mov function[0], 1& 'set success condition EX: 'Exit !emms 'empty mmx state !popad 'restore registers END FUNCTION '---------------------------------------------------- MACRO FUNCTION TEA_PAD8MAC_MMX (sz) 'Macro Takes: ' sz - the size of the data buffer ' 'Macro Returns: ' long - the number of bytes to pad your buffer so ' that it will fall on an 8 byte boundry. ' 'Notes: call this Macro with the size of ' your buffer and the function will ' return the number of bytes you need ' to add to your buffer to align it to a ' eight byte boundry MACROTEMP EX, LE, x DIM x AS LONG x = sz !push eax 'save eax !push ecx 'save ecx !mov ecx, x 'move sz into eax !cmp ecx, 8 'check if less than 8 bytes long !jl LE 'jump to LE if we have less than 8 bytes !mov eax, ecx 'copy ecx into eax !shr ecx, 3 'integer divide ecx by 8 !shl ecx, 3 'integer multiply ecx by 8 !sub eax, ecx 'subtract ecx from eax !mov ecx, 8 'move 8 into ecx !sub ecx, eax 'subtract eax from ecx !mov x, ecx 'move result into sz !jmp EX 'jump to exit LE: 'less than eight bytes !mov x, 8 'move 8 into sz EX: 'exit !pop ecx 'restore ecx !pop eax 'restore eax END MACRO = x '---------------------------------------------------- FUNCTION TEA_PAD8_MMX ALIAS "TEA_PAD8_MMX" (BYVAL sz AS LONG) EXPORT AS LONG 'Function Takes: ' sz - the size of the data buffer ' 'Function Returns: ' long - the number of bytes to pad your buffer so ' that it will fall on an 8 byte boundry. ' 'Notes: call this Function with the size of ' your buffer and the function will ' return the number of bytes you need ' to add to your buffer to align it to a ' eight byte boundry !push eax 'save eax !push ecx 'save ecx !mov ecx, sz 'move sz into eax !cmp ecx, 8 'check if less than 8 bytes long !jl LE 'jump to LE if we have less than 8 bytes !mov eax, ecx 'copy ecx into eax !shr ecx, 3 'integer divide ecx by 8 !shl ecx, 3 'integer multiply ecx by 8 !sub eax, ecx 'subtract ecx from eax !mov ecx, 8 'move 8 into ecx !sub ecx, eax 'subtract eax from ecx !mov function[0], ecx 'move result into function !jmp EX 'jump to exit LE: 'less than eight bytes !mov function[0], 8 'move 8 into sz EX: 'exit !pop ecx 'restore ecx !pop eax 'restore eax END FUNCTION '------------------------------------------------------------------------------ FUNCTION TEA_ENCVB_MMX ALIAS "TEA_ENCVB_MMX" (Src AS STRING, Key AS STRING, _ BYVAL nLoops AS DWORD, BYVAL Length AS DWORD) EXPORT AS LONG 'Function Takes ' Src - string that will be encoded 'pKey - string that holds the keyword ' nLoops - the number of passes on the data ' Length - the length of the data to encode ' 'Function Returns ' long - %FALSE on error, %TRUE on success ' 'Notes: encode using TEA Cipher. This function takes a 8 byte ' aligned buffer and performs the TEA encoding algo ' on it. The source buffer is replaced with the result ' of the encode. This function is for compatibility with ' VB in the way VB uses Unicode strings. #REGISTER NONE 'do not allow pb to register vars DIM sPtr AS DWORD 'pointer to the strings 'save registers, get source and destination buffers, get key ptr !pushad 'save registers sPtr = STRPTR(Src) !mov esi, sPtr 'pointer to source buffer into esi sPtr = STRPTR(Key) !mov edx, sPtr 'pointer to keyword into edx 'take care of 8 byte boundry !mov ecx, Length 'length of buffer into ecx !cmp ecx, 8 'check if less than 8 bytes long !jl EX 'jump to LOB if we have less than 8 bytes 'check 8 byte boundry and get loop counter !mov eax, ecx 'copy length into eax !shr ecx, 3 'integer divide ecx by 8 for quotient !push ecx 'temporarily store ecx (quotient) value !shl ecx, 3 'integer multiply ecx (quotient) by 8 !sub eax, ecx 'subtract. length - (quotient*8) = remainder !pop ecx 'eax now has remainder and ecx has 8 byte boundry loop count. !cmp eax, 0 'compare eax (remainder) with 0 !jne EX 'jump not equal exit. data is not aligned to 8 bytes. FL: 'For Loop !movd mm0, [esi + 4] 'move data at esi + 4 into mm0 (eax) !mov ebx, nLoops 'nLoops into ebx !movd mm6, [esi] 'move data at esi into mm6 (y) !xor edi, edi 'clear edi !movq mm7, mm0 'copy of mm0 into mm7 (z) IFL: 'inner for loop. encrypt the data here using nLoops passes !movq mm1, mm0 'copy mm0 (eax) into mm1 (ebx) !pslld mm0, 4 'packed shift left logical mm0 4 bits !psrld mm1, 5 'packed shift right logical mm1 5 bits !pxor mm0, mm1 'packed xor mm0 with mm1 (eax, ebx) !paddd mm0, mm7 'packed add doublewords mm0 with mm7 (z) !mov eax, edi 'copy edi into eax !and eax, 3 'logical and eax with 3 for key entry !movd mm2, [edx + eax * 4] 'move portion of key into mm2 !movd mm3, edi 'value of edi into mm3 !paddd mm2, mm3 'add mm3 to mm2 !pxor mm0, mm2 'xor mm0 with mm2 !paddd mm0, mm6 'add mm6 to mm0 !movq mm6, mm0 'store result in mm6 (y) !add edi, &h9E3779B9??? 'add delta value to edi !movq mm1, mm0 'copy mm0 into mm1 !pslld mm0, 4 'packed shift left logical mm0 4 bits !psrld mm1, 5 'packed shift right logical mm1 5 bits !pxor mm0, mm1 'packed xor mm0 with mm1 !paddd mm0, mm6 'packed add double words mm0 with mm6 (y) !mov eax, edi 'copy edi into eax !shr eax, 11 'shift eax right 11 bits !and eax, 3 'logical and eax with 3 for key entry !movd mm2, [edx + eax * 4] 'move portion of key into mm2 !movd mm3, edi 'value of edi into mm3 !paddd mm2, mm3 'add mm3 to mm2 !pxor mm0, mm2 'xor mm0 with mm2 !paddd mm0, mm7 'add mm0 to mm7 (z) !movq mm7, mm0 'store result into mm7 (z) !dec ebx 'decriment nLoops (innerloop) counter !jnz IFL 'jump not zero inner for loop !psllq mm7, 32 'packed shift left logical mm0 32 bits !por mm6, mm7 'packed or mm6 with mm7 !movq [esi], mm6 'move result back into esi !add esi, 8 'move to next quad !dec ecx 'decriment loop counter !jnz FL 'jump not zero for loop !mov function[0], 1& 'set success condition EX: 'exit function !emms 'empty mmx state !popad 'restore registers END FUNCTION '----------------------------------------------------------------------------------- FUNCTION TEA_DECVB_MMX ALIAS "TEA_DECVB_MMX" (Src AS STRING, Key AS STRING, _ BYVAL nLoops AS DWORD, BYVAL Length AS DWORD) EXPORT AS LONG 'Function Takes ' Src - string that will be decoded ' Key - string that holds the keyword ' nLoops - the number of passes on the data ' Length - the length of the data to decode ' 'Function Returns ' long - %FALSE on error, %TRUE on success ' 'Notes: decode using TEA Cipher. This function takes a 8 byte ' aligned buffer and performs the TEA decoding algo ' on it. The source buffer is replaced with the result ' of the decode. the buffer should be aligned to eight ' byte boundry from already being processed by the ' encode algo. #REGISTER NONE 'do not allow pb to register vars DIM sPtr AS DWORD 'pointer to the strings 'save registers, get source and destination buffers, get key ptr !pushad 'save registers sPtr = STRPTR(Src) !mov esi, sPtr 'pointer to source buffer into esi sPtr = STRPTR(Key) !mov edi, sPtr 'pointer to keyword into edi 'take care of 8 byte boundry !mov ecx, Length 'length of buffer into ecx !cmp ecx, 8 'check if less than 8 bytes long !jl EX 'jump to LOB if we have less than 8 bytes 'check 8 byte boundry and get loop counter !mov eax, ecx 'copy length into eax !shr ecx, 3 'integer divide ecx by 8 for quotient !push ecx 'temporarily store ecx (quotient) value !shl ecx, 3 'integer multiply ecx (quotient) by 8 !sub eax, ecx 'subtract. length - (quotient*8) = remainder !pop ecx 'eax now has remainder and ecx has 8 byte boundry loop count. !cmp eax, 0 'compare eax (remainder) with 0 !jne EX 'jump not equal exit. data is not aligned to 8 bytes. FL: 'For Loop !movd mm1, [esi] 'move data at esi into mm0 (eax) !mov ebx, nLoops 'nLoops into ebx !movq mm6, mm1 'copy mm1 into mm6 (y) !mov eax, &h9E3779B9??? 'move delta into eax !mul ebx 'multiply ebx with eax !mov edx, eax 'copy eax into edx !movd mm7, [esi + 4] 'move data at esi + 4 into mm7 (z) IFL: 'inner for loop. encrypt the data here using nLoops passes !movq mm0, mm1 'copy mm1 (y) into mm0 !pslld mm0, 4 'packed shift left logical mm0 4 bits !psrld mm1, 5 'packed shift right logical mm1 5 bits !pxor mm0, mm1 'packed xor mm0 with mm1 !paddd mm0, mm6 'packed add double words mm0 with mm6 (y) !mov eax, edx 'copy edx into eax !shr eax, 11 'shift eax right 11 bits !and eax, 3 'logical and eax with 3 for key entry !movd mm2, [edi + eax * 4] 'move portion of key into mm2 !movd mm3, edx 'value of edx into mm3 !paddd mm2, mm3 'add mm3 to mm2 !pxor mm0, mm2 'xor mm0 with mm2 !movq mm1, mm7 'copy mm7 into mm1 !psubd mm1, mm0 'sub mm0 to mm1 !movq mm7, mm1 'store result into mm7 (z) !sub edx, &h9E3779B9??? 'subtract delta value to edx !movq mm0, mm1 'copy mm1 into mm0 !pslld mm0, 4 'packed shift left logical mm0 4 bits !psrld mm1, 5 'packed shift right logical mm1 5 bits !pxor mm0, mm1 'packed xor mm0 with mm1 (eax, ebx) !paddd mm0, mm7 'packed add doublewords mm0 with mm7 (z) !mov eax, edx 'copy edx into eax !and eax, 3 'logical and eax with 3 for key entry !movd mm2, [edi + eax * 4] 'move portion of key into mm2 !movd mm3, edx 'value of edx into mm3 !paddd mm2, mm3 'add mm3 to mm2 !pxor mm0, mm2 'xor mm0 with mm2 !movq mm1, mm6 'move mm6 into mm1 !psubd mm1, mm0 'sub mm0 to mm1 !movq mm6, mm1 'store result in mm6 (y) !dec ebx 'decriment nLoops (innerloop) counter !jnz IFL 'jump not zero inner for loop !psllq mm7, 32 'packed shift left logical mm0 32 bits !por mm6, mm7 'packed or mm6 with mm7 !movq [esi], mm6 'move result back into esi !add esi, 8 'move to next quad !dec ecx 'decriment loop counter !jnz FL 'jump not zero for loop !mov function[0], 1& 'set success condition EX: 'Exit !emms 'empty mmx state !popad 'restore registers END FUNCTION '##################################################################################################### '##################################################################################################### 'Test app taken from PB Forums and modified. #REGISTER NONE #INCLUDE "tea.inc" DECLARE FUNCTION TEA_Decode(BYVAL sCoded AS STRING, k AS STRING * 16) AS STRING DECLARE FUNCTION TEA_Encode(BYVAL sText AS STRING, k AS STRING * 16) AS STRING '---------------------------------------------------------------------------- FUNCTION PBMAIN DIM keyWord AS STRING * 16 DIM sText AS STRING DIM sCoded AS STRING DIM sDecoded AS STRING DIM l&, t! keyWord = "this is a test" sText = "Dear PowerBasic users," & $CRLF & "TEA is working with PB very well." & SPACE$(100000) t! = TIMER sCoded = TEA_Encode(sText, keyWord) t! = TIMER - t! PRINT "486 Code time: " & STR$(t!) ' PRINT "Coded 486: " & sCoded t! = TIMER sDecoded = TEA_Decode(sCoded, keyWord) t! = TIMER - t! PRINT "486 Decode time: " & STR$(t!) ' PRINT "Decoded 486: " & sDecoded t! = TIMER sText = sText & STRING$(TEA_PAD8MAC_MMX(LEN(sText)), 0) 'align data TEA_ENC_MMX STRPTR(sText), VARPTR(keyWord), 32, LEN(sText) t! = TIMER - t! PRINT "MMX Code time: " & STR$(t!) ' PRINT "Coded MMX: " & sText t! = TIMER TEA_DEC_MMX STRPTR(sText), VARPTR(keyWord), 32, LEN(sText) t! = TIMER - t! PRINT "MMX Decode time: " & STR$(t!) ' Print "Decoded MMX: " & sText END FUNCTION '----------------------------------------------------------------------------- FUNCTION TEA_Decode(BYVAL sCoded AS STRING, k AS STRING * 16) AS STRING DIM v AS STRING * 8 DIM w AS STRING * 8 DIM sDecoded AS STRING DIM i AS LONG sDecoded = "" FOR i = 1 TO LEN(sCoded) \ 8 v = MID$(sCoded, (i - 1) * 8 + 1, 8) CALL decipherASM(BYVAL VARPTR(v), BYVAL VARPTR(w), BYVAL VARPTR(k), 32) sDecoded = sDecoded & w NEXT IF LEN(sCoded) MOD 8 > 0 THEN 'the leftover v = RIGHT$(sCoded, LEN(sCoded) MOD 8) 'CALL encipherASM(BYVAL VARPTR(v), BYVAL VARPTR(w), BYVAL VARPTR(k), 32) CALL decipherASM(BYVAL VARPTR(v), BYVAL VARPTR(w), BYVAL VARPTR(k), 32) sDecoded = sDecoded & w END IF FUNCTION = sDecoded END FUNCTION '-------------------------------------------------------------------------- FUNCTION TEA_Encode(BYVAL sText AS STRING, k AS STRING * 16) AS STRING DIM v AS STRING * 8 DIM w AS STRING * 8 DIM sCoded AS STRING DIM i AS LONG 'Test Inline Asm Version sCoded = "" FOR i = 1 TO LEN(sText)\8 v = MID$(sText, (i - 1) * 8 + 1, 8) CALL encipherASM(BYVAL VARPTR(v), BYVAL VARPTR(w), BYVAL VARPTR(k), 32) sCoded = sCoded & w NEXT IF LEN(sText) MOD 8 > 0 THEN 'the leftover v = RIGHT$(sText, LEN(sText) MOD 8) CALL encipherASM(BYVAL VARPTR(v), BYVAL VARPTR(w), BYVAL VARPTR(k), 32) sCoded = sCoded & w END IF FUNCTION = sCoded END FUNCTION '------------------------------------------------------------------------------------ FUNCTION encipherASM(BYVAL v AS DWORD PTR, BYVAL w AS DWORD PTR, BYVAL k AS DWORD PTR, BYVAL nLoops AS LONG) AS DWORD DIM y AS DWORD DIM z AS DWORD y = @v[0] z = @v[1] !MOV EDI, nLoops !MOV EDX, k !MOV EAX, z !MOV ESI, 0 eLoop: !MOV EBX, EAX !SHL EAX, 4 !SHR EBX, 5 !XOR EAX, EBX !ADD EAX, z !MOV ECX, ESI !AND ECX, 3 !MOV ECX, [EDX + ECX * 4] !ADD ECX, ESI !XOR EAX, ECX !ADD EAX, y !MOV y, EAX !ADD ESI, &H9E3779B9??? !MOV EBX, EAX !SHL EAX, 4 !SHR EBX, 5 !XOR EAX, EBX !ADD EAX, y !MOV ECX, ESI !SHR ECX, 11 !AND ECX, 3 !MOV ECX, [EDX + ECX * 4] !ADD ECX, ESI !XOR EAX, ECX !ADD EAX, z !MOV z, EAX !DEC EDI !JNZ eLoop @w[0] = y @w[1] = z END FUNCTION '----------------------------------------------------------------------------------- SUB decipherASM(BYVAL v AS DWORD PTR, BYVAL w AS DWORD PTR, BYVAL k AS DWORD PTR, BYVAL nLoops AS LONG) DIM y AS DWORD DIM z AS DWORD y = @v[0] z = @v[1] !MOV EDI, nLoops !MOV EAX, &H9E3779B9??? !MUL EDI !MOV ESI, EAX !MOV EDX, k !MOV EBX, y eLoop: !MOV EAX, EBX !SHL EAX, 4 !SHR EBX, 5 !XOR EAX, EBX !ADD EAX, y !MOV ECX, ESI !SHR ECX, 11 !AND ECX, 3 !MOV ECX, [EDX + ECX * 4] !ADD ECX, ESI !XOR EAX, ECX !MOV EBX, z !SUB EBX, EAX !MOV z, EBX !SUB ESI, &H9E3779B9??? !MOV EAX, EBX !SHL EAX, 4 !SHR EBX, 5 !XOR EAX, EBX !ADD EAX, z !MOV ECX, ESI !AND ECX, 3 !MOV ECX, [EDX + ECX * 4] !ADD ECX, ESI !XOR EAX, ECX !MOV EBX, y !SUB EBX, EAX !MOV y, EBX !DEC EDI !JNZ eLoop @w[0] = y @w[1] = z END SUB