Announcement

Collapse
No announcement yet.

an array of label addresses?

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

  • an array of label addresses?

    I appreciate that this may not be "do-able" but I've got to ask...
    Is this possible...
    Currently...I have an array of codeptrs and call them in turn to execute a program...See post #4 here...
    http://www.powerbasic.com/support/pb...ad.php?t=50198
    I'd like to reduce the call overhead by placing my procedures in subroutines.
    The problem is...I'd like to invoke these from outside the procedure containing the subroutines.
    Because...I don't know how/it can't be done....
    I'd currently have to supply an array of TOKENS into the the procedure containing the subroutines i.e. Interpret() and...
    TRANSLATE them into labels which could then be jumped to via GOSUB.
    If possible...I'd like to bypass the TRANSLATE operation and just GOSUB <the contents of each array element> to speed things up
    i.e.
    Code:
    'pseudo code
    SUB Interpret(aTkn() AS LONG)
        FOR i = LBOUND(aTkn) TO UBOUND(aTkn)
            GOSUB aTkn(i)
        NEXT
        'rather than eg...
        'FOR i = LBOUND(aTkn) TO UBOUND(aTkn)
           'select case
                'case aTkn(i) 'ie not a label addr but some other representative token
                   'gosub prim1
        'which is more indirect
        EXIT SUB
    prim1:
        ? "prim1"
        RETURN
    prim2:
        ? "prim2"
        RETURN
    END SUB
    
    
    FUNCTION PBMAIN () AS LONG
        '...create an array of label addresses ie addr of prim1 etc outside of Interpret()
    END FUNCTION
    Last edited by Dean Gwilliam; 6 May 2012, 03:39 AM.

  • #2
    Gosub dword

    Comment


    • #3
      John
      WOW!!!...GOSUB DWORD

      I wasn't aware of' this because I thought I "knew" how GOSUB worked and so never read help on GOSUB.

      Help says...
      dwpointer must be a Double word, Long integer, or pointer variable that contains the address of a label that is in the same procedure as the GOSUB DWORD statement.

      Now all I need to know is how you get the "address of a label" and it's sorted.

      Thank you very much indeed.
      That's made my day!

      Comment


      • #4
        Dean,
        CODEPTR() will give you the address of a label but you say you want to jump to a label in a different SUB which will be a problem.

        Paul

        Comment


        • #5
          A dword is a dword and a RET is a RET, unless PB "adds value" to the GOSUB call by including a localising reference, like the stack ptr, it should be possible.

          Grisly, but possible.

          I can't wait to discover the why of this.

          Comment


          • #6
            Paul is correct on two points.
            You simply build the array at the start of the sub or function using Codepointer Label
            His second point (warning) is also correct as the Gosub addresses must be in the same procedure (sub or function) as the Gosub requirements you quote from the manual.
            If as you say they are outside the current procedure then you need to make them seperate procedures and use Call Dword.
            If you have WIN10 or CC6 (which I dont yet) and want the best of both worlds, code outside the procedure but not have the overhead time of a procedure call then there is a new feature called I think Fastproc or something like that.

            Comment


            • #7
              Originally posted by Chris Holbrook View Post
              A dword is a dword and a RET is a RET, unless PB "adds value" to the GOSUB call by including a localising reference, like the stack ptr, it should be possible.

              Grisly, but possible.

              I can't wait to discover the why of this.
              Manual is very explicit about this point as to what the compiler can handle. As this is the Asm forum you can write your own.
              Hutch an Asm expert raised this point for years and the result is Fastproc (if that is what it is called)

              Comment


              • #8
                @John

                I realised a bit late that the compiler could also enforce it at compile time using a range check but it appears not to do so.
                Code:
                #compile exe
                #dim all
                global adword as dword
                
                '
                sub a
                    
                    gosub dword adword
                    ? "back to sub a"
                end sub
                '
                function b as dword
                    function = codeptr(1)
                    exit function
                1:
                     ? "sub B, label 1"
                     return
                end function
                '
                function pbmain () as long
                
                    adword = b()
                    a
                
                end function

                It is still horrible.

                Comment


                • #9
                  Originally posted by Chris Holbrook View Post
                  A dword is a dword and a RET is a RET, unless PB "adds value" to the GOSUB call by including a localising reference, like the stack ptr, it should be possible.

                  Grisly, but possible.

                  I can't wait to discover the why of this.
                  A possible reason is a Gosub can use variables Local to the procedure and any reference to them outside the procedure could cause problems

                  Comment


                  • #10
                    Dean
                    Actually you don't even need to build the array of Codeptrs if you have less that 256 tests, just use ON GOSUB
                    Code:
                    local x as long
                    for x = 1 to (number of tests)
                        ON x GOSUB Label1, Label2, Label3 etc
                    next

                    Comment


                    • #11
                      Paul, Chris, John
                      >CODEPTR() will give you the address of a label
                      Great!
                      I'm really grateful for your advice and interest...it helps a lot.
                      >I can't wait to discover the why of this.
                      I'm putting an interpreter together and am not clever enough to do a BASIC one so I'm reverting to a Forth-like one. That doesn't mean I don't want speed and to get this...when in interactive mode...I'm going to have a compile flag so that when I interpret the language word strings that I write in an editor...I'll also write the tokens (codeptr(labels)) which are used as jump addresses to an array, along with numbers and variable addresses so as to create a "compiled" program. That way when you run the "compiled" program you're just doing a series of jumps inside the interpreter proc rather than having to search for the word strings in the "dictionary" first.
                      I thought I was going to need a return stack but am hoping that GOSUB as opposed to GOTO is going to look after this for me.

                      Once again...thanks for your help!

                      Comment


                      • #12
                        Originally posted by Dean Gwilliam View Post
                        Paul, Chris, John
                        >CODEPTR() will give you the address of a label
                        Great!
                        I'm really grateful for your advice and interest...it helps a lot.
                        >I can't wait to discover the why of this.
                        I'm putting an interpreter together and am not clever enough to do a BASIC one so I'm reverting to a Forth-like one. That doesn't mean I don't want speed and to get this...when in interactive mode...I'm going to have a compile flag so that when I interpret the language word strings that I write in an editor...I'll also write the tokens (codeptr(labels)) which are used as jump addresses to an array, along with numbers and variable addresses so as to create a "compiled" program. That way when you run the "compiled" program you're just doing a series of jumps inside the interpreter proc rather than having to search for the word strings in the "dictionary" first.
                        I thought I was going to need a return stack but am hoping that GOSUB as opposed to GOTO is going to look after this for me.

                        Once again...thanks for your help!
                        WOW haven't used Forth for 30 years. A great stack based language that required a minimum of built in procedures. I think it is the forerunner of Postscript which I have also written in.
                        Please share what you come up with and happy to help.

                        Comment


                        • #13
                          John
                          I just came back to say thanks for the fastproc suggestion. I do have 10.
                          Today's a bit "fragmented" i.e. I'm getting distracted by some other stuff, hence the delays and short responses.
                          >Please share what you come up with and happy to help.
                          Absolutely...
                          This is very much my take on Forth i.e. I've been brain-storming re how to do what I need to do for a few days and I think I've finally got something.
                          Please stay tuned...it'll take a little while but I am happy to share it and thank you for your kind offer.

                          Comment


                          • #14
                            Just tested solution by Chris and It works with minor changes

                            Code:
                            function b as dword
                                function = codeptr(e)
                                exit function
                            e:
                                 ? "sub B, label 1"
                                 return
                            end function

                            Comment


                            • #15
                              [QUOTE=Aslan Babakhanov;405902]Just tested solution by Chris and It works with minor changes

                              [CODE]Should have mentioned that I compiled it with PBWIn V9 as I happened to have that IDE open.

                              Comment


                              • #16
                                I have both PB9 and PB10 installed separately.
                                Version with numebred label compiling and running fine with PB9.
                                But gives error with PB10.

                                Comment


                                • #17
                                  In taking a while to respond to John yesterday I think I missed some of the discussion and code.
                                  Here's the sort of thing I had in mind.
                                  I'm sure Paul's right re the problem of using codeptrs outside of Interpreter() but...
                                  as you can see...
                                  the table of codeptrs is built INSIDE the proc containing them and then passed out so...no problem!
                                  i.e. it seems to work ok.
                                  I've included only enough code to show the concept
                                  i.e. I've omitted writing the "program" using string tokens and building higher level words
                                  i.e. I've just provided a ready-compiled "program" and run it.
                                  I was an advocate of Fastproc's creation and have only gone for GOSUB because I think it's about 2X faster.
                                  More to come!

                                  BTW I'd like to chop the decision code down, under 'compile:' to save as many cycles as possible
                                  ie the code which decides whether to gosub dword <the number> or place <the number> on the stack.


                                  Code:
                                  #COMPILE EXE
                                  #DIM ALL
                                  #DEBUG ERROR ON
                                  #DEBUG DISPLAY ON
                                  
                                  
                                  TYPE tJmp_tbl
                                      wrd AS ASCIZ * 100
                                      pSub AS DWORD
                                  END TYPE
                                  
                                  
                                  SUB Interpreter(aPrg&(), OPT aPrg$(), aJmp_tbl() AS tJmp_tbl)
                                      LOCAL i&,j&,ln$,tkn$,found&
                                      STATIC aJmp() AS tJmp_tbl,aStk() AS DWORD
                                      DIM aStk(10)
                                      IF ISFALSE ISMISSING(aJmp_tbl()) THEN GOSUB fill_jmp_tbl : EXIT SUB
                                      IF ISMISSING(aPrg$()) THEN GOSUB compile : EXIT SUB
                                      GOSUB interpret
                                      EXIT SUB
                                  fill_jmp_tbl:
                                      REDIM aJmp(4)
                                      aJmp(0).wrd = "prim0" : aJmp(0).pSub = CODEPTR(prim0)
                                      aJmp(1).wrd = "prim1" : aJmp(1).pSub = CODEPTR(prim1)
                                      aJmp(2).wrd = "colon" : aJmp(2).pSub = CODEPTR(colon)
                                      aJmp(3).wrd = "comma" : aJmp(3).pSub = CODEPTR(comma)
                                      DIM aJmp_tbl(LBOUND(aJmp) TO UBOUND(aJmp)) AT VARPTR(aJmp(0))
                                      RETURN
                                  compile:
                                      FOR i& = LBOUND(aPrg&) TO UBOUND(aPrg&) 'why is UBOUND 4 and not 3???
                                          found& = -1
                                          FOR j& = LBOUND(aJmP) TO UBOUND(aJmp)
                                              IF aPrg&(i&) = aJmp(j&).pSub THEN
                                                  found& = j&
                                                  EXIT FOR
                                              END IF
                                          NEXT
                                          IF found& <> -1 THEN
                                              GOSUB DWORD aPrg&(i&)
                                          ELSE
                                              ? "placing " & STR$(aPrg&(i&)) & " on aStk()"
                                          END IF
                                      NEXT
                                      RETURN
                                  interpret:
                                      'not implemented yet but you get the idea
                                      FOR i& = LBOUND(aPrg$) TO UBOUND(aPrg$)
                                          ln$ = aPrg$(i&)
                                          FOR j& = 1 TO PARSECOUNT(ln$,$SPC)
                                              tkn$ = PARSE$(ln$,$SPC,j&)
                                              'process tkn$
                                          NEXT
                                      NEXT
                                      RETURN
                                  prim0:
                                      ? "prim0"
                                      RETURN
                                  prim1:
                                      ? "prim1"
                                      RETURN
                                  colon:
                                      ? "colon"
                                      RETURN
                                  comma:
                                      ? "comma"
                                      RETURN
                                  END SUB
                                  
                                  
                                  FUNCTION PBMAIN () AS LONG
                                      LOCAL aInterpreted$() : DIM aInterpreted$(7)
                                      LOCAL aJmp_tbl() AS tJmp_tbl
                                      LOCAL aCompiled&() : DIM aCompiled&(3)
                                  'make primitives jmp tbl
                                      Interpreter(aCompiled&(),aInterpreted$(),aJmp_tbl())
                                  '"compiled" program
                                      aCompiled&(0) = aJmp_tbl(0).pSub
                                  '   aCompiled&(1) = aJmp_tbl(1).pSub
                                  '   replace with a number just to show what happens to non-words
                                      aCompiled&(1) = 3
                                      aCompiled&(2) = aJmp_tbl(2).pSub
                                      aCompiled&(3) = aJmp_tbl(3).pSub
                                  'run "compiled program"
                                      Interpreter(aCompiled&())
                                  END FUNCTION
                                  Last edited by Dean Gwilliam; 7 May 2012, 08:55 AM.

                                  Comment


                                  • #18
                                    Version with numebred label compiling and running fine with PB9.
                                    But gives error with PB10.
                                    If the code is truly identical and none of the intrinsics are "Improved!" then that should be reported to PowerBASIC support.

                                    That said, the change to wide chars as the default condition means the source code cannot be identical, at the very least you'd need an #OPTION ANSIAPI directive.

                                    However I would think the inclusion of that directive should create sufficient equality that the program should run identically without regard to the compiler version used.

                                    All that said...
                                    Code:
                                    'why is UBOUND 4 and not 3???
                                    .... your problem is here....

                                    Code:
                                    DIM aJmp_tbl(LBOUND(aJmp) TO UBOUND(aJmp)) AT VARPTR(aJmp(0))
                                    A second DIM (vs REDIM) of the same array is ignored without warning or error. In essence, that statement never happened so your bounds do not change.

                                    MCM
                                    Michael Mattias
                                    Tal Systems Inc.
                                    Racine WI USA
                                    mmattias@talsystems.com
                                    http://www.talsystems.com

                                    Comment


                                    • #19
                                      Re 'why is UBOUND 4 and not 3???...is just my ramblings.
                                      I'd misunderstood that you get 1+the subscript size cells due to cell 0
                                      i.e. at the time I thought 3 would give me 0 to 2 cells until I read help.

                                      aJmp_tbl() is dim'd only once
                                      i.e. it's just LOCAL'd outside of Interpreter()...and then supplied as an argument, byref, for dim-ing and filling.

                                      Your observations are understandable given my comment which should have been removed and I thank you for them.

                                      If anyone's wondering why the asm sub-forum...it's because this is likely to be a mixed PB/asm app.
                                      I have no problem moving it to the programming sub-forum if that's more appropriate.
                                      Last edited by Dean Gwilliam; 9 May 2012, 02:11 PM.

                                      Comment


                                      • #20
                                        Dean, what does your code do that couldn't be done with an ON GOSUB?

                                        Comment

                                        Working...
                                        X