Announcement

Collapse
No announcement yet.

copying characters from strings the fastest possible way without using asm

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

  • copying characters from strings the fastest possible way without using asm

    hello everybody,


    i am a newcomer to powerbasic even though i purchased it some time ago
    and had it laying on the shelf, like i have the 2 powerbasic for windows compilers
    on the shelf right now, but i know they will come in use later.
    i wanted to support powerbasic in its ongoing ventures so my programs will be ongoing.

    i do not understand much asm or want to use asm code if at all possible to keep
    my programs in a stardard code so i can upgrade from powerbasic for dos
    to powerbasic for windows later.
    i perfer to use compiler builtin functions when possible for compatiblity reasons.


    i have read about cell pointers and strptr and all the other powerbasic
    functions concerning pointers to strings and still a bit confused on how to accomplish
    what i want to write.

    in the powerbasic for dos 3.5 users guide on the section of pointers(@)(page 91), i have read about using the
    pointers to read the screen fast but also i want to copy(fill,plug) a string from one string to another.


    i do not want to write a function(routine) that is called , i want an inline code, but beggers
    cannot be chosers.

    i just want to copy(fill,plug) characters for one string to another as fast a possible in a program
    that i have watching what is displayed on the screen and taking some action if certain information
    is displayed on the screen, the program is a tsr that is loaded before a certain program
    and unloaded after the program has finished. it will activate every 1 second if there is
    no activity by popping down using the POPUP QUIET 18 command for tsr's.

    here is what i have so far and it is abbreiated for general purposes


    'i initialize this variable in the beginning of my progam
    'i never want the variable to be less or more than 2000 characters
    CHARACTERSONSCREEN$=SPACE$(2000)


    'here is the kicker
    'i want to transfer the characters from the screen to the above
    'string variable as fast as possible without using any asm code.
    'and here is how i do that
    'i do this many times in the tsr
    'i do not know but i have read that reading the screen with pointers
    'is a faster way to go in copying(filling,plugging) of data in powerbasic

    DIM J AS INTERGER
    DIM I AS INTERGER
    ' this next line is only placed once in the program
    CHARACTERSONSCREEN$=SPACE$(2000)

    SAVESCREEN$ = PEEK$(0,4000) ' save the entire screen
    J=0
    FOR I=0 TO 2000
    I=I+1
    J=J+1
    MID$(CHARACTERSONSCREEN$,J,1)=MID$(SAVESCREEN$,I,1)
    NEXT I

    also i want to mention, i would also like to transfer(copy,fill,plug) characters
    from one string to another fast without using asm code.
    the characters from the string being copied may only be a few characters in
    length to the total characters in the string and being placed in the
    middle of the second string.

    maybe somebody out there has already gone through some of this kind of testing for speed
    and has some answers for me.

    thanks in advance.


    ps.
    a big thanks to all those who understand asm and help me and others with by suppling your code for
    things that might otherswise be unpossible to write in normal(text)source code and for powerbasic having
    the ability to easily add asm code into the source code. both are applauded by myself.


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




    [This message has been edited by paul d purvis (edited October 09, 2003).]
    p purvis

  • #2
    Originally posted by paul d purvis:
    SAVESCREEN$ = PEEK$(0,4000) ' save the entire screen
    J%=0
    FOR I%=0 TO 2000
    I%=I%+1
    J%=J%+1
    MID$(CHARACTERSONSCREEN$,J%,1)=MID$(SAVESCREEN$,I%,1)
    NEXT I%
    You are real close here. The save screen function consists of
    two bytes for each byte of screen saved. The first character is
    the background color attribute and the 2nd character is the
    actual character itself.

    The easiest way I have found to record the contents of a screen
    into a string array is:
    Code:
    a$ = ""
    for row% = 1 to 24    'or the number of rows you have on screen
    for col% = 1 to 80    'or the number of columns on screen
    
    y% = screen(row%,col%) 'Gives the ASCII value.
    a$ = a$ + chr$(y%)
    
    next col%
    'put Cr/Lf here if you want
    next row%
    May not be the most efficient but it works okay in TEXT mode.
    Graphics mode, on the other hand, is a horse of a different
    color.

    To copy text of one string varialbe to another:
    b$ = a$

    If you want to time a particular function:
    Code:
    mtimer
    for a = b to c
    ...process
    ...process
    next a
    t = mtimer
    print;t;
    If you want to stay with SAVESCREEN$, you will have to STEP 2
    in your For/Next loop
    Code:
    for x= 2 to len(savescreen$) step 2  'Start with the 2nd (1st text) character.
    t$ = t$ + mid$(savescreen$,x,1)
    next x
    ------------------




    [This message has been edited by Mel Bishop (edited October 09, 2003).]
    There are no atheists in a fox hole or the morning of a math test.
    If my flag offends you, I'll help you pack.

    Comment


    • #3
      thanks mel,

      that code is certainly standard and might be just the ticket for transferring
      code from one compiler to another from different companies.

      mel, please go back and reread my note, i made some modifications to my text
      in the first request for help.

      something i did not see before, is that maybe i should have used
      the INCR instruction rather that the J=J+1 to make a speed improvoement.


      but i am planning on staying with powerbasic and i need(or want)speed.
      i figure the best way to keep my older slower systems running is speed.
      the program above is my first tsr and i would like to keep the tsr for interferring
      with anything the computer might need as far as computer timing goes, so therfore
      i figure in a tsr, speed may be a key issue.

      i have not done any testing on that code but unless i am not mistaken
      it would be faster to leave a string(destination) located in memory where it is and fill the
      string with characters from the source string if the destination string was already initialized to a certain length
      and will not change in length of characters for the duration of the program.

      it might also help keep from fragmenting your memory by keeping the string at its location.
      i have had that problem in a different basic compiler before,
      when i only had 64k for code and 64k for data.

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




      [This message has been edited by paul d purvis (edited October 09, 2003).]
      p purvis

      Comment


      • #4
        It's been awhile since DOS days and as you DON'T want ASM then
        you might want to give this (untested) code a shot.

        Code:
        FUNCTION fReadScreen () AS STRING
         
          DIM Col  AS INTEGER
          DIM P    AS INTEGER
          DIM Row  AS INTEGER
          DIM Tlen AS INTEGER
          DIM Tptr AS BYTE PTR
          DIM Txt  AS STRING
         
          Tlen = (ScreenX * ScreenY) + ScreenY
          Txt  = STRING$(Tlen,32)
          Tptr = STRPTR(Txt)
         
          FOR Row = 1 to ScreenY
            FOR Col = 1 to ScreenX 
              @Tptr[P] = SCREEN(Row,Col)
              INCR P
            NEXT
            INCR P
          NEXT
         
          FUNCTION = Txt
         
        END FUNCTION
        ------------------
        C'ya
        Don
        [email protected]

        [This message has been edited by Don Schullian (edited October 09, 2003).]
        C'ya
        Don

        http://www.ImagesBy.me

        Comment


        • #5
          Hmmm, "copying(filling,plugging)" ... are these intended to be synonymous
          terms? I'm a bit confused as to what is wanted there.

          Screen copying, that's no problem. I gather we're dealing with an 80x25
          text-mode screen and just want to grab all the text. So:
          Code:
              DIM ix AS INTEGER
              DIM pScreen AS BYTE PTR
              DIM pBuffer AS BYTE PTR
              DIM sBuffer AS STRING
          
              sBuffer = SPACE$(80 * 25)
              pBuffer = STRPTR32(sBuffer)
          
              pScreen = pbvScrnBuff
          
              FOR ix = 1 TO LEN(sBuffer)
                  @pBuffer = @pScreen
                  INCR pBuffer
                  INCR pScreen, 2   ' need to skip the display attribute, too
              NEXT
          ------------------
          Tom Hanlin
          PowerBASIC Staff

          Comment


          • #6
            Compatibility... this code will be completely worthless for the Windows
            compilers. Actually, it doesn't translate to PB/Win at all, as the GUI
            design uses a completely different approach to display handling. Don's
            technique will translate well enough to PB/CC, although you would do better
            to INCR Tptr directly and throw away the P index. Saving
            the screen using the SCREEN function is going to be very slow under either
            DOS or Windows, though. Maybe page flipping would be a better approach?

            ------------------
            Tom Hanlin
            PowerBASIC Staff

            Comment


            • #7
              thanks to all that answered
              and pondered on my message.

              what i really wanted was two things
              1 fast read the screen into a text variable without the screen attributes.
              2 fast string insertion

              after reviewing many notes of code in the book, a few on the forums, and
              notes from answers here is my code as of yet.
              it was really close to tom's

              what i meant by (fill,plug) was to insert characters from one string into another
              string. there is the MID$ statement, and i like it but it was slower than
              i wanted for a particular application.

              here is the code
              please feel free to edit the code and make it better anyone.
              i programmed the source on a pure dos system.
              i also ran the program on a windows nt 2000 system(500mhz), and was
              amased at how much faster the window text box mode is compared to the full screen mode.

              this program compares the speed of the my code to tom's, not that i
              am in competition with it. i wrote the program to test the best too
              codes i could find. it appears my code is faster and also note i made
              some miner changes to tom's code so that our code would be identical, basically
              removing the LEN statement and mutliplication in his code.


              REM $CPU 80386 ' program works on any CPU
              $OPTIMIZE SPEED ' make smallest possible executable
              $DEBUG MAP OFF ' turn off map file generation
              $DEBUG PBDEBUG OFF ' don't include pbdebug support in our executable
              $LIB COM OFF ' turn off PowerBASIC's communications library.
              $LIB CGA OFF ' turn off PowerBASIC's CGA graphics library.
              $LIB EGA OFF ' turn off PowerBASIC's EGA graphics library.
              $LIB LPT OFF ' turn off PowerBASIC's printer support library.
              $LIB IPRINT OFF ' turn off PowerBASIC's interpreted print library.
              $LIB FULLFLOAT OFF ' turn off PowerBASIC's floating point support.
              $ERROR BOUNDS OFF ' turn off bounds checking
              $ERROR NUMERIC OFF ' turn off numeric checking
              $ERROR OVERFLOW OFF ' turn off overflow checking
              $ERROR STACK OFF ' turn off stack checking
              $COM 0 ' set communications buffer to nothing
              $STRING 8 ' set largest string size at 8k
              $STACK 4096 ' let's use a 2k stack
              $SOUND 1 ' smallest music buffer possible
              $DYNAMIC ' all arrays will be dynamic by default
              $OPTION CNTLBREAK OFF ' don't allow Ctrl-Break to exit program
              $DIM NONE
              $COMPILE EXE ' this tells PB to make a standalone EXE
              $INCLUDE "PB35.INC"
              $LINK "PB35.Pbl"
              $EVENT OFF

              DIM I AS INTEGER
              DIM CELL AS BYTE PTR
              DIM SCRNTEXTPTR AS BYTE PTR
              DIM SCRNTEXT AS STRING
              SCRNTEXT = SPACE$( 2000 )

              INPUT "FIRST ROUTINE";A%
              B=TIMER
              FOR J=1 TO 10000
              CELL = &HB800 * 65536
              SCRNTEXTPTR = STRPTR32( SCRNTEXT )
              FOR I = 1 TO 2000
              @SCRNTEXTPTR = @CELL
              INCR SCRNTEXTPTR
              INCR CELL, 2
              NEXT
              NEXT
              PRINT TIMER-B

              DIM ix AS INTEGER
              DIM pScreen AS BYTE PTR
              DIM pBuffer AS BYTE PTR
              DIM sBuffer AS STRING
              sBuffer = SPACE$(2000)

              INPUT "SECOND ROUTINE";A%
              B=TIMER
              FOR J=1 TO 10000
              pBuffer = STRPTR32(sBuffer)
              pScreen = pbvScrnBuff
              FOR ix = 1 TO 4000
              @pBuffer = @pScreen
              INCR pBuffer
              INCR pScreen, 2 ' need to skip the display attribute, too
              NEXT
              NEXT
              PRINT TIMER-B
              END


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


              [This message has been edited by paul d purvis (edited October 10, 2003).]
              p purvis

              Comment


              • #8
                Hi Paul

                Try this one.
                Code:
                ' starting after all metastatements
                DIM ABSOLUTE Video(3999) AS BYTE AT &H0B800
                DIM I AS INTEGER
                DIM CELL AS BYTE PTR
                DIM SCRNTEXTPTR AS BYTE PTR
                DIM SCRNTEXT AS STRING
                SCRNTEXT = SPACE$( 2000 )
                '
                INPUT "FIRST ROUTINE";A%
                B=TIMER
                FOR J=1 TO 10000
                   CELL = &HB800 * 65536
                   SCRNTEXTPTR = STRPTR32( SCRNTEXT )
                   FOR I = 1 TO 4000
                      @SCRNTEXTPTR = @CELL
                      INCR SCRNTEXTPTR
                      INCR CELL, 2
                   NEXT
                NEXT
                PRINT TIMER-B
                '
                DIM ix AS INTEGER
                DIM pScreen AS BYTE PTR
                DIM pBuffer AS BYTE PTR
                DIM sBuffer AS STRING
                sBuffer = SPACE$(2000)
                '
                INPUT "SECOND ROUTINE";A%
                B=TIMER
                FOR J=1 TO 10000
                   pBuffer = STRPTR32(sBuffer)
                   FOR I = 0 TO 3999 STEP 2
                      @pBuffer = Video(I)
                      INCR pBuffer
                   NEXT
                NEXT
                PRINT TIMER-B
                END
                '
                the second one was a bit faster on my machine

                Buck




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

                Comment


                • #9
                  BUCK
                  THAT WAS AWESOME!
                  thanks for the sharing your code, that really kicked some serious
                  butt. an unbeliveable 3 times faster on my machine on your new code with
                  the DIM ABSOLUTE of an array. pat yourself on the back for me, i thought
                  the code i last wrote last would have been hard to improve over in speed and i am sure there
                  may be a lot of people to benefit from it after seeing it.
                  i figure i can now stop trying to improve the speed on this string routine.

                  what was really amazing again was that i am home now and have a faster computer thank at work running windows
                  2000 nt on a hp 1.1ghz althon machine and i ran those those routines in a window dos box and in a full screen
                  mode, and surprising the windows box still ran the program faster, and believe this condition or not,
                  the 500mhz intel computer at work, ran the routines so much faster than the machine at home which i would have
                  thought would be twice as fast.

                  i believe the video card or some other hardware different is the biggest difference.
                  i booted my hp 1.1mhz machine in pure dos mode and ran the routines above and came to the
                  the same speed in the routine as in a full screen mode in windows.
                  i have a 550 amd pentium 1 chip also at my desk that out ran my faster machine
                  at home.


                  i will add a seperate note when i figure out, if ever i do figure out what
                  is causing the problem, maybe it is just the video card.


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




                  [This message has been edited by paul d purvis (edited October 11, 2003).]
                  p purvis

                  Comment

                  Working...
                  X