Announcement

Collapse
No announcement yet.

FastProc

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

  • FastProc

    I have over 1600 snippets in my gbSnippets library, and not a single one that uses FastProc.

    Do folks use it all that much? Apparently I don't.

  • #2
    I think a lot of us have not really gotten into the habit of checking to see if it is more suitable than old standbys. I know that applies to me.
    It is a nifty tool in the box.
    I'm glad you brought this up.
    Rod
    "To every unsung hero in the universe
    To those who roam the skies and those who roam the earth
    To all good men of reason may they never thirst " - from "Heaven Help the Devil" by G. Lightfoot

    Comment


    • #3
      It very much depends on the type of code you write. If you normally write high level code, it is of limited use to you apart from some simplified 2 argument forms but if you write low level code it removes all of the high level overhead and you can write whatever you like in assembler. To expand this some, Bob was an assembler language programmer and among the target he had in mind was writing a newer version of PB in PB and this required some more low level power than traditional basic. FASTPROC and ASMDATA are very useful for a task as complicated as writing a compiler but they are both lower level than traditional basic. Here is an example.
      Code:
      ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      
          MACRO szcopy(src,dst)
            PREFIX "!"
              push pdst
              push psrc
              call szcopy_string
            END PREFIX
          END MACRO
      
      ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      
       FASTPROC szcopy_string
      
          PREFIX "!"
      
          mov ecx, [esp+4][4]
          mov edx, [esp+8][4]
          sub ecx, 1
      
        lbl0:
          add ecx, 1
          movzx eax, BYTE PTR [ecx]
          mov BYTE PTR [edx], al
          add edx, 1
          test eax, eax
          jz lbl1
      
          add ecx, 1
          movzx eax, BYTE PTR [ecx]
          mov BYTE PTR [edx], al
          add edx, 1
          test eax, eax
          jnz lbl0
      
        lbl1:
          ret 8
      
          END PREFIX
      
       END FASTPROC
      
      ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      hutch at movsd dot com
      The MASM Forum

      www.masm32.com

      Comment


      • #4
        I don't. As Steve says, it depends on the type of code you write.

        In the absence of local variables and with limited parameters, I would find little use for FASTPROC in the sort of programming that I do. (It's predominantly data related, especially string data) Even where a FASTPOC would be feasible, I really can't recall a situation where the decreased processing time would have been significant.

        Also, I like to be consistent in my coding and I eschew SUBS. Everything is a FUNCTION whether it needs a return value or not (if not, I just return a default LONG) so I don't really think about alternatives such as SUB or FASTPROC when designing a program.

        There is no doubt that FASTPROC is a very useful construct for some programming environments, just not mine.


        Comment


        • #5
          Thanks for raising this Gary.

          I never even knew it existed.

          I may have some applications for it - and I have stored it away in my memory.

          It would be interesting to see some analyses of situations where it is faster - and by how much.

          There are two reasons for using SUBs and FINCTIONs. One is that the make the code easier to read and one is that it saves RAM. I am not sure if saving RAM is really an issue today. An even faster FASTPROC would be just to duplicate the code wherever you would normally use a SUB or FUNCTION. You cannot get faster than that.

          Normally such excessive speed is only required in small parts of the program ie for most of the program you can use the old fashioned slow way. But for the core of the calculation, you might use FASTPROC.

          Note to self - one day when you have a week to spare, I order myself to read through carefully every PB instruction. { I wonder if that time will ever come???}
          [I]I made a coding error once - but fortunately I fixed it before anyone noticed[/I]
          Kerry Farmer

          Comment


          • #6
            Originally posted by Kerry Farmer View Post
            Note to self - one day when you have a week to spare, I order myself to read through carefully every PB instruction. { I wonder if that time will ever come???}
            Great minds think alike (or maybe it's "fools never differ" )
            My comment in another thread a couple days ago:

            "Note the {sic - typo] self: again!

            Comment


            • #7
              Here is an example of the difference when using a FASTPROC, 1st is a basic function, second is a no stack frame FASTPROC and the third is an emulated FASTCALL FASTPROC. To provide the facilities for a high level language like BASIC, you carry the additional overhead and while in many instances it simply does not matter, it jumps up and bites you (not BYTES you) if you are processing large volumes of data. Its a normal trade between flexibility versus performance. The three (3) algorithms below use the identical loop code and differ only in how the argument is passed and whether it uses a stack frame.
              Code:
              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
              
                  #include "\basic\include\win32api.inc"
              
              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
              
              FUNCTION PBmain as LONG
              
                  LOCAL sadr as DWORD
                  LOCAL slth as DWORD
              
                  a$ = "12345678901234567890"     ' 20 characters
              
                  sadr = StrPtr(a$)
              
                ' ---------------
                ' high level call
                ' ---------------
                  slth = lenz(sadr)
                  msgbox format$(slth),0,"High level"
              
                ' -----------------------------------
                ' no stack frame, arg passed on stack
                ' -----------------------------------
                PREFIX "!"
                  push sadr
                  call zslen
                  mov slth, eax
                END PREFIX
                  msgbox format$(slth),0,"No stack frame"
              
                ' -----------------------------------
                ' FASTCALL arg passed in EAX register
                ' -----------------------------------
                PREFIX "!"
                  mov eax, sadr
                  call fclen
                  mov slth, eax
                END PREFIX
                  msgbox format$(slth),0,"FASTCALL procedure"
              
              End FUNCTION
              
              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
              ' ---------------------
              ' high level basic call
              ' ---------------------
              FUNCTION lenz(ByVal pstr as DWORD) as DWORD
              
                  #REGISTER NONE
              
                  PREFIX "!"
              
                  mov eax, pstr           ; move stack variable into EAX
                  sub eax, 1              ; decrement EAX
                lbl:
                  add eax, 1              ; add 1 at front of loop
                  cmp BYTE PTR [eax], 0   ; compare BYTE to zero
                  jne lbl                 ; loop back if not zero
              
                  sub eax, pstr           ; subtract original address from EAX to get length
                  mov FUNCTION, eax       ; return length in EAX
              
                  END PREFIX
              
              End FUNCTION
              
              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
              ' -----------------------------------
              ' no stack frame, arg passed on stack
              ' -----------------------------------
              FASTPROC zslen
              
                  PREFIX "!"
              
                  mov eax, [esp+4]        ; load string address into EAX
                  mov ecx, eax            ; save EAX into ECX
                  sub eax, 1              ; decrement EAX
                lbl:
                  add eax, 1              ; add 1 at front of loop
                  cmp BYTE PTR [eax], 0   ; compare BYTE to zero
                  jne lbl                 ; loop back if not zero
              
                  sub eax, ecx            ; subtract original address from EAX to get length
                  ret 4                   ; balance the stack
              
                  END PREFIX
              
              END FASTPROC
              
              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
              ' -----------------------------------
              ' FASTCALL arg passed in EAX register
              ' -----------------------------------
              FASTPROC fclen
              
                  PREFIX "!"
              
                  mov ecx, eax            ; save EAX into ECX
                  sub eax, 1              ; decrement EAX
                lbl:
                  add eax, 1              ; add 1 at front of loop
                  cmp BYTE PTR [eax], 0   ; compare BYTE to zero
                  jne lbl                 ; loop back if not zero
              
                  sub eax, ecx            ; subtract original address from EAX to get length
                  ret                     ; return with length in EAX
              
                  END PREFIX
              
              END FASTPROC
              
              ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
              
              #IF 0  ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
              
              -----------------------------------------------------------
                  BASIC FUNCTION  28 instructions
              -----------------------------------------------------------
              00201190                    fn_00201190:
              00201190 55                     push    ebp
              00201191 8BEC                   mov     ebp,esp
              00201193 53                     push    ebx
              00201194 56                     push    esi
              00201195 57                     push    edi
              00201196 683F130000             push    133Fh
              0020119B 83EC70                 sub     esp,70h
              0020119E 6890112000             push    offset fn_00201190
              002011A3 31F6                   xor     esi,esi
              002011A5 56                     push    esi
              002011A6 56                     push    esi
              002011A7 56                     push    esi
              002011A8 56                     push    esi
              002011A9 56                     push    esi
              002011AA 8B4508                 mov     eax,[ebp+8]
              002011AD 2D01000000             sub     eax,1
              002011B2                    loc_002011B2:
              002011B2 0501000000             add     eax,1
              002011B7 803800                 cmp     byte ptr [eax],0
              002011BA 0F85F2FFFFFF           jne     loc_002011B2
              002011C0 2B4508                 sub     eax,[ebp+8]
              002011C3 898568FFFFFF           mov     [ebp-98h],eax
              002011C9                    off_002011C9:
              002011C9 8B8568FFFFFF           mov     eax,[ebp-98h]
              002011CF 8D65F4                 lea     esp,[ebp-0Ch]
              002011D2 5F                     pop     edi
              002011D3 5E                     pop     esi
              002011D4 5B                     pop     ebx
              002011D5 5D                     pop     ebp
              002011D6 C20400                 ret     4
              
              -----------------------------------------------------------
                  NO STACK FRAME PROCEDURE    8 instructions
              -----------------------------------------------------------
              002011E0                    fn_002011E0:
              002011E0 8B442404               mov     eax,[esp+4]
              002011E4 8BC8                   mov     ecx,eax
              002011E6 2D01000000             sub     eax,1
              002011EB                    loc_002011EB:
              002011EB 0501000000             add     eax,1
              002011F0 803800                 cmp     byte ptr [eax],0
              002011F3 0F85F2FFFFFF           jne     loc_002011EB
              002011F9 2BC1                   sub     eax,ecx
              002011FB C20400                 ret     4
              
              -----------------------------------------------------------
                  FASTCALL DATA PASSED IN REGISTER    7 instructions
              -----------------------------------------------------------
              00201200                    fn_00201200:
              00201200 8BC8                   mov     ecx,eax
              00201202 2D01000000             sub     eax,1
              00201207                    loc_00201207:
              00201207 0501000000             add     eax,1
              0020120C 803800                 cmp     byte ptr [eax],0
              0020120F 0F85F2FFFFFF           jne     loc_00201207
              00201215 2BC1                   sub     eax,ecx
              00201217 C3                     ret
              
              -----------------------------------------------------------
              
              #ENDIF ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
              hutch at movsd dot com
              The MASM Forum

              www.masm32.com

              Comment


              • #8
                I may be wrong, but as I understand it, your 28:8:7 instruction count is only valid for a Null string.

                The add, cmp, jne loop would be repeated for each character plus once more for the Null

                So with your 20 byte string, the actual instruction ratio would be: 88:68:67.

                If you are manipulating really large strings, the difference becomes trivial.

                Comment


                • #9
                  That is correct for the iteration count for each procedure call, if you are doing a single large count, the gain becomes trivial but if the procedure is called a large number of times, the gain becomes very noticeable as you have to shovel through all of the setup code to get to the loop code. All three have the same 3 instruction loop code so you will have that as a constant between the three algorithms but the big difference is in the setup code, the no stack frame version only has the original CALL and a RET 4 as overhead where the emulated FASTCALL passes in a register with no PUSH and exits with a RET.

                  With a very short algorithm like these ones, in some circumstances directly inlining the code is more efficient again as it removes the CALL / RET completely.
                  hutch at movsd dot com
                  The MASM Forum

                  www.masm32.com

                  Comment


                  • #10
                    I've used it frequently to be able to create command tables with CODEPTR addresses of exposed METHODS in an object. Obviously CODEPTR can't do it so I create small stubs like the following. Letting me code CODEPTR(PTPowerCopy) etc.

                    Code:
                    FASTPROC PTPowerCopy:       TP.PTPowerCopy:             END FASTPROC
                    FASTPROC PTPowerCut:        TP.PTPowerCut:              END FASTPROC
                    FASTPROC PTPowerPaste:      TP.PTPowerPaste:            END FASTPROC
                    George

                    Comment

                    Working...
                    X