Announcement

Collapse
No announcement yet.

Argument List - Optional Parameters

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

  • Argument List - Optional Parameters

    I hate to be a pain, but being new to PB and with the users manual so criptic, it is difficult to figure things out. There are two questions concerning optional parameters in an argument list. Here is sample code:

    DEFINT A - Z

    DIM aPtr AS DWORD

    aPtr = CODEPTR32(AProc)

    A = 3
    B = 7
    D = 9
    C = 25
    E = 99

    CALL DWORD aPtr CDECL(A, B, E)
    'CALL Aproc CDECL(A, B, E)

    END

    SUB Aproc CDECL(N [,I, J, L, M, O])

    PRINT N, I, J, L

    END SUB

    The questions are:

    1. Other than using asm, is there a way to tell how many parameters were passed? Printing "L" gives a "null pointer error" (error #211). The value of N in the above is 99 instead of 3 which is clearly incorrect. I realize that the parameters are placed on the stack from right to left, but it seems that N still should equal A regardless of the pass sequence.

    2. In the above code "CALL Aproc CDECL(A, B, E)" produces error #481 "parameter mismatch - may need by copy". Why? It is of the same form except for DWORD aPtr.
    Walt Decker

  • #2
    Hi again Walter...

    1. There is no built-in way to tell how many paramaters were passed - the documentation recommends that you include a parameter (usually at the start of the parameter list) that cen be used to pass a parameter count value to the function.

    2. The CDECL keyword is only necessary in DECLARE and prototype statements... when calling the sub/function you do not use the CDECL keyword:

    DECLARE SUB Aproc CDECL (ParamCount%, N [,I, J, L, M, O])
    ...
    CALL Aproc(3, A, B, E) ' no CDECL needed!
    ...
    SUB Aproc CDECL (ParamCount&, N [,I, J, L, M, O])


    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      1. There is no built-in way to tell how many paramaters were passed - the documentation recommends that you include a parameter (usually at the start of the parameter list) that cen be used to pass a parameter count value to the function.
      -------------------------------------------------------------
      Thank you, Lance. That is what the "N" is for in the param list. However, since the params are pushed onto the stack from right to left, the param counter is somewhere between BP + 2 and BP + N * 2 depending on the number of params passed. That's why N has a value of 25 when queried instead of it's original value of 3. Does passing a literal or BYVAL for the param counter change its location on stack?


      2. The CDECL keyword is only necessary in DECLARE and prototype statements... when calling the sub/function you do not use the CDECL keyword:

      DECLARE SUB Aproc CDECL (ParamCount%, N [,I, J, L, M, O])
      ...
      CALL Aproc(3, A, B, E) ' no CDECL needed!
      ...
      SUB Aproc CDECL (ParamCount&, N [,I, J, L, M, O])

      OK. So if I:

      DECLARE SUB DWORD ProcName CDECL (ParamList)

      I can use either form, eg.:

      CALL DWORD aPtr (Paramlist)
      or
      CALL ProcName(Paramlist)?


      ------------------
      Walt Decker

      Comment


      • #4
        Here is what is happening.
        When you use CALL DWORD, the parameters are pushed onto the stack
        from left to right regardless of the calling convention specified
        (CDECL or BDECL). So if your SUB specifies CDECL as the calling
        convention and you use CALL DWORD to call it, the CALL will push
        the parameters from left to right, and the SUB will read them from
        right to left, resulting in your parameters being reversed.

        DWORD cannot be included in the DECLARE for a SUB. It is just a
        way of specifying how a SUB should be called, and so can only be
        used with CALL. You can CALL a SUB with either:

        CALL ProcName()
        or
        CALL DWORD aPtr()

        regardless of how the SUB is declared.

        When specifying CDECL in a SUB, you needn't worry about where each
        parameter is located relative to BP. PowerBASIC handles that automatically,
        and as long as you use the CALL ProcName() form of calling a SUB,
        your parameters can be handled just like any other SUB. The only
        exception is the option of using a variable number of parameters.
        You must determine for your own program how many parameters were
        passed to it, which you can do by specifying it as your first parameter
        (leftmost parameter). Its the CALL statement that determines how
        many parameters actually get passed, and as long as the number of
        parameters doesn't exceed the most that the SUB will accept (and
        as long as all the REQUIRED parameters are passed), PowerBASIC
        handles all the parameter passing details automatically. No ASM
        required. The program itself must determine how many parameters were
        passed to it, by simply reading the first parameter.

        I believe CALL DWORD was meant to be used with assembly routines,
        where you retrieve the parameters yourself relative to BP, which
        is probably why the parameters are always passed in the same order,
        even with CDECL (something that is not mentioned in the documentation).


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

        Comment


        • #5
          Thank you, Mr. Grant. That matches what is displayed. The documentation is rather misleading on the way that parameters are passed since it states that CDECL causes the argument list to be passed from right to left. It seems that if the arguments are always passed from left to right a C or ASM prog expecting the parameters from right to left would also read the information in the reverse order. Oh, well, there is a way around that.

          Thanks again.



          ------------------
          Walt Decker

          Comment


          • #6
            I don't think the optional parameters can be "in the middle" of the list. How would the compiler know if the third parameter was really the second parameter?


            I think optional parameters must be last.

            MCM




            ------------------
            Michael Mattias
            Racine WI USA
            [email protected]
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              Originally posted by Michael Mattias:
              I don't think the optional parameters can be "in the middle" of the list. How would the compiler know if the third parameter was really the second parameter?


              I think optional parameters must be last.


              Michael:

              If you look at the original post you will see that the optional parameters are last. Using CALL DWORD CDECL the argument addresses are pushed on the stack from left to right but the SUB is reading them from right to left. This means that there is no way for the sub to determine how many parameters were actually passed, even using ASM (RMB/HTB has an option to do that, however). On the other hand, using a straight basic call, eg. CALL Proc(N ,I, J) the parameters are read from left to right and therefore the number of parameters can be determined.


              ------------------
              Walt Decker

              Comment


              • #8
                If you look at the original post you will see that the optional parameters are last.

                Yikes!
                Too many birthdays, or something. I thought the "J" was a closing bracket!

                (Sadly, yes, I *am* using a large font!)

                MCM
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment

                Working...
                X