Announcement

Collapse
No announcement yet.

XOR every byte in a string using inline ASM?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • XOR every byte in a string using inline ASM?

    Code:
    Dim sStr As String
    Dim I As Long
    For I = 1 To Len(sStr)
     MID$(sStr, I, 1) = CHR$(ASC(MID$(sStr, I, 1)) XOR 50)
    Next I
    Would anyone be kind enough to convert this to inline assembly? I need maximum speed for large files!
    Im a huge fan of assembly but this is still a bit out of my reach at the moment, still much study to do


    ------------------
    -

  • #2
    NOT TESTED haven't got PB at work ...

    Code:
    myStrLen& = LEN(myStr)
    
    ! mov eax, myStr ; string descriptor in eax
    ! cmp eax, 0     ; no str data
    ! je EndXorLoop
    
    ! mov ecx, myStrLen&
    BeginXorLoop
    ! mov eax, [eax] ; eax now is the pointer to the string data
    ! mov dl, [eax]  ; move 1 byte to dl (low byte of edx)
    ! xor dl, 50
    ! mov [eax], dl
    ! dec ecx
    ! cmp ecx, 0     ; detect end of string
    ! je EndXorLoop
    ! jmp BeginXorLoop
    
    EndXorLoop:
    If it doesn't work, tell me what error occurs. If a GPF occurs, run
    it through the debugger ...

    Best Regards
    Lothar

    ------------------

    Comment


    • #3
      Originally posted by Lothar Pink 2:
      NOT TESTED haven't got PB at work ...
      Hmm dont you think its time to find a new line of work then?

      Thanks very much Lothar! It looks spot on, I'll give it a go now and report my findings here in about 10-15 minutes


      ------------------
      -

      Comment


      • #4
        BTW, there's a wonderful ASM documentation at intel.com, I don't know
        where but I've downloaded it some time ago, and printed it (about 400 pages...)

        Assembler is very easy because only a few statements are needed for
        most tasks, and it's very easy to debug. It's more logical thought than
        programming skills that count ...

        L.

        ------------------

        Comment


        • #5
          I'm working at a press agenture, it's not really programming / PC related.

          Lothar

          ------------------

          Comment


          • #6
            Lothar, I just had to add a ":" to the end of BeginXorLoop to make it a label, and then she compiled fine.
            But it GPF'd at this line:
            ! mov dl, [eax]
            Any idea why?
            Thanks

            And yes, I want to learn assembler just for string and number manipulation, it seems to be often a lot easier (and nearly always faster) when done in asm!


            ------------------
            -

            Comment


            • #7
              Ooops...

              Code:
              myStrLen& = LEN(myStr)
              
              ! mov eax, myStr ; string descriptor in eax
              ! cmp eax, 0     ; no str data
              ! je EndXorLoop
              
              ! mov ecx, myStrLen&
              BeginXorLoop:
              ! mov dl, [eax]  ; move 1 byte to dl (low byte of edx)
              ! xor dl, 50
              ! mov [eax], dl
              ! dec ecx
              ! cmp ecx, 0     ; detect end of string
              ! je EndXorLoop
              ! inc eax
              ! jmp BeginXorLoop
              
              EndXorLoop:
              I'm sorry ...

              ------------------

              (!!! two lines have been edited, copy the whole source again !!!)




              [This message has been edited by Lothar Pink 2 (edited March 05, 2002).]

              Comment


              • #8
                PERFECT! Thankyou so very much
                These sorts of things may seem simple to people like yourself who are already asm-fluent, but as im not fluent, I find these sorts of samples the best to learn from
                I'm sure others will get some use out of this!

                Best,
                Wayne


                ------------------
                -

                Comment


                • #9
                  Well, all you have to know about asm, are the processor registers,
                  the mov statement, the jmp statement and it's derivations (in combination
                  with "cmp"), and the arithmetic statements (add, mul, dec, inc, ...)

                  I forgot push/pop.

                  It's very easy!

                  Lothar

                  ------------------


                  [This message has been edited by Lothar Pink 2 (edited March 05, 2002).]

                  Comment


                  • #10
                    Lothar, its _too_ simple, thats probably where I get confused, thinking that something should be more complex than it really is
                    Ive just been reading through your code now for the last 10 or so minutes, and I cant see any way that it could be optimised, at least I cant see any code that could be taken out or made faster... would you say this is about as fast as such an XOR loop could get?
                    Thanks i love this sorta stuff!


                    ------------------
                    -

                    Comment


                    • #11
                      Well, when dealing with large strings, it would be faster to load 32 bit
                      junks into edx, instead of loading 1-byte-junks into dl...

                      However, the string lenght MUST be a multiple of 4 then ...

                      Code:
                      myStrLen4& = LEN(myStr) \ 4 ' we are working with 4-byte-junks now...
                      
                      ! mov eax, myStr ; string descriptor in eax
                      ! cmp eax, 0     ; no str data
                      ! je EndXorLoop
                      
                      ! mov ecx, myStrLen4&
                      BeginXorLoop:
                      ! mov edx, [eax]  ; move 4 bytes to edx
                      ! xor edx, 50
                      ! mov [eax], edx
                      ! dec ecx
                      ! cmp ecx, 0     ; detect end of string
                      ! je EndXorLoop
                      ! add eax, 4
                      ! jmp BeginXorLoop
                      
                      EndXorLoop:
                      l.

                      ------------------

                      CAUTION: small bug corrected ...



                      [This message has been edited by Lothar Pink 2 (edited March 05, 2002).]

                      Comment


                      • #12
                        In case you don't know, a register is a "variable" inside the procesor.

                        A register also is a "pointer". To access the value of EAX, just write
                        EAX. To access the value of the memory address stored in EAX, use
                        [EAX].

                        So, PB ebx = eax would be
                        ! mov ebx, eax

                        and PB ebx = @eax would be
                        ! mov ebx, [eax]

                        This always moves 32-bit-chunks into the registers.
                        In order to move 16 bits, write
                        ! mov bx, [eax]

                        and in order to move 8 bits (1 byte), write
                        ! mov bl, [eax]

                        al, bl, cl, dl are 8-byte-registers which are part of eax, ...
                        ax, bx, dx, dx are 16-byte ...

                        In order to understand the code, you also need do know what "cmp" is...
                        it just compares two values.
                        The jxxx statement after the cmp statements is a conditional jump.
                        "je" means "jump if equal"
                        there are also "ja" (above), "jb" (below), "jae" jump above or equal ...
                        statements, as well as an extra set of "jxxx" statements for signed
                        integers.

                        Lothar




                        [This message has been edited by Lothar Pink 2 (edited March 05, 2002).]

                        Comment


                        • #13
                          Superb thanks, Im looking through your last two posts now
                          Incidently, I did a GetTickCount speed test using a 50mb string ("mystr = STRING$(50000000,0)")
                          Using the normal BASIC-code version of the XOR loop that I posted at the very top of this thread, that clocked in at 31625 'ticks'. Your assembly version did it in 485


                          ------------------
                          -

                          Comment


                          • #14
                            Actually, a LOT of optimization can also be done in PB code, using pointers
                            (they are VERY fast!!!)

                            You might also test the following code:

                            Code:
                            LOCAL pStr AS BYTE PTR
                            
                            pStr = STRPTR(myStr)
                            
                            FOR z& = 0 TO LEN(myStr)
                                @pStr = XOR(@pStr)
                                INCR pStr
                            
                            NEXT z&
                            As well as the following code for 4-byte-XOR...

                            Code:
                            LOCAL pStr AS LONG PTR
                            
                            pStr = STRPTR(myStr)
                            
                            FOR z& = 0 TO LEN(myStr) \ 4
                                @pStr = XOR(@pStr)
                                pStr = pStr + 4
                            
                            NEXT z&
                            The disadvantage of your code is that it allocates and frees memory
                            on every loop iteration ...

                            Lothar

                            ------------------

                            Comment


                            • #15
                              Wayne,

                              If I remember correctly I posted this algo a long time ago and its
                              the code for XOR based encryption using any length key up to the
                              source length. I think the technique is called a "one shot pad" so
                              if you want a bit more grunt than a 1 character XOR, this one should
                              help some.

                              The problem with a single character XOR is that you can break the
                              encryption in 256 or less combinations. The more characters you use,
                              the more complex it becomes to break it.

                              SPeed should be reasonable allowing that it handles the sequential
                              reading of the key string as well.

                              Regards,

                              hutch@movsd.com

                              PS : I think you can remove the 3 register preservations at the beginning
                              and end as PB does this automatically. Kust comment them out and give it
                              a whirl.

                              Code:
                                ' ###########################################################################
                                
                                FUNCTION XorString(bString$,KeyString$) as LONG
                                
                                  ' ---------------------------------------------------------------
                                  ' The method used is to read through the source string "bString$"
                                  ' one byte at a time and XOR it with the "KeyString$" which is
                                  ' also read one byte at a time. If the Keystring is shorter than
                                  ' the source string, it will loop around to the beginning of the
                                  ' keystring and continue the same process until the source string
                                  ' is completed.
                                  ' ---------------------------------------------------------------
                                
                                    #REGISTER NONE
                                
                                    LOCAL ln   as LONG      ' source length
                                    LOCAL lkey as LONG      ' key length
                                    LOCAL lref as LONG      ' counter reference for key char position
                                    LOCAL src  as LONG
                                    LOCAL lpBt as LONG
                                    LOCAL pcnt as LONG
                                    LOCAL bvar as BYTE
                                
                                    ! push ebx
                                    ! push esi
                                    ! push edi
                                
                                    ln   = len(bString$)
                                    lkey = len(KeyString$)
                                
                                    lpBt = StrPtr(KeyString$)   ' get starting address of key string
                                    pcnt = lpBt                 ' copy it to another variable
                                    lref = pcnt + lkey
                                
                                    ! mov esi, lpBt
                                    ! mov al,[esi]
                                    ! mov bvar, al      ; put 1st byte in bvar
                                
                                    src = StrPtr(bString$)
                                
                                    ! mov ecx, ln
                                    ! mov esi, src
                                    ! mov edi, src
                                
                                  xsSt:
                                    ! mov al,[esi]      ; copy 1st byte of source into al
                                    ! inc esi
                                    
                                    ! xor al, bvar      ; xor al with the byte in bvar
                                
                                    ! push eax
                                    ! push esi
                                
                                  ' ====== This code gets the next byte in the key string ======
                                  '        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                    ! inc pcnt          ; increment byte address
                                    ! mov esi, pcnt     ; put it in esi
                                    ! mov al,[esi]
                                    ! inc esi
                                
                                    ! mov ebx, lref
                                    ! cmp pcnt, ebx     ; if pcnt = lref
                                    ! jne xsNxt
                                
                                    ! mov edx, lpBt
                                    ! mov pcnt, edx     ; reset pcnt to ariginal address
                                    ! mov esi, pcnt     ; put original address in esi
                                
                                    ! mov al,[esi]
                                    ! inc esi
                                
                                  xsNxt:
                                    ! mov bvar, al      ; put the next byte in the variable
                                  ' ============================================================
                                
                                    ! pop esi
                                    ! pop eax
                                
                                    ! mov [edi], al
                                    ! inc edi
                                
                                    ! dec ecx
                                    ! cmp ecx, 0
                                    ! jne xsSt
                                
                                    ! pop edi
                                    ! pop esi
                                    ! pop ebx
                                
                                    FUNCTION = 0
                                
                                END FUNCTION
                                
                                ' ###########################################################################
                              ------------------
                              hutch at movsd dot com
                              The MASM Forum

                              www.masm32.com

                              Comment


                              • #16
                                *drool*
                                cheers for another asm gem Steve! im gonna head off now for an hour of squash, but I know what I'll be doing all evening after that ...


                                ------------------
                                -

                                Comment

                                Working...
                                X