No announcement yet.

Undocumented BDECL in PB DOS 3.2+

  • Filter
  • Time
  • Show
Clear All
new posts

  • Undocumented BDECL in PB DOS 3.2+

    Hello to all PB-(DOS-)Users,
    I am confused about an undocumented BDECL, I found in an old Listing from Jamshid Khoshrangi, Code: PB32, Packet: PB.ABC, Date: 10-05-95:

    FOR x = 1 TO 8

    ' The appropriate SUB is called by means of a code pointer,
    ' and the parameters are passed accordingly, using the newly
    ' introduced BDECL format....

    CALL DWORD CodePtrTable(x) BDECL (one, two, three)

    NEXT x
    I searched for BDECL in the Manuals from PB 3.2 and in the PDF-Versions of PB 3.5: There was only CDECL discribed (online-help 3.5).

    What is BDECL good for? And who knows about it in PB DOS and used it?

    The code from Jamshid Khoshrangi works fine, but I want to understand it a bit better.


  • #2
    Andy. In another manual for PB console compiler.
    Read from the instructions of the FUNCTION/END FUNCTION statement.
    That will help you some. I am reading now from my manual inside version 4 of the console compiler but I would think both manuals for the current versions of aconsoke and Wimdiw compilers should have the same instructions.
    Read those few pages then come back.
    p purvis


    • #3
      Hi Paul,
      have many thanks for your answer.
      I only use PB DOS and only have manuals for PB DOS Version 3 and digtal up to Version 3.5.
      That is the reason, why I ask here for answers.


      • #4
        BDECL stands for "BASIC declaration" so it would be the PB/DOS default method. You can optionally override that with CDECL, which is short for "C declaration", if you are using a function that requires the C calling convention.

        I suspect that if BDECL compiles under PB/DOS it doesn't actually do anything, other than tell the compiler to use its default method.
        "Not my circus, not my monkeys."


        • #5
          Hello Eric,

          your words make me laugh! :-)
          How funny to search something, I have always used for so long... :-D
          On the Net I found the following description from an onlinehelp for pb/cc 5:
          BDECL Specifies that the declared procedure uses the BASIC/Pascal calling convention. When a procedure calls a BDECL procedure, it passes its parameters on the stack from left to right.

          It is the responsibility of the called procedure to clean up the stack before returning to the calling procedure. Therefore, all PowerBASIC Subs and Functions that specify the BDECL convention automatically clean up the stack before execution returns to the calling code.
          Sounds the way you wrote me.
          Many thanks to you, Eric!



          • #6
            Andy. I looked at the REF,PDF for PBDos 3.5 and there were some description in there but not as much as PBCC version 4. I did see all manuals for the last 3 different versions and I looked at PBCC 6. Wow. Over 3000 pages in that manual. Anyway, the wording in these later manuals were improved and that is why I sent you to read those
            p purvis


            • #7
              I thank you both, Paul and Eric.
              While I was very interested, I tested the code without the BDECL and it worked very fine! :-)
              So it seems, that PB 3.5 was in some ways a kind of "father" or "mother" of its later children... ;-)

              Paul, do you have a pagenumber for me?
              I searched in the PBFs of Version 3.5 for BDECL without success.

              Have a nice day, night or whatever,
              Andy :-)


              • #8
                Andy. There is a User manual and Reference manual.
                In the Refence manual, look under Function/End Function.
                p purvis


                • #9
                  In the PDF-File of my PB 3.5-Version, one can find the following information:
                  Originally posted by PowerBASIC 3.5 - Reference Guide, Page 128ff on paper, 138ff in file
                  FUNCTION/END FUNCTION statements
                  FUNCTION and END FUNCTION define a function block.
                  FUNCTION name [CDECL] [(parameters)] [LOCAL|SHARED|STATIC] [PUBLIC|PRIVATE]
                  [LOCAL variable list]
                  [STATIC variable list]
                  [SHARED variable list]
                  { statements }
                  [{name|FUNCTION} = return value]
                  { statements }
                  [EXIT FUNCTION]
                  { statements }
                  END FUNCTION
                  Use FUNCTION/END FUNCTION to define a function block. These are "true" functions,
                  offering more flexibility than functions defined with DEF FN/END DEF.
                  name is the name of the function, including a type specifier (just like an ordinary variable name);
                  this determines the type of the function's return value. It must be unique: No other variable,
                  function, procedure, subroutine, or label can share it.
                  return value is the value to be returned by the function.
                  parameters is an optional, comma-delimited sequence of formal parameters. The parameters used
                  in the argument list serve only to define the function; they have no relationship to other variables
                  in the program with the same name. The default variable type within the FUNCTION body can be
                  specified by including a type class keyword (STATIC, SHARED, or LOCAL) at the end of the
                  header; the default, if no keyword is included, is LOCAL.
                  Normally, PowerBASIC passes parameters to a function either by reference or by copy. Either
                  way, the address of a variable is passed and the procedure has to look at that address to get the
                  value of the parameter. If you don't need to modify the parameter (true in many cases), you can
                  speed up your functions by passing the parameter by value using the BYVAL keyword with your
                  parameter name.
                  You can also force a parameter to be passed by reference (rather than by value or by copy) using
                  the SEG keyword.
                  The type of the parameter is specified either by including a type-declaration character at the end of
                  the name or using an AS clause. For example:
                  FUNCTION Test(A AS INTEGER)
                  FUNCTION Test(A%)
                  FUNCTION Test(BYVAL A%)
                  ' A is an integer passed by reference
                  ' A is an integer passed by reference
                  ' A is an integer passed by value
                  Specifying CDECL forces PowerBASIC to push the parameters on the stack from Left to Right
                  (in the order of appearance, also known as C calling convention). This makes the FUNCTION
                  callable from C code in an external .OBJ module. An added benefit is that optional parameters
                  may be specified using brackets [ ] to indicate which parameters are optional:
                  DECLARE FUNCTION Kerplunk CDECL (x%, y% [, z%])
                  Note that the comma separating the y% parameter from the optional z% parameter is inside the
                  brackets. The following calling sequences are then valid:
                  a = Kerplunk (x%, y%)
                  a = Kerplunk (x%, y%, z%)
                  Optional parameters must be the last parameters designated in the list. The following is invalid:
                  DECLARE FUNCTION Kerplunk CDECL ([x%,] y% , z%)
                  Because FUNCTION being called does not know how many parameters are being passed at the
                  time it is called, you should pass the number of parameters as one of the required parameters in
                  the list.
                  Array parameters
                  You need to declare an array parameter using a special syntax:
                  array({MIN|MAX}, dimensions)
                  ? MIN specifies that the array has a minimum subscript other than zero. For example, if you
                  dimensioned an array like this:
                  Chapter 2, Reference directory
                  129DIM Years%(1970 TO 1999)
                  Years% has a minimum subscript other than zero (namely, 1970). Therefore, to declare
                  FUNCTION Test(Years%(MIN, 1), ...)
                  ? MAX specifies that the array's lower bound is zero. For example, if you dimensioned an
                  array like this:
                  DIM Students&(0 TO 30, 0 TO 6)
                  Students&' minimum subscript is zero. Therefore, to declare Students&:
                  FUNCTION Test(Students&(MAX, 2), ...)
                  Using MIN is always safe, but MAX lets the compiler optimize access to zero-based arrays.
                  Variables within functions
                  The default type for variables within the function can be set by including a type keyword
                  (STATIC, SHARED, or LOCAL) at the end of the function header. In the absence of an explicit
                  type declaration, variables default to LOCAL. The type of individual variables can be set by using
                  the LOCAL, STATIC, and SHARED statements within the function.
                  Function blocks are constructed very much like procedures (see SUB/END SUB). Functions
                  differ in that they can be used in expressions, and they return a value simply by assigning it to the
                  function name. See Chapter 8 of the User's Guide for a detailed comparison of FUNCTIONs,
                  DEF FNs, and SUBs.
                  Functions cannot return flex strings, fixed-length strings, structures, or whole arrays.
                  Private and public functions
                  The PUBLIC and PRIVATE keywords determine if a function will be accessible (PUBLIC) or
                  inaccessible (PRIVATE) from another module (main program, unit, or object file). Functions are
                  PRIVATE by default.
                  See also
                  DEF FN, LOCAL, SHARED, STATIC, SUB
                  FUNCTION HalfOf(X)
                  HalfOf = X/2
                  END FUNCTION
                  FOR I = 1 TO 10
                  PRINT I,HalfOf(I)
                  NEXT I
                  Am I blind? I absolutely see nowhere an information about BDECL.


                  • #10

                    Andy, I was breech born.
                    I likely read about in the Powerbasic Console Manual.

                    From page 316 in the Powerbasic Console version 6 manual, here it gets started.
                    And in the same manual page 2029, you will find references but as I said, I possibly made assumptions because
                    i mostly read about call conventions in the 32 bit compiler books.
                    I guess I read into what was left out and it seems they later added words or options later for clarity sake.
                    Writing manual inhouse and with some help is still a laborious job and not always the best and manuals get better usually, but i thought overall it was good.
                    link to Powerbasic Console Version 6 manual.


                    p purvis


                    • #11
                      Paul, thanks a lot. :-)


                      • #12
                        The online help with PB3.50 explains the usage of CDECL/BDECL with the CALL statement (where it's normally used):

                        Click image for larger version

Name:	pbscreen.png
Views:	45
Size:	70.3 KB
ID:	776474


                        • #13
                          Wow ? Are there still people using PB DOS 3.2 in 2018 ? Very surprising.
                          So here we are, this is the end.
                          But all that dies, is born again.
                          - From The Ashes (In This Moment)


                          • #14
                            Not me. I am using Powerbasic Dos 3.5.
                            p purvis


                            • #15
                              Ok my mistake, 3.5 it is. I still have the disks laying around but I wouldn't know what purpose it would still serve to write software in it these days. I don't even have a system that boots up in DOS.
                              So here we are, this is the end.
                              But all that dies, is born again.
                              - From The Ashes (In This Moment)