home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft_Programmers_Library.7z / MPL / common / mixlang.txt < prev    next >
Encoding:
Text File  |  2013-11-08  |  213.0 KB  |  5,929 lines

  1.  Microsoft Mixed-Language Programming Guide
  2.  
  3.  
  4.  
  5.  ───────────────────────────────────────────────────────────────────────────
  6.  
  7.  
  8.  
  9.  MICROSOFT(R) MIXED-LANGUAGE PROGRAMMING GUIDE
  10.  
  11.  for the MS-DOS Operating System
  12.  
  13.  ───────────────────────────────────────────────────────────────────────────
  14.  
  15.  
  16.  
  17.  Information in this document is subject to change without notice and does
  18.  not represent a commitment on the part of Microsoft Corporation. The
  19.  software described in this document is furnished under a license agreement
  20.  or nondisclosure agreement. The software may be used or copied only in
  21.  accordance with the terms of the agreement. The purchaser may make one copy
  22.  of the software for backup purposes. No part of this manual may be
  23.  reproduced or transmitted in any form or by any means, electronic or
  24.  mechanical, including photocopying and recording, for any purpose other
  25.  than the purchaser's personal use without the written permission of
  26.  Microsoft Corporation.
  27.  
  28.  
  29.  
  30.  (C) Copyright Microsoft Corporation, 1987. All rights reserved.
  31.  Simultaneously published in the U.S. and Canada.
  32.  
  33.  
  34.  
  35.  Microsoft(R), MS-DOS(R), and CodeView(R) are registered trademarks
  36.  and QuickC(TM) is a trademark of Microsoft Corporation.
  37.  
  38.  
  39.  
  40.  TABLE OF CONTENTS
  41.  
  42.  ───────────────────────────────────────────────────────────────────────────
  43.  
  44.  Introduction
  45.  
  46.  
  47.  PART 1--MIXED-LANGUAGE INTERFACES
  48.  
  49.  
  50.  1    ELEMENTS OF MIXED-LANGUAGE PROGRAMMING
  51.  
  52.  1.1  Making Mixed-Language Calls
  53.  
  54.  1.2  Naming Convention Requirement
  55.  
  56.  1.3  Calling Convention Requirement
  57.  
  58.  1.4  Parameter-Passing Requirement
  59.  
  60.  1.5  Compiling and Linking
  61.  
  62.        1.5.1  Compiling with Proper Memory Models
  63.  
  64.        1.5.2  Linking with Language Libraries
  65.  
  66.  
  67.  2    BASIC CALLS TO HIGH-LEVEL LANGUAGES
  68.  
  69.  2.1  The BASIC Interface to Other Languages
  70.  
  71.        2.1.1  The DECLARE Statement
  72.  
  73.        2.1.2  Using ALIAS
  74.  
  75.        2.1.3  Using the Parameter List
  76.  
  77.  2.2  Alternative BASIC Interfaces
  78.  
  79.  2.3  BASIC Calls to C
  80.  
  81.        2.3.1  Calling C from BASIC--No Return Value
  82.  
  83.        2.3.2  Calling C from BASIC--Function Call
  84.  
  85.  2.4  BASIC Calls to FORTRAN
  86.  
  87.        2.4.1  Calling FORTRAN from BASIC--Subroutine Call
  88.  
  89.        2.4.2  Calling FORTRAN from BASIC--Function Call
  90.  
  91.  2.5  BASIC Calls to Pascal
  92.  
  93.        2.5.1  Calling Pascal from BASIC--Procedure Call
  94.  
  95.        2.5.2  Calling Pascal from BASIC--Function Call
  96.  
  97.  2.6  Restrictions on Calls from BASIC
  98.  
  99.        2.6.1  Memory Allocation
  100.  
  101.        2.6.2  Incompatible Functions
  102.  
  103.  
  104.  3    C CALLS TO HIGH-LEVEL LANGUAGES
  105.  
  106.  3.1  The C Interface to Other Languages
  107.  
  108.  3.2  Alternative C Interfaces
  109.  
  110.  3.3  C Calls to BASIC
  111.  
  112.  3.4  C Calls to FORTRAN
  113.  
  114.        3.4.1  Calling FORTRAN from C--Subroutine Call
  115.  
  116.        3.4.2  Calling FORTRAN from C--Function Call
  117.  
  118.  3.5  C Calls to Pascal
  119.  
  120.        3.5.1  Calling Pascal from C--Procedure Call
  121.  
  122.        3.5.2  Calling Pascal from C--Function Call
  123.  
  124.  
  125.  4    FORTRAN CALLS TO HIGH-LEVEL LANGUAGES
  126.  
  127.  4.1  The FORTRAN Interface to Other Languages
  128.  
  129.        4.1.1  The INTERFACE Statement
  130.  
  131.        4.1.2  Using ALIAS
  132.  
  133.  4.2  Alternative FORTRAN Interface to C
  134.  
  135.  4.3  FORTRAN Calls to BASIC
  136.  
  137.  4.4  FORTRAN Calls to C
  138.  
  139.        4.4.1  Calling C from FORTRAN--No Return Value
  140.  
  141.        4.4.2  Calling C from FORTRAN--Function Call
  142.  
  143.  4.5  FORTRAN Calls to Pascal
  144.  
  145.        4.5.1  Calling Pascal from FORTRAN--Procedure Call
  146.  
  147.        4.5.2  Calling Pascal from FORTRAN--Function Call
  148.  
  149.  
  150.  5    PASCAL CALLS TO HIGH-LEVEL LANGUAGES
  151.  
  152.  5.1  The Pascal Interface to Other Languages
  153.  
  154.  5.2  Alternative Pascal Interface to C
  155.  
  156.  5.3  Pascal Calls to BASIC
  157.  
  158.  5.4  Pascal Calls to C
  159.  
  160.        5.4.1  Calling C from Pascal--No Return Value
  161.  
  162.        5.4.2  Calling C from Pascal--Function Call
  163.  
  164.  5.5  Pascal Calls to FORTRAN
  165.  
  166.        5.5.1  Calling FORTRAN from Pascal--Subroutine Call
  167.  
  168.        5.5.2  Calling FORTRAN from Pascal--Function Call
  169.  
  170.  
  171.  6    ASSEMBLY-TO-HIGH-LEVEL INTERFACE
  172.  
  173.  6.1  Writing the Assembly Procedure
  174.  
  175.        6.1.1  Setting Up the Procedure
  176.  
  177.        6.1.2  Entering the Procedure
  178.  
  179.        6.1.3  Allocating Local Data (Optional)
  180.  
  181.        6.1.4  Preserving Register Values
  182.  
  183.        6.1.5  Accessing Parameters
  184.  
  185.        6.1.6  Returning a Value (Optional)
  186.  
  187.        6.1.7  Exiting the Procedure
  188.  
  189.  6.2  Calls from BASIC
  190.  
  191.  6.3  Calls from C
  192.  
  193.  6.4  Calls from FORTRAN
  194.  
  195.  6.5  Calls from Pascal
  196.  
  197.  6.6  Calling High-Level Languages from Assembly
  198.  
  199.  6.7  The Microsoft Segment Model
  200.  
  201.  
  202.  PART 2--DATA HANDLING REFERENCE
  203.  
  204.  
  205.  7    PASSING BY REFERENCE OR VALUE
  206.  
  207.  7.1  BASIC Arguments
  208.  
  209.  7.2  C Arguments
  210.  
  211.  7.3  FORTRAN Arguments
  212.  
  213.  7.4  Pascal Arguments
  214.  
  215.  
  216.  8    NUMERICAL, LOGICAL, AND STRING DATA
  217.  
  218.  8.1  Integer and Real Numbers
  219.  
  220.  8.2  FORTRAN COMPLEX Types
  221.  
  222.  8.3  FORTRAN LOGICAL Type
  223.  
  224.  8.4  Strings
  225.  
  226.        8.4.1  String Formats
  227.  
  228.        8.4.2  Passing BASIC Strings
  229.  
  230.        8.4.3  Passing C Strings
  231.  
  232.        8.4.4  Passing FORTRAN Strings
  233.  
  234.        8.4.5  Passing Pascal Strings
  235.  
  236.  
  237.  9    SPECIAL DATA TYPES
  238.  
  239.  9.1  Arrays
  240.  
  241.        9.1.1  Passing Arrays from BASIC
  242.  
  243.        9.1.2  Array Declaration and Indexing
  244.  
  245.  9.2  Structures, Records, and User-defined Types
  246.  
  247.  9.3  External Data
  248.  
  249.  9.4  Pointers and Address Variables
  250.  
  251.  9.5  Common Blocks
  252.  
  253.        9.5.1  Passing the Address of the Common Block
  254.  
  255.        9.5.2  Accessing Common Blocks Directly
  256.  
  257.  9.6  Using a Varying Number of Parameters
  258.  
  259.  
  260.  INDEX
  261.  
  262.  
  263.  FIGURES
  264.  
  265.  Figure 1.1  Mixed-Language Call
  266.  
  267.  Figure 1.2  Naming Convention
  268.  
  269.  Figure 3.1  C Call to BASIC
  270.  
  271.  Figure 4.1  FORTRAN Call to BASIC
  272.  
  273.  Figure 5.1  Pascal Call to BASIC
  274.  
  275.  Figure 6.1  The Stack Frame
  276.  
  277.  Figure 6.2  FORTRAN/Pascal Long Return Values
  278.  
  279.  Figure 6.3  BASIC Stack Frame
  280.  
  281.  Figure 6.4  C Stack Frame
  282.  
  283.  Figure 6.5  FORTRAN Stack Frame
  284.  
  285.  Figure 6.6  Pascal Stack Frame
  286.  
  287.  Figure 6.7  Assembly Call to C
  288.  
  289.  Figure 8.1  FORTRAN COMPLEX Data Format
  290.  
  291.  Figure 8.2  BASIC String Descriptor Format
  292.  
  293.  Figure 8.3  C String Format
  294.  
  295.  Figure 8.4  FORTRAN String Format
  296.  
  297.  Figure 8.5  Pascal String Format
  298.  
  299.  Figure 9.1  Structure and Record Storage
  300.  
  301.  
  302.  TABLES
  303.  
  304.  Table 1.1  Language Equivalents for Routine Calls
  305.  
  306.  Table 1.2  Parameter-Passing Defaults
  307.  
  308.  Table 6.1  Default Segments and Types for Standard Memory Models
  309.  
  310.  Table 8.1  Equivalent Numeric Data Types
  311.  
  312.  Table 9.1  Equivalent Array Declarations
  313.  
  314.  
  315.  
  316.  INTRODUCTION
  317.  
  318.  ───────────────────────────────────────────────────────────────────────────
  319.  
  320.  Mixed-language programming is the process of creating programs from two
  321.  or more source languages. This capability allows you to combine the unique
  322.  strengths of Microsoft(R) BASIC, C, FORTRAN, Pascal, and Macro Assembler.
  323.  Any one of these languages (in their recent versions) can call any of the
  324.  others. Virtually all of the routines from all extensive language libraries
  325.  are available to a mixed-language program.
  326.  
  327.  For example, mixed-language programming helps you effectively use assembly
  328.  language. You can develop the majority of your program quickly with
  329.  Microsoft C or QuickBASIC, then call assembly for those few routines that
  330.  are executed many times and must run with utmost speed.
  331.  
  332.  Mixed-language programming also facilitates the transition from one lan-
  333.  guage to another. You may have a large FORTRAN program which you are con-
  334.  verting to C. You can replace your FORTRAN subroutines, one by one, with
  335.  corresponding C functions. C-generated code can come on-line as soon as
  336.  each function is written.
  337.  
  338.  Finally, mixed-language programming is particularly valuable if you are
  339.  marketing your own libraries. With the techniques presented here, you can
  340.  produce libraries for any of the languages mentioned above, often with
  341.  little change.
  342.  
  343.  
  344.  How to Use this Manual
  345.  
  346.  This manual focuses on the concepts, syntax, and programming methods neces-
  347.  sary to write mixed-language programs. The manual assumes that you have a
  348.  basic understanding of the languages you wish to combine and that you
  349.  already know how to write, compile, and link multiple-module programs with
  350.  these languages. The manual does not attempt to teach the basics of pro-
  351.  gramming in any particular language.
  352.  
  353.  Mixed-language programming is not particularly difficult, but it does
  354.  require that you understand certain basic issues. This manual first
  355.  presents these issues in some detail. Once you understand the basics, you
  356.  can proceed to the sections that are relevant to the languages you are
  357.  using.  The manual is divided into two parts; each part has a different
  358.  orientation and purpose:
  359.  
  360.    ■  Part 1. Mixed-Language Interfaces.
  361.  
  362.       Part 1 shows how to establish an interface between any two languages
  363.       (of those listed above). It does not assume you have any background
  364.       in mixed-language programming, and extensively uses examples with sim-
  365.       ple parameter lists.
  366.  
  367.    ■  Part 2%. Data Handling Reference.
  368.  
  369.       Part 2 shows how to pass different kinds of data. This part of the
  370.       manual assumes you already know the basics of mixed-language program-
  371.       ming. It focuses on the particular programming considerations for
  372.       passing strings, arrays, common blocks, etc.
  373.  
  374.  Depending on your current level of knowledge, you may not need to start
  375.  reading this manual at the beginning. The manual is structured so that you
  376.  can easily turn to the section that would be most helpful:
  377.  
  378.    1.  For an introduction to mixed-language concepts, read Chapter 1,
  379.        "Elements of Mixed-Language Programming."
  380.  
  381.    2.  Depending on the high-level language of your main program, read
  382.        either Chapter 2, 3, 4, or 5. The opening section of each of these
  383.        chapters describes mixed-language syntax in detail. For quick
  384.        reference, turn directly to the section in Chapters 2-5 most relevant
  385.        to your combination of languages.
  386.  
  387.    3.  To find out about calls to assembly language, read Chapter 6,
  388.        "Assembly-to-High-Level Interface."
  389.  
  390.    4.  After you have learned how to pass simple arguments (such as
  391.        integers) between languages, use Part 2 as a reference for passing
  392.        more complex kinds of data, such as strings and arrays.
  393.  
  394.  
  395.  Definitions
  396.  
  397.  The notational conventions used in this manual are consistent with the con-
  398.  ventions described in the user's guide for each Microsoft language. How-
  399.  ever, the following terms are used in specialized ways:
  400. ╓┌──────────────────┌────────────────────────────────────────────────────────╖
  401.    Term             Definition
  402.  ───────────────────────────────────────────────────────────────────────────
  403.    Routine          Any function, subprogram, subroutine, or procedure that
  404.                     can be called from another language.
  405.  
  406.                     The concept is similar to that of a procedure in
  407.                     assembly language; however, the term "routine" is used
  408.                     in most contexts to avoid confusion with the Pascal
  409.                     keyword procedure.
  410.  
  411.    Parameter        A piece of data passed directly between two routines.
  412.                     (External data are shared by all routines, but cannot be
  413.                     said to be passed.)
  414.  
  415.                     Although elsewhere the term "argument" is sometimes used
  416.                     interchangeably with "parameter," in this manual,
  417.                     "argument" is used to refer to the particular values or
  418.                     expressions given for parameters.
  419.  
  420.    Interface        A method for providing effective communication between
  421.                     different formats. With high-level languages, an
  422.    Term             Definition
  423.                    different formats. With high-level languages, an
  424.                     interface is often established by some kind of formal
  425.                     declaration.
  426.  
  427.    Formal           A formal parameter is a dummy parameter declared in an
  428.    parameter        interface statement or declaration. C uses parameter
  429.                     type declarations rather than formal parameters.
  430.  
  431.  
  432.  
  433.  PART 1 --MIXED-LANGUAGE INTERFACES
  434.  
  435.  ───────────────────────────────────────────────────────────────────────────
  436.  
  437.  CHAPTERS
  438.  
  439.      1    Elements of Mixed-Language Programming
  440.      2    BASIC Calls to High-Level Languages
  441.      3    C Calls to High-Level Languages
  442.      4    FORTRAN Calls to High-Level Languages
  443.      5    Pascal Calls to High-Level Languages
  444.      6    Assembly-to-High-Level Interface
  445.  
  446.  
  447.  
  448.  Part 1 of the Mixed-Language Programming Guide explains how to establish
  449.  an interface between modules written in Microsoft BASIC, C, FORTRAN,
  450.  Pascal, and Macro Assembler. This part of the manual extensively uses
  451.  examples; however, these examples feature only integer parameters, which
  452.  are relatively easy to pass. Sharing other kinds of data (such as strings
  453.  and arrays) presents special problems, and is dealt with in Part 2.
  454.  
  455.  
  456.  
  457.  CHAPTER 1  ELEMENTS OF MIXED-LANGUAGE PROGRAMMING
  458.  
  459.  ───────────────────────────────────────────────────────────────────────────
  460.  
  461.  1.1  Making Mixed-Language Calls
  462.  
  463.  1.2  Naming Convention Requirement
  464.  
  465.  1.3  Calling Convention Requirement
  466.  
  467.  1.4  Parameter-Passing Requirement
  468.  
  469.  1.5  Compiling and Linking
  470.  
  471.        1.5.1  Compiling with Proper Memory Models
  472.  
  473.        1.5.2  Linking with Language Libraries
  474.  
  475.  
  476.  
  477.  Microsoft languages have special keywords that facilitate mixed-language
  478.  programming (described in Chapters 2-5). However, in order to use these
  479.  keywords, you first need to understand the basic issues involved.
  480.  
  481.  This chapter describes the elements of mixed-language programming: how
  482.  languages differ and how to resolve these differences. If you understand
  483.  the principles described in the next few paragraphs, then you may want to
  484.  turn directly to other chapters in this manual. Nevertheless, you still may
  485.  find it helpful to refer to this chapter occasionally.
  486.  
  487.  Section 1.1 presents the basic context of a mixed-language call, when and
  488.  how you make such a call.
  489.  
  490.  Sections 1.2-1.4 present the three fundamental mixed-language programming
  491.  requirements:
  492.  
  493.    ■  Naming convention requirement
  494.  
  495.    ■  Calling convention requirement
  496.  
  497.    ■  Parameter-passing requirement
  498.  
  499.  Section 1.5 presents the compile-time and link-time issues, including use
  500.  of memory models.
  501.  
  502.  
  503.  1.1  Making Mixed-Language Calls
  504.  
  505.  Mixed-language programming always involves a call; specifically, it in-
  506.  volves a function, procedure, or subroutine call. For example, a BASIC main
  507.  module may need to execute a specific task that you would like to program
  508.  separately. Instead of calling a BASIC subprogram, however, you decide to
  509.  call a C function.
  510.  
  511.  Mixed-language calls necessarily involve multiple modules (at least with
  512.  Microsoft languages). Instead of compiling all of your source modules with
  513.  the same compiler, you use different compilers. In the example mentioned
  514.  above, you would compile the main-module source file with the BASIC
  515.  compiler, another source file (written in C) with the C compiler, and then
  516.  link together the two object files.
  517.  
  518.  Figure 1.1 illustrates how the syntax of a mixed-language call works,
  519.  using the example mentioned above.
  520.  
  521.  
  522.                       BASIC code                         C code
  523.  
  524.             ┌────────────────────────────┐    ┌────────────────────────────┐
  525.             │                            │    │                            │
  526.             │                            │    │                            │
  527.             │                            │    │                            │
  528.  affects  ┌─┤ DECLARE SUB Prn CDECL()    │    │                            │
  529.  how call │ │ .                          │    │                            │
  530.  is made  │ │ .                          │    │                            │
  531.           │ │ .                       ┌──┼──── void prn() {               │
  532.           │ │                         │  │    │ .                          │
  533.           └│ CALL Prn ─────────┐ ───┘  │    │ .                          │
  534.             │ .                  │       │    │ .                          │
  535.             │ .                  └───────┼────┼─}                          │
  536.             │ .                          │    │                            │
  537.             │ END                        │    │                            │
  538.             │                            │    │                            │
  539.             │                            │    │                            │
  540.             │                            │    │                            │
  541.             │                            │    │                            │
  542.             └────────────────────────────┘    └────────────────────────────┘
  543.  
  544.  Figure 1.1  Mixed-Language Call
  545.  
  546.  
  547.  In the illustration above, the BASIC call to C is CALL Prn, similar to a
  548.  call to a BASIC subprogram. However, there are two differences between this
  549.  mixed-language call and a call between two BASIC modules: 1) the subprogram
  550.  Prn is actually implemented in C, using standard C syntax; and 2) the
  551.  implementation of the call in BASIC is affected by DECLARE statement, which
  552.  uses the CDECL keyword in order to create compatibility with C. The DECLARE
  553.  statement (which is discussed in detail in Chapter 2) is an example of a
  554.  mixed-language "interface" statement. Each language provides its own form
  555.  of interface.
  556.  
  557.  Despite syntactic differences, functions, procedures, and FORTRAN
  558.  subroutines are all similar. The principal difference is that some kinds of
  559.  routines return values, and others do not. You can interchange routines
  560.  that have a return value, and you can interchange routines that have no
  561.  return value.  (Note that in this manual, "routine" refers to any function,
  562.  procedure or subroutine that can be called from another module.)
  563.  
  564.  Table 1.1 shows the correspondence between routine calls in different
  565.  languages.
  566.  
  567.  
  568.             Table 1.1
  569.             Language Equivalents for Routine Calls
  570. ╓┌─────────────────────────────────┌───────────────┌─────────────────────────╖
  571.             Language               Return value    No return value
  572.             ────────────────────────────────────────────────────────────
  573.             BASIC                  FUNCTION        subprogram
  574.                                    procedure
  575.             C                      function        (void) function
  576.             FORTRAN                function        subroutine
  577.             Pascal                 function        procedure
  578.             Macro Assembler        procedure       procedure
  579.  
  580.  For example, a BASIC module can make a subprogram call to a FORTRAN
  581.  subroutine. BASIC should make a FUNCTION call in order to call a FORTRAN
  582.  function; otherwise, the call can be made, but the return value will be
  583.  lost.
  584.  
  585.  ───────────────────────────────────────────────────────────────────────────
  586.  Note
  587.    BASIC DEF FN functions and GOSUB subroutines cannot be called from
  588.    another language.
  589.  ───────────────────────────────────────────────────────────────────────────
  590.  
  591.  
  592.  1.2  Naming Convention Requirement
  593.  
  594.  The term "naming convention" refers to the way that a compiler alters the
  595.  name of the routine before placing it into an object file.
  596.  
  597.  It is important that you adopt a compatible naming convention when you
  598.  issue a mixed-language call. If the name of the called routine is stored
  599.  differently in each object file, then the linker will not be able to find a
  600.  match. It will instead report an unresolved external.
  601.  
  602.  Microsoft compilers place machine code into object files; but they also
  603.  place there the names of all routines and variables which need to be
  604.  accessed publicly. That way, the linker can compare the name of a routine
  605.  called in one module to the name of a routine defined in another module,
  606.  and recognize a match. Names are stored in ASCII (American Standard Code
  607.  for Information Interchange) format. You can see precisely how they are
  608.  stored if you use the DEBUG utility to dump an object file's bytes.
  609.  
  610.  BASIC, FORTRAN, and Pascal use roughly the same naming convention. They
  611.  translate each letter to uppercase. BASIC type declaration characters (%,
  612.  &, !, #, $) are dropped.
  613.  
  614.  However, each language recognizes a different number of characters.
  615.  FORTRAN recognizes the first 6 characters of any name, Pascal the first 8,
  616.  and BASIC the first 40. If a name is longer than the language will
  617.  recognize, additional characters are simply not placed in the object file.
  618.  
  619.  C uses a quite different convention; the C compiler does not translate any
  620.  letters to uppercase, but inserts a leading underscore (_) in front of the
  621.  name of each routine. C recognizes the first 31 characters of a name.
  622.  
  623.  Differences in naming conventions are taken care of for you automatically
  624.  by mixed-language keywords, as long as you follow two rules:
  625.  
  626.    1.  If you are using any FORTRAN routines, all names should be 6
  627.        characters or less in length.
  628.  
  629.    2.  Do not use the /NOIGNORE linker option (which causes the linker to
  630.        distinguish between Prn and prn). With C modules, this means that you
  631.        will have to be careful not to rely upon differences between
  632.        uppercase and lowercase letters.
  633.  
  634.  The CL driver and Microsoft QuickC(TM) automatically use the
  635.  /NOIGNORE option when linking. To solve the problems created by this
  636.  behavior, either link separately with the LINK utility, or use all
  637.  lowercase letters in your C modules.
  638.  
  639.  Figure 1.2 illustrates a complete mixed-language development example,
  640.  showing how naming conventions enter into the process.
  641.  
  642.  
  643.      ┌── DECLARE affects
  644.      │   how BASIC
  645.      │   makes the call.
  646.      │
  647.      │    MAINPROG.BAS (source file)            PRN.C (source file)
  648.      │ ┌──────────────────────────────┐   ┌──────────────────────────────┐
  649.      ├─┤ DECLARE SUB Prn CDECL()  ┌------- prn() {                      │
  650.      │ │ .                        |   │   │ .                            │
  651.      │ │ .                        |   │   │ .                            │
  652.      └─ CALL Prn ________________|   │   │ .                            │
  653.        │ .                            │   │                              │
  654.        │ .                            │   │ .                            │
  655.        │ .                            │   │ .                            │
  656.        │ END                          │   │ }                            │
  657.        └──────────────╥───────────────┘   └──────────────╥───────────────┘
  658.                       ║                                  ║
  659.                     BASIC                                C
  660.                    Compiler                           Compiler
  661.        ┌─────────────────────────────┐   ┌─────────────────────────────┐
  662.        │                          ┌------- _prn:                        │
  663.        │                          |   │   │                              │
  664.        │                          |   │   │                              │
  665.        │ call _prn _______________|   │   │                              │
  666.        │                              │   │                              │
  667.        │                              │   │                              │
  668.        │                              │   │                              │
  669.        │                              │   │                              │
  670.        └──────────────╥───────────────┘   └───────────────╥──────────────┘
  671.                       ║                                   ║
  672.                   MAINPROG.OBJ                         PRN.OBJ ┌───────────┐
  673.                     (object                            (object │           │
  674.                      file)                              file)  │ LIBRARIES │
  675.                       ║                                   ║    │           │
  676.                       ╚═════════════════╦═════════════════╝    └──────╥────┘
  677.                                        LINK                           ║
  678.                                    (ignores case ════════════════════╝
  679.                                    unless /NOI)
  680.                                         ║
  681.                          ┌─────────────────────────────┐
  682.                          │                              │
  683.          call _prn       │ xxxx:  call yyyy             │ ▒
  684.                          │                │             │ ▒
  685.                          │ ┌──────────────┘             │ ▒ Machine-level
  686.                          │ │                            │ ▒  addresses
  687.                          │                             │ ▒
  688.          _prn:           │ yyyy:                        │ ▒
  689.                          │                              │
  690.                          └──────────────────────────────┘
  691.                                    MAINPROG.EXE
  692.  
  693.  Figure 1.2  Naming Convention
  694.  
  695.  
  696.  In the example above, note that the BASIC compiler inserts a leading
  697.  underscore in front of Prn as it places the name into the object file,
  698.  because the CDECL keyword directs the BASIC compiler to use the C naming
  699.  convention. BASIC will also convert all letters to lowercase when this
  700.  keyword is used. (Strictly speaking, converting letters to lowercase is not
  701.  part of the C naming convention; however, it is consistent with the
  702.  programming style of most C programs.)
  703.  
  704.  
  705.  1.3  Calling Convention Requirement
  706.  
  707.  The term "calling convention" refers to the way that a language implements
  708.  a call. The choice of calling convention affects the actual machine
  709.  instructions that a compiler generates in order to execute (and return
  710.  from) a function, procedure, or subroutine call.
  711.  
  712.  The calling convention is a low-level protocol. It is crucial that the two
  713.  routines concerned (the routine issuing a call and the routine being
  714.  called) recognize the same protocol. Otherwise, the processor may receive
  715.  inconsistent instructions, thus causing the system to crash.
  716.  
  717.  The use of a calling convention affects programming in two ways:
  718.  
  719.    1.  The calling routine uses a calling convention to determine in what
  720.        order to pass arguments (parameters) to another routine. This
  721.        convention can usually be specified in a mixed-language interface.
  722.  
  723.    2.  The called routine uses a calling convention to determine in what
  724.        order to receive the parameters that were passed to it. In most
  725.        languages, this convention can be specified in the routine's heading.
  726.        BASIC, however, always uses its own convention to receive parameters.
  727.  
  728.  In other words, each call to a routine uses a certain calling convention,
  729.  and each routine heading specifies or assumes some calling convention. The
  730.  two conventions must be compatible. With each language except BASIC, it is
  731.  possible to change either calling convention. Usually, however, it is
  732.  simplest to adopt the convention of the called routine. For example, a C
  733.  function would use its own convention to call another C function, and use
  734.  the Pascal convention to call Pascal.
  735.  
  736.  BASIC, FORTRAN, and Pascal use the same standard calling convention. C,
  737.  however, uses a quite different convention.
  738.  
  739.  ───────────────────────────────────────────────────────────────────────────
  740.  Note
  741.    The next few paragraphs discuss some of the details of calling
  742.    conventions. It is not crucial for a high-level language programmer to
  743.    understand these details; the programmer only needs to know that the dif-
  744.    ferent conventions are not compatible with each other.
  745.  ───────────────────────────────────────────────────────────────────────────
  746.  
  747.  The Microsoft BASIC, FORTRAN and Pascal calling conventions each push
  748.  parameters onto the stack in the order in which they appear in the source
  749.  code. For example, the BASIC statement CALL Calc(A,B) pushes the argument A
  750.  onto the stack before it pushes B. These conventions also specify that the
  751.  stack is restored by the called routine, just before returning control to
  752.  the caller. (The stack is restored by removing parameters.)
  753.  
  754.  The C calling convention pushes parameters onto the stack in the
  755.  reverse order in which they appear in the source code. For example, the C
  756.  function call calc(a,b); pushes b onto the stack before it pushes a. In
  757.  contrast with the other high-level languages, the C calling convention
  758.  specifies that a calling routine always restores the stack immediately
  759.  after the called routine returns control.
  760.  
  761.  The BASIC, FORTRAN, and Pascal conventions produce slightly less object
  762.  code. However, the C convention makes calling with a variable number of
  763.  parameters possible. (Because the first parameter is always the last one
  764.  pushed, it is always on the top of the stack; therefore it has the same
  765.  address relative to the frame pointer, regardless of how many parameters
  766.  were actually passed.)
  767.  
  768.  
  769.  1.4  Parameter-Passing Requirement
  770.  
  771.  Section 1.3 discussed the overall protocol (the calling convention) that
  772.  two routines use to communicate with each other; this section concerns how
  773.  an individual piece of data (a parameter) is actually sent.
  774.  
  775.  If your routines do not agree on how a parameter is to be sent, then a
  776.  called routine will receive bad data. It is also possible that the
  777.  program could cause the system to crash.
  778.  
  779.  Microsoft compilers support three methods for passing a parameter:
  780. ╓┌───────────────────┌───────────────────────────────────────────────────────╖
  781.    Method            Description
  782.    ─────────────────────────────────────────────────────────────────────────
  783.    By near reference Passes a variable's near (offset) address.
  784.  
  785.                      This method gives the called routine direct access to
  786.                      the variable itself. Any change the routine makes to
  787.                      the parameter will be reflected in the calling routine.
  788.  
  789.    By far reference  Passes a variable's far (segmented) address.
  790.  
  791.                      This method is similar to passing by near reference,
  792.                      except that a longer address is passed. This method is
  793.                      slower than passing by near reference but is necessary
  794.                      when you pass data that is outside of the default data
  795.                      segment. (This is not an issue in BASIC or Pascal,
  796.                      unless you have specifically requested far memory.)
  797.  
  798.    By value          Passes only the variable's value, not address.
  799.  
  800.    Method            Description
  801. 
  802.                      With this method, the called routine knows the value of
  803.                      the parameter, but has no access to the original
  804.                      variable. Changes to a value parameter have no affect
  805.                      on the value of the parameter in the calling routine,
  806.                      once the routine terminates.
  807.  
  808.  The fact that there are different parameter-passing methods has two
  809.  implications for mixed-language programming.
  810.  
  811.  First, you need to make sure that the called routine and the calling
  812.  routine use the same method for passing each parameter (argument). In most
  813.  cases, you will need to check the parameter-passing defaults used by each
  814.  language, and possibly make adjustments. Each language has keywords or
  815.  language features that allow you to change parameter-passing methods.
  816.  
  817.  Second, you may want to use a particular parameter-passing method rather
  818.  than using the defaults of any language. (In fact, the examples in Chapters
  819.  2-5 specifically require one particular method or another, because of
  820.  program logic.)
  821.  
  822.  Table 1.2 summarizes the parameter-passing defaults for each language.
  823.  
  824.  
  825.         Table 1.2
  826.         Parameter-Passing Defaults
  827. ╓┌────────────────────────┌──────────────────┌──────────────────┌────────────╖
  828.         ────────────────────────────────────────────────────────────────────
  829.         Language          Near reference     Far reference      By value
  830.         ────────────────────────────────────────────────────────────────────
  831.         BASIC             all
  832.         C                 near arrays        far arrays         non-arrays
  833.         FORTRAN                              all                all1
  834.         Pascal            VAR, CONST         VARS, CONSTS       other params
  835.  
  836.  Each language has methods for overriding these defaults, which are listed
  837.  in Chapter 7.
  838.  
  839.  
  840.  1.5  Compiling and Linking
  841.  
  842.  After you have written your source files and resolved the issues raised in
  843.  Sections 1.2-1.4, you are ready to compile individual modules and then link
  844.  them together.
  845.  
  846.  
  847.  1.5.1  Compiling with Proper Memory Models
  848.  
  849.  With Microsoft BASIC, FORTRAN, and Pascal, no special options are required
  850.  to compile source files that are part of a mixed-language program.
  851.  
  852.  With Microsoft C, however, you need to be aware that not all memory models
  853.  will be compatible with other languages. BASIC, FORTRAN, and Pascal use
  854.  only far (segmented) code addresses. Therefore, you must always compile C
  855.  modules in medium, large, or huge model, because these models also use far
  856.  code addresses.  Compiling in small or compact model will cause the mixed-
  857.  language program to crash, as soon as a call is made to or from C. (This
  858.  problem can be averted if you apply the far keyword to a C function
  859.  definition, in order to specify that the function uses a far call and
  860.  return.)
  861.  
  862.  The paragraph above concerns the size of code addresses. Differences in
  863.  the size of data addresses can be resolved through compile options or in
  864.  the source code. Choice of memory model affects the default data pointer
  865.  size in C and FORTRAN, although this default can be overriden with near and
  866.  far. Choice of memory model, with C and FORTRAN, also affects whether data
  867.  objects are located in the default data segment; if a data object is not
  868.  located in the default data segment, it cannot be directly passed by near
  869.  reference.
  870.  
  871.  
  872.  1.5.2  Linking with Language Libraries
  873.  
  874.  In many cases, linking modules compiled with different languages can be
  875.  done easily. Any of the following measures will ensure that all of the
  876.  required libraries are linked in the correct order:
  877.  
  878.    ■  Put all language libraries in the same directory as the source files.
  879.  
  880.    ■  List directories containing all needed libraries in the LIB
  881.       environment variable.
  882.  
  883.    ■  Let the linker prompt you for libraries.
  884.  
  885.  In each of the above cases, the linker finds libraries in the order that it
  886.  requires them. If you enter the libraries on the command line, then they
  887.  must be entered in a particular order.
  888.  
  889.  However, if you are using Version 4.0 of FORTRAN to produce one
  890.  of your modules, then you will need to link with /NOD (no default
  891.  libraries), and specify all the libraries you need directly on the link
  892.  command-line. You can also specify these libraries with an automatic-
  893.  response file (or batch file), but you cannot use a default library search.
  894.  
  895.  If your program uses both FORTRAN and C, then specify the library for
  896.  the most recent of the two language products first. If you use C 4.0 with
  897.  FORTRAN 4.0 or later, specify the FORTRAN library first. If you use C 5.0
  898.  or later, specify the C library first. In addition, make sure that you
  899.  chose a C-compatible library when you installed FORTRAN.
  900.  
  901.  If you are listing BASIC libraries on the LINK command-line, the BASIC
  902.  libraries must precede all others.
  903.  
  904.  
  905.  ■  Example
  906.  
  907.  LINK /NOD mod1 mod2,,,GRAFX+LLIBCE+LLIBFORE
  908.  
  909.  The example above links two object modules with the C 5.1 and FORTRAN 4.0
  910.  large-model libraries. In addition, the example links in an extra
  911.  library, GRAFX.
  912.  
  913.  
  914.  
  915.  CHAPTER 2  BASIC CALLS TO HIGH-LEVEL LANGUAGES
  916.  
  917.  ───────────────────────────────────────────────────────────────────────────
  918.  
  919.  2.1  The BASIC Interface to Other Languages
  920.  
  921.        2.1.1  The DECLARE Statement
  922.  
  923.        2.1.2  Using ALIAS
  924.  
  925.        2.1.3  Using the Parameter List
  926.  
  927.  2.2  Alternative BASIC Interfaces
  928.  
  929.  2.3  BASIC Calls to C
  930.  
  931.        2.3.1  Calling C from BASIC--No Return Value
  932.  
  933.        2.3.2  Calling C from BASIC--Function Call
  934.  
  935.  2.4  BASIC Calls to FORTRAN
  936.  
  937.        2.4.1  Calling FORTRAN from BASIC--Subroutine Call
  938.  
  939.        2.4.2  Calling FORTRAN from BASIC--Function Call
  940.  
  941.  2.5  BASIC Calls to Pascal
  942.  
  943.        2.5.1  Calling Pascal from BASIC--Procedure Call
  944.  
  945.        2.5.2  Calling Pascal from BASIC--Function Call
  946.  
  947.  2.6  Restrictions on Calls from BASIC
  948.  
  949.        2.6.1  Memory Allocation
  950.  
  951.        2.6.2  Incompatible Functions
  952.  
  953.  
  954.  
  955.  Microsoft BASIC supports calls to routines written in Microsoft C,
  956.  FORTRAN, and Pascal. This chapter describes the necessary syntax for
  957.  calling these other languages, and then gives examples for each combination
  958.  of BASIC with another language. Only integers are used as parameters in
  959.  these examples.
  960.  
  961.  The chapter ends with a section that lists restrictions on the use of
  962.  functions from the C standard library. Consult this section if you are
  963.  using any memory allocation or system library functions.
  964.  
  965.  For information on how to pass specific kinds of data, consult Part 2,
  966.  "Data Handling Reference."
  967.  
  968.  
  969.  2.1  The BASIC Interface to Other Languages
  970.  
  971.  The BASIC DECLARE statement provides a flexible and convenient interface to
  972.  other languages. It is available with Microsoft QuickBASIC, Versions 4.0
  973.  and later. Versions that do not provide the DECLARE statement do not
  974.  provide libraries that are compatible with other languages, either. These
  975.  earlier versions have limited use in mixed-language programs, as they
  976.  cannot successfully call a C, FORTRAN, or Pascal routine that makes any use
  977.  of a library.
  978.  
  979.  The syntax of the DECLARE statement is summarized below.
  980.  
  981.  
  982.  2.1.1  The DECLARE Statement
  983.  
  984.  When you call a function, the DECLARE statement syntax is as follows:
  985.  
  986.  DECLARE FUNCTION name «CDECL»«ALIAS "aliasname"»«(parameter-list)»
  987.  
  988.  When you call a subprogram, the statement syntax is as follows:
  989.  
  990.  DECLARE SUB name «CDECL»«ALIAS "aliasname"»«(parameter-list)»
  991.  
  992.  The name field is the name of the function or subprogram procedure you wish
  993.  to call, as it appears in the BASIC source file. Here are the recommended
  994.  steps for using the DECLARE statement to call other languages:
  995.  
  996.    1.  For each distinct interlanguage routine you plan to call, put a
  997.        DECLARE statement in the BASIC source file before the routine is
  998.        called.
  999.  
  1000.        For example, your program may call the subprogram Maxparam five
  1001.        different times, each time with different arguments. However, you
  1002.        need to declare Maxparam just once. Ideally, DECLARE statements
  1003.        should be placed near the beginning of the source file.
  1004.  
  1005.    2.  If you are calling a routine from a C module, use CDECL in the
  1006.        DECLARE statement (unless the C routine is declared with the pascal
  1007.        or fortran keyword).
  1008.  
  1009.        CDECL directs BASIC to use the C naming and calling conventions
  1010.        during each subsequent call to name. No similar keywords are provided
  1011.        for Pascal or FORTRAN, because they each use the same calling
  1012.        convention as BASIC.
  1013.  
  1014.    3.  If you are calling a FORTRAN routine with a name longer than six
  1015.        characters, or a C or Pascal routine with a name longer than eight
  1016.        characters, use the ALIAS feature. The use of ALIAS is explained in
  1017.        the section below.
  1018.  
  1019.    4.  Use the parameter list to determine how each parameter is to be
  1020.        passed. The use of the parameter list is explained below, in the
  1021.        section immediately after the information on ALIAS.
  1022.  
  1023.    5.  Once the routine is properly declared, call it just as you would a
  1024.        BASIC subprogram or function.
  1025.  
  1026.  The other fields are explained in the following discussion.
  1027.  
  1028.  
  1029.  2.1.2  Using ALIAS
  1030.  
  1031.  As noted above, the use of ALIAS may be necessary because FORTRAN places
  1032.  only the first 6 characters of a name into an object file, whereas C and
  1033.  Pascal each place the first 8, but BASIC will place up to 40 characters of
  1034.  a name into an object file.
  1035.  
  1036.  ───────────────────────────────────────────────────────────────────────────
  1037.  Note
  1038.    You do not need the ALIAS feature to remove type declaration characters
  1039.    (%, &, !, #, $). BASIC automatically removes these characters when it
  1040.    generates object code. Thus, Fact% in BASIC matches Fact in Pascal.
  1041.  ───────────────────────────────────────────────────────────────────────────
  1042.  
  1043.  The ALIAS keyword directs BASIC to place aliasname into the object file,
  1044.  instead of name. The BASIC source file still contains calls to name.
  1045.  However, these calls are interpreted as if they were actually calls to
  1046.  aliasname.
  1047.  
  1048.  
  1049.  ■  Example
  1050.  
  1051.  DECLARE FUNCTION Quadratic% ALIAS "QUADRA" (a, b, c)
  1052.  
  1053.  In the example above, QUADRA, the aliasname, contains the first six
  1054.  characters of Quadratic%, the name. This causes BASIC to place QUADRA into
  1055.  the object code, thereby mimicking FORTRAN's behavior.
  1056.  
  1057.  
  1058.  2.1.3  Using the Parameter List
  1059.  
  1060.  The parameter list syntax is displayed below, followed by explanations of
  1061.  each field. Note that you can use BYVAL or SEG, but not both.
  1062.  
  1063.  
  1064.  ■  Syntax
  1065.  
  1066.  «BYVAL | SEG» variable «AS type»...,
  1067.  
  1068.  Use the BYVAL keyword to declare a value parameter. In each subsequent
  1069.  call, the corresponding argument will be passed by value (the default
  1070.  method for C and Pascal modules).
  1071.  
  1072.  ───────────────────────────────────────────────────────────────────────────
  1073.  Note
  1074.    BASIC provides two ways of "passing by value." The usual method of
  1075.    passing by value is to use an extra set of parentheses, as in:
  1076.  
  1077.      CALL Holm((A))
  1078.  
  1079.    This method actually creates a temporary value, whose address is passed.
  1080.    BYVAL provides a true method of passing by value, because the value
  1081.    itself is passed, not an address. Only by using BYVAL will a BASIC
  1082.    program be compatible with a non-BASIC routine that expects a value
  1083.    parameter.
  1084.  ───────────────────────────────────────────────────────────────────────────
  1085.  
  1086.  Use the SEG keyword to declare a far reference parameter. In each
  1087.  subsequent call, the far (segmented) address of the corresponding argument
  1088.  will be passed (the default method for FORTRAN modules).
  1089.  
  1090.  You can choose any legal name for variable; but only the type associated
  1091.  with the name has any significance to BASIC. As with other variables, the
  1092.  type can be indicated with a type declaration character (%, &, !, #, $) or
  1093.  by implicit declaration.
  1094.  
  1095.  You can use the AS type clause to override the type declaration of
  1096.  variable. The type field can be INTEGER, LONG, SINGLE, DOUBLE, STRING, a
  1097.  user-defined type, or ANY, which directs BASIC to permit any type of data
  1098.  to be passed as the argument.
  1099.  
  1100.  
  1101.  ■  Examples
  1102.  
  1103.  DECLARE FUNCTION Calc2! CDECL (BYVAL a%, BYVAL b%, BYVAL c!)
  1104.  
  1105.  In the example above, Calc2 is declared as a C routine that takes three
  1106.  arguments: the first two are integers passed by value, and the last is a
  1107.  single-precision real number passed by value.
  1108.  
  1109.  DECLARE SUB Maxout (SEG var1 AS INTEGER, BYVAL var2 AS DOUBLE)
  1110.  
  1111.  This example declares a subprogram Maxout that takes an integer passed by
  1112.  far reference, and a double-precision real number passed by value.
  1113.  
  1114.  
  1115.  2.2  Alternative BASIC Interfaces
  1116.  
  1117.  Though the DECLARE statement provides a particularly convenient interface,
  1118.  there are other methods of implementing mixed-language calls.
  1119.  
  1120.  Instead of modifying the behavior of BASIC with CDECL, you can modify the
  1121.  behavior of C by applying the pascal or fortran keyword to the function
  1122.  definition heading. (These two keywords are functionally equivalent). Or
  1123.  you can compile the C module with the /Gc option, which specifies that all
  1124.  C functions, calls, and public symbols use the conventions of
  1125.  BASIC/FORTRAN/Pascal.
  1126.  
  1127.  For example, the following C function uses the BASIC/FORTRAN/Pascal
  1128.  conventions to receive an integer paramter:
  1129.  
  1130.  int pascal fun1(n)
  1131.  int n;
  1132.  
  1133.  You can specify parameter-passing methods without using a DECLARE
  1134.  statement or by using a DECLARE statement and omitting the parameter list.
  1135.  
  1136.    ■  You can make the call with the CALLS statement. The CALLS statement
  1137.       causes each parameter to be passed by far reference.
  1138.  
  1139.    ■  You can use the BYVAL and SEG keywords in the actual parameter list
  1140.       when you make the call:
  1141.  
  1142.       CALL Fun2(BYVAL Term1, BYVAL Term2, SEG Sum);
  1143.  
  1144.  In the example above, BYVAL and SEG have the same meaning that they have in
  1145.  a BASIC DECLARE statement. When you use BYVAL and SEG this way, however,
  1146.  you need to be careful because neither the type nor the number of
  1147.  parameters will be checked as they would be in a DECLARE statement.
  1148.  
  1149.  
  1150.  2.3  BASIC Calls to C
  1151.  
  1152.  This section applies the steps outlined in Section 2.1 to two example
  1153.  programs. An analysis of programming considerations follows each example.
  1154.  
  1155.  
  1156.  2.3.1  Calling C from BASIC--No Return Value
  1157.  
  1158.  The example below demonstrates a BASIC main module calling a C function,
  1159.  maxparam. The function maxparam returns no value, but adjusts the lower of
  1160.  two arguments to equal the higher argument.
  1161.  
  1162.  
  1163.  ■  Example
  1164.  
  1165.  ' BASIC source file - calls C function returning no value
  1166.  '
  1167.  DECLARE SUB Maxparam CDECL (A AS INTEGER, B AS INTEGER)
  1168.  '
  1169.  ' DECLARE as subprogram, since there is no return value
  1170.  ' CDECL keyword causes Maxparam call to be made w/ C conventions
  1171.  ' Integer parameters passed by near reference (BASIC default)
  1172.  '
  1173.  X% = 5
  1174.  Y% = 7
  1175.  PRINT USING "X% = ##  Y% = ##";X% ;Y%   ' X% and Y% before call
  1176.  CALL Maxparam(X%, Y%)                   ' Call C function
  1177.  PRINT USING "X% = ##  Y% = ##";X% ;Y%   ' X% and Y% after call
  1178.  END
  1179.  
  1180.  /* C source file */
  1181.  /* Compile in MEDIUM or LARGE memory model */
  1182.  /* Maxparam declared VOID because no return value */
  1183.  
  1184.  void maxparam(p1, p2)
  1185.  int near *p1;        /* Integer params received by near ref. */
  1186.  int near *p2;        /* NEAR keyword not needed in MEDIUM model */
  1187.  {
  1188.          if (*p1 > *p2)
  1189.                  *p2 = *p1;
  1190.          else
  1191.                  *p1 = *p2;
  1192.  }
  1193.  
  1194.  Naming conventions: The CDECL keyword causes Maxparam to be called with the
  1195.  C naming convention (as _maxparam). Note that word length is not an issue
  1196.  because maxparam does not exceed eight characters.
  1197.  
  1198.  Calling conventions: The CDECL keyword causes Maxparam to be called with
  1199.  the C calling convention, which pushes parameters in the reverse order to
  1200.  how they appear in the source code.
  1201.  
  1202.  Parameter-passing methods: Since the C function maxparam may alter the
  1203.  value of either parameter, both parameters must be passed by reference. In
  1204.  this case, near reference was chosen; this method is the default for BASIC
  1205.  (so neither BYVAL nor SEG is used) and is specified in C by using near
  1206.  pointers.
  1207.  
  1208.  Far reference could have been specified by applying SEG to each argument
  1209.  in the DECLARE statement. In that case, the C parameter declarations would
  1210.  use far pointers.
  1211.  
  1212.  
  1213.  2.3.2  Calling C from BASIC--Function Call
  1214.  
  1215.  The example below demonstrates a BASIC main module calling a C function,
  1216.  fact. This function returns the factorial of an integer value.
  1217.  
  1218.  
  1219.  ■  Example
  1220.  
  1221.  ' BASIC source file - calls C function with return value
  1222.  '
  1223.  DECLARE FUNCTION Fact% CDECL (BYVAL N AS INTEGER)
  1224.  '
  1225.  ' DECLARE as function returning integer (%)
  1226.  ' CDECL keyword causes Fact% call to be made w/ C conventions
  1227.  ' Integer parameter passed by value
  1228.  '
  1229.  X% = 3
  1230.  Y% = 4
  1231.  PRINT USING "The factorial of X%    is ####"; Fact%(X%)
  1232.  PRINT USING "The factorial of Y%    is ####"; Fact%(Y%)
  1233.  PRINT USING "The factorial of X%+Y% is ####"; Fact%(X%+Y%)
  1234.  END
  1235.  
  1236.  /* C source file */
  1237.  /* Compile in MEDIUM or LARGE model */
  1238.  /* Factorial function, returning integer */
  1239.  
  1240.  int fact(n)
  1241.  int n;         /* Integer passed by value, the C default */
  1242.  {
  1243.           int   result = 1;
  1244.  
  1245.           while (n > 0)
  1246.                 result *= n--;  /* Parameter n modified here */
  1247.           return(result);
  1248.  }
  1249.  
  1250.  Naming conventions: The CDECL keyword causes Fact to be called with the C
  1251.  naming convention (as _fact). Note that word length is not an issue
  1252.  because fact does not exceed eight characters.
  1253.  
  1254.  Calling conventions: The CDECL keyword causes fact to be called with the C
  1255.  calling convention, which pushes parameters in reverse order and
  1256.  specifies other low-level differences.
  1257.  
  1258.  Parameter-passing methods: The C function above should receive the
  1259.  parameter by value. Otherwise the function will corrupt the parameter's
  1260.  value in the calling module. True passing by value is achieved in BASIC
  1261.  only by applying BYVAL to the parameter in the DECLARE statement; in C,
  1262.  passing by value is the default (except for arrays).
  1263.  
  1264.  
  1265.  2.4  BASIC Calls to FORTRAN
  1266.  
  1267.  This section applies the steps outlined in Section 2.1 to two example
  1268.  programs. An analysis of programming considerations follows each example.
  1269.  
  1270.  
  1271.  2.4.1  Calling FORTRAN from BASIC--Subroutine Call
  1272.  
  1273.  The example below demonstrates a BASIC main module calling a FORTRAN
  1274.  subroutine, MAXPARAM. The subroutine returns no value, but adjusts the
  1275.  lower of two arguments to equal the higher argument.
  1276.  
  1277.  
  1278.  ■  Example
  1279.  
  1280.  ' BASIC source file - calls FORTRAN subroutine
  1281.  '
  1282.  DECLARE SUB Maxparam ALIAS "MAXPAR" (A AS INTEGER, B AS INTEGER)
  1283.  '
  1284.  ' DECLARE as subprogram, since there is no return value
  1285.  ' ALIAS needed because FORTRAN recognizes only first 6 letters
  1286.  ' Integer parameters passed by near reference (BASIC default)
  1287.  '
  1288.  X% = 5
  1289.  Y% = 7
  1290.  PRINT USING "X% = ##  Y% = ##";X% ;Y%   ' X% and Y% before call
  1291.  CALL Maxparam(X%, Y%)                   ' Call FORTRAN function
  1292.  PRINT USING "X% = ##  Y% = ##";X% ;Y%   ' X% and Y% after call
  1293.  END
  1294.  
  1295.  C   FORTRAN source file, subroutine MAXPARAM
  1296.  C
  1297.           SUBROUTINE MAXPARAM (I, J)
  1298.           INTEGER*2 I [NEAR]
  1299.           INTEGER*2 J [NEAR]
  1300.  
  1301.  C
  1302.  C   I and J received by near reference, because of NEAR attribute
  1303.  C
  1304.           IF (I .GT. J) THEN
  1305.                   J = I
  1306.           ELSE
  1307.                   I = J
  1308.           ENDIF
  1309.           END
  1310.  
  1311.  Naming conventions: By default, BASIC places all  eight characters of
  1312.  Maxparam into the object file, yet FORTRAN places only the first six. This
  1313.  conflict is resolved with the ALIAS feature: both modules place MAXPAR into
  1314.  the object file.
  1315.  
  1316.  Calling conventions: BASIC and FORTRAN use the same convention for
  1317.  calling.
  1318.  
  1319.  Parameter-passing methods: Since the subprogram Maxparam may alter the
  1320.  value of either parameter, both arguments must be passed by reference. In
  1321.  this case, near reference was chosen; this method is the default for
  1322.  BASIC (so neither BYVAL nor SEG is used) and is specified in FORTRAN by
  1323.  applying the NEAR attribute to each of the parameter declarations.
  1324.  
  1325.  Far reference could have been specified by applying SEG to each argument
  1326.  in the DECLARE statement. In that case, the NEAR attribute would not be
  1327.  used in the FORTRAN code.
  1328.  
  1329.  
  1330.  2.4.2  Calling FORTRAN from BASIC--Function Call
  1331.  
  1332.  The example below demonstrates a BASIC main module calling a FORTRAN
  1333.  function, FACT. This function returns the factorial of an integer value.
  1334.  
  1335.  
  1336.  ■  Example
  1337.  
  1338.  ' BASIC source file - calls FORTRAN function
  1339.  '
  1340.  DECLARE FUNCTION Fact% (BYVAL N AS INTEGER)
  1341.  '
  1342.  ' DECLARE as function returning integer(%)
  1343.  ' Integer parameter passed by value
  1344.  '
  1345.  X% = 3
  1346.  Y% = 4
  1347.  PRINT USING "The factorial of X%    is ####"; Fact%(X%)
  1348.  PRINT USING "The factorial of Y%    is ####"; Fact%(Y%)
  1349.  PRINT USING "The factorial of X%+Y% is ####"; Fact%(X%+Y%)
  1350.  END
  1351.  
  1352.  C   FORTRAN source file - factorial function
  1353.  C
  1354.          INTEGER*2 FUNCTION FACT (N)
  1355.          INTEGER*2 N [VALUE]
  1356.  C
  1357.  C   N is received by value, because of VALUE attribute
  1358.  C
  1359.          INTEGER*2 I
  1360.          FACT = 1
  1361.          DO 100 I = 1, N
  1362.              FACT = FACT * I
  1363.   100        CONTINUE
  1364.          RETURN
  1365.          END
  1366.  
  1367.  Naming conventions: There are no conflicts with naming conventions because
  1368.  the function name, FACT, does not exceed six characters. The type
  1369.  declaration character (%) is automatically dropped by BASIC.
  1370.  
  1371.  Calling conventions: BASIC and FORTRAN use the same convention for
  1372.  calling.
  1373.  
  1374.  Parameter-passing methods: When a parameter is passed that should not be
  1375.  changed, it is generally safest to pass the parameter by value. True
  1376.  passing by value is specified in BASIC by applying BYVAL to an argument in
  1377.  the DECLARE statement; in FORTRAN, passing by value is achieved by applying
  1378.  the VALUE attribute to a parameter declaration.
  1379.  
  1380.  
  1381.  2.5  BASIC Calls to Pascal
  1382.  
  1383.  This section applies the steps outlined in Section 2.1 to two example
  1384.  programs. An analysis of programming considerations follows each example.
  1385.  
  1386.  
  1387.  2.5.1  Calling Pascal from BASIC--Procedure Call
  1388.  
  1389.  The example below demonstrates a BASIC main module calling a Pascal
  1390.  procedure, Maxparam. Maxparam returns no value, but adjusts the lower of
  1391.  two arguments to equal the higher argument.
  1392.  
  1393.  
  1394.  ■  Example
  1395.  
  1396.  ' BASIC source file - calls Pascal procedure
  1397.  '
  1398.  DECLARE SUB Maxparam (A AS INTEGER, B AS INTEGER)
  1399.  '
  1400.  ' DECLARE as subprogram, since there is no return value
  1401.  ' Integer parameters passed by near reference (BASIC default)
  1402.  '
  1403.  X% = 5
  1404.  Y% = 7
  1405.  PRINT USING "X% = ##  Y% = ##";X% ;Y%   ' X% and Y% before call
  1406.  CALL Maxparam(X%, Y%)                   ' Call Pascal function
  1407.  PRINT USING "X% = ##  Y% = ##";X% ;Y%   ' X% and Y% after call
  1408.  END
  1409.  
  1410.  {  Pascal source code - Maxparam procedure. }
  1411.  
  1412.  module Psub;
  1413.   procedure Maxparam(var a:integer; var b:integer);
  1414.  
  1415.  {  Two integer parameters are received by near reference. }
  1416.  {  Near reference is specified with the VAR keyword. }
  1417.  
  1418.   begin
  1419.      if a > b then
  1420.          b := a
  1421.      else
  1422.          a := b
  1423.   end;
  1424.  end.
  1425.  
  1426.  Naming conventions: Note that word length is not an issue because Maxparam
  1427.  does not exceed eight characters.
  1428.  
  1429.  Calling conventions: BASIC and Pascal use the same calling convention.
  1430.  
  1431.  Parameter-passing methods: Since the procedure Maxparam may alter the
  1432.  value of either parameter, both parameters must be passed by reference. In
  1433.  this case, near reference was chosen; this method is the default for BASIC
  1434.  (so neither BYVAL nor SEG is used) and is specified in Pascal by declaring
  1435.  parameters as VAR.
  1436.  
  1437.  Far reference could have been specified by applying SEG to each argument
  1438.  in the DECLARE statement. In that case, the VARS keyword would be required
  1439.  instead of VAR.
  1440.  
  1441.  
  1442.  2.5.2  Calling Pascal from BASIC--Function Call
  1443.  
  1444.  The example below demonstrates a BASIC main module calling a Pascal
  1445.  function, Fact. This function returns the factorial of an integer value.
  1446.  
  1447.  
  1448.  ■  Example
  1449.  
  1450.  ' BASIC source file - calls Pascal function
  1451.  '
  1452.  DECLARE FUNCTION Fact% (BYVAL N AS INTEGER)
  1453.  '
  1454.  ' DECLARE as function returning integer (%)
  1455.  ' Integer parameter passed by value
  1456.  '
  1457.  X% = 3
  1458.  Y% = 4
  1459.  PRINT USING "The factorial of X%    is ####"; Fact%(X%)
  1460.  PRINT USING "The factorial of Y%    is ####"; Fact%(Y%)
  1461.  PRINT USING "The factorial of X%+Y% is ####"; Fact%(X%+Y%)
  1462.  END
  1463.  
  1464.  { Pascal source code - factorial function. }
  1465.  
  1466.  module Pfun;
  1467.   function Fact (n : integer) : integer;
  1468.  
  1469.  { Integer parameters received by value, the Pascal default. }
  1470.  
  1471.   begin
  1472.      Fact := 1;
  1473.      while n > 0 do
  1474.          begin
  1475.              Fact := Fact * n;
  1476.              n := n - 1;           { Parameter n altered here. }
  1477.          end;
  1478.   end;
  1479.  end.
  1480.  
  1481.  Naming conventions: Note that word length is not an issue because fact does
  1482.  not exceed eight characters.
  1483.  
  1484.  Calling conventions: BASIC and Pascal use the same calling convention.
  1485.  
  1486.  Parameter-passing methods: The Pascal function above should receive a
  1487.  parameter by value. Otherwise the function will corrupt the parameter's
  1488.  value in the calling module. True passing by value is achieved in BASIC
  1489.  only by applying BYVAL to the parameter; in Pascal, passing by value is the
  1490.  default.
  1491.  
  1492.  
  1493.  2.6  Restrictions on Calls from BASIC
  1494.  
  1495.  BASIC has a much more complex environment and initialization procedure than
  1496.  C, FORTRAN, or Pascal (all of which use a similar environment).
  1497.  Interlanguage calling between BASIC and these other languages is possible
  1498.  only because BASIC intercepts a number of library function calls from the
  1499.  other languages and handles them in its own way. In other words, BASIC
  1500.  creates a host environment in which the C, FORTRAN, and Pascal library
  1501.  routines can function.
  1502.  
  1503.  However, BASIC is limited in its ability to handle some C function calls.
  1504.  This section considers two kinds of limitations: C memory-allocation
  1505.  functions, which may require a special declaration, and C library
  1506.  functions, which cannot be called at all.
  1507.  
  1508.  
  1509.  2.6.1  Memory Allocation
  1510.  
  1511.  If your C module is medium model and you do dynamic memory allocation with
  1512.  malloc(), or if you execute explicit calls to _nmalloc() with any memory
  1513.  model, then you need to include the following lines in your BASIC source
  1514.  code before you call C:
  1515.  
  1516.  DIM mallocbuf%(2048)
  1517.  COMMON SHARED /NMALLOC/ mallocbuf%()
  1518.  
  1519.  The array can have any name; only the size of the array is significant.
  1520.  However, the name of the common block must be NMALLOC. In the QuickBASIC,
  1521.  Version 4.0, in-memory environment, you need to put this declaration in a
  1522.  module that you load into a resident Quick library.
  1523.  
  1524.  The example above has the effect of reserving 4k bytes of space in the
  1525.  common block NMALLOC. When BASIC intercepts C malloc calls, BASIC
  1526.  allocates space out of this common block.
  1527.  
  1528.  ───────────────────────────────────────────────────────────────────────────
  1529.  Warning
  1530.    When you call the BASIC intrinsic function CLEAR, all space allocated
  1531.    with near malloc calls will be lost. If you use CLEAR at all, use it only
  1532.    before any calls to malloc.
  1533.  ───────────────────────────────────────────────────────────────────────────
  1534.  
  1535.  When you make far memory requests in mixed-language programs, you may find
  1536.  it useful to first call the BASIC intrinsic function SETMEM. This function
  1537.  can be used to reduce the amount of memory BASIC is using, thus freeing up
  1538.  memory for far allocations.
  1539.  
  1540.  
  1541.  2.6.2  Incompatible Functions
  1542.  
  1543.  The following C functions are incompatible with BASIC and should be
  1544.  avoided:
  1545.  
  1546.    ■  All forms of spawn() and exec()
  1547.  
  1548.    ■  system()
  1549.  
  1550.    ■  getenv()
  1551.  
  1552.    ■  putenv()
  1553.  
  1554.  In addition, you should not link with the xVARSTK.OBJ modules (where x is a
  1555.  memory model), which C provides to allocate memory from the stack.
  1556.  
  1557.  
  1558.  
  1559.  CHAPTER 3  C CALLS TO HIGH-LEVEL LANGUAGES
  1560.  
  1561.  ───────────────────────────────────────────────────────────────────────────
  1562.  
  1563.  3.1  The C Interface to Other Languages
  1564.  
  1565.  3.2  Alternative C Interfaces
  1566.  
  1567.  3.3  C Calls to BASIC
  1568.  
  1569.  3.4  C Calls to FORTRAN
  1570.  
  1571.        3.4.1  Calling FORTRAN from C--Subroutine Call
  1572.  
  1573.        3.4.2  Calling FORTRAN from C--Function Call
  1574.  
  1575.  3.5  C Calls to Pascal
  1576.  
  1577.        3.5.1  Calling Pascal from C--Procedure Call
  1578.  
  1579.        3.5.2  Calling Pascal from C--Function Call
  1580.  
  1581.  
  1582.  
  1583.  Microsoft C supports calls to routines written in Microsoft FORTRAN and
  1584.  Pascal. Also, if the main program is in BASIC, then a C routine can call a
  1585.  BASIC routine. This chapter describes the necessary syntax for calling
  1586.  these other languages, and then gives examples for each language. Only
  1587.  simple parameter lists are used in this chapter.
  1588.  
  1589.  For information on how to pass particular kinds of data, consult Part 2,
  1590.  "Data Handling Reference."
  1591.  
  1592.  
  1593.  3.1  The C Interface to Other Languages
  1594.  
  1595.  The C interface to other languages utilizes the standard C extern
  1596.  statement, combined with the special fortran or pascal keyword. Using
  1597.  either of these keywords causes the routine to be called with the naming
  1598.  and calling conventions of FORTRAN/Pascal/BASIC.  Here are the recommended
  1599.  steps for using this statement to execute a mixed-language call from C:
  1600.  
  1601.    1.  Write an extern statement for each mixed-language routine called.
  1602.  
  1603.        The extern statement should precede all calls to the routine. The
  1604.        exact rules of syntax for using the fortran and pascal keywords
  1605.        with the extern statement are presented below.
  1606.  
  1607.        Instead of using the fortran or pascal keyword, you can simply
  1608.        compile with /Gc. The /Gc option causes all functions inp the module
  1609.        to use the BASIC/FORTRAN/Pascal naming and calling conventions,
  1610.        except where you apply the cdecl keyword.
  1611.  
  1612.    2.  Use parameter type declarations within the extern statement.
  1613.  
  1614.        This step is essential if you are going to specify pointers that are
  1615.        not the default size. (Near pointers are the default for medium
  1616.        model; far pointers are the default for large model.)
  1617.  
  1618.    3.  To pass an argument by reference, pass a pointer to the object.
  1619.  
  1620.        C automatically translates array names into addresses. Therefore,
  1621.        arrays are automatically passed by reference.
  1622.  
  1623.    4.  Once a routine has been properly declared with an extern statement,
  1624.        call it just as you would call a C function.
  1625.  
  1626.    5.  Always compile the C module in medium or large model.
  1627.  
  1628.  
  1629.  ■  Using fortran and pascal Keywords
  1630.  
  1631.  There are two rules of syntax that apply when you use the fortran or pascal
  1632.  keyword:
  1633.  
  1634.    1.  The fortran and pascal keywords modify the item immediately to the
  1635.        right.
  1636.  
  1637.    2.  The special near and far keywords can be used with the fortran and
  1638.        pascal keywords in declarations. The sequences fortran far and far
  1639.        fortran are equivalent.
  1640.  
  1641.  The keywords pascal and fortran actually have the same effect on the
  1642.  program; the use of one or the other makes no difference except for
  1643.  documentation purposes. Use either keyword to declare a BASIC routine.
  1644.  
  1645.  The following examples demonstrate the syntax rules presented above.
  1646.  
  1647.  
  1648.  ■  Examples
  1649.  
  1650.  extern short pascal thing(short, short);     /* Example 1 */
  1651.  
  1652.  Example 1 declares thing to be a BASIC, Pascal, or FORTRAN function taking
  1653.  two short parameters and returning a short value.
  1654.  
  1655.  extern void (fortran *thing)(long);          /* Example 2 */
  1656.  
  1657.  Example 2 declares thing to be pointer to a BASIC, Pascal, or FORTRAN
  1658.  routine that takes a long parameter and returns no value. The keyword void
  1659.  is appropriate when the called routine is a BASIC subprogram, Pascal
  1660.  procedure, or FORTRAN subroutine, since it indicates that no return value
  1661.  is required.
  1662.  
  1663.  extern short near pascal thing(double *);      /* Example 3 */
  1664.  
  1665.  Example 3 declares thing to be a near BASIC, Pascal, or FORTRAN routine.
  1666.  The routine receives a double parameter by reference (because it expects a
  1667.  pointer to a double) and returns a short value.
  1668.  
  1669.  extern short pascal near thing(double *);      /* Example 4 */
  1670.  
  1671.  Example 4 is equivalent to Example 3 (pascal near is equivalent to near
  1672.  pascal).
  1673.  
  1674.  
  1675.  3.2  Alternative C Interfaces
  1676.  
  1677.  When you call BASIC, you must use the BASIC/FORTRAN/Pascal conventions to
  1678.  make the call. When you call FORTRAN or Pascal, however, you have a choice.
  1679.  You can make C adopt the appropriate conventions (as described in the
  1680.  previous section), or you can make the FORTRAN or Pascal routine adopt the
  1681.  C conventions.
  1682.  
  1683.  To make a FORTRAN or Pascal routine adopt the C conventions, simply put
  1684.  the C attribute in the heading of the routine's definition. The following
  1685.  example demonstrates the syntax for the C attribute in a FORTRAN
  1686.  subroutine-definition heading:
  1687.  
  1688.       SUBROUTINE FFROMC [C] (N)
  1689.       INTEGER*2 N
  1690.  
  1691.  The following example demonstrates the syntax for the C attribute in a
  1692.  Pascal procedure-definition heading:
  1693.  
  1694.  module Pmod;
  1695.  procedure Pfromc (n : integer) [C];
  1696.  begin
  1697.  
  1698.  
  1699.  3.3  C Calls to BASIC
  1700.  
  1701.  No BASIC routine can be executed unless the main program is in BASIC,
  1702.  because a BASIC routine requires the environment to be initialized in a way
  1703.  that is unique to BASIC. No other language will perform this special
  1704.  initialization.
  1705.  
  1706.  However, it is possible for a program to start up in BASIC, call a C
  1707.  function that does most of the work of the program, and then call BASIC
  1708.  subprograms and function procedures as needed. Figure 3.1 illustrates how
  1709.  this can be done.
  1710.  
  1711.  The following rules are recommended when you call BASIC from C:
  1712.  
  1713.    1.  Start up in a BASIC main module. You will need to use QuickBASIC,
  1714.        Version 4.0 or later, and the DECLARE statement to provide an
  1715.        interface to the C module. (See Chapter 2, "BASIC Calls to High-Level
  1716.        Languages," for more information.)
  1717.  
  1718.    2.  Once in the C module, declare the BASIC routine as extern, and
  1719.        include type information for parameters. Use either the fortran or
  1720.        pascal keyword to modify the routine itself.
  1721.  
  1722.    3.  Make sure that all data are passed as a near pointer. BASIC can pass
  1723.        data in a variety of ways, but is unable to receive data in any form
  1724.        other than near reference.
  1725.  
  1726.        With near pointers, the program assumes that the data are in the
  1727.        default data segment. If you want to pass data that are not in the
  1728.        default data segment (this is only a consideration with large-model
  1729.        programs), then first copy the data to a variable that is in the
  1730.        default data segment.
  1731.  
  1732.    4.  Compile the C module in medium or large model.
  1733.  
  1734.  
  1735.               BASIC code                             C code
  1736.  
  1737.    ┌───────────────────────────────┐    ┌───────────────────────────────┐
  1738.    │                               │    │                               │
  1739.    │                               │    │                               │
  1740.    │ (BASIC start-up)              │    │                               │
  1741.    │                               │    │                               │
  1742.    │ CALL Csub ──────┐             │    │                               │
  1743.    │ END             └─────────────┼────┼void csub() {                 │
  1744.    │                               │    │ .                             │
  1745.    │ (BASIC termination)           │    │ .                             │
  1746.    │                               │    │ .                             │
  1747.    │                      ┌────────┼────┼─btest();                      │
  1748.    │                      │        │    │ .                             │
  1749.    │ SUB Btest STATIC ───┘        │    │ .                             │
  1750.    │ .                             │    │ .                             │
  1751.    │ .                             │    │ }                             │
  1752.    │ .                             │    │                               │
  1753.    │ END SUB                       │    │                               │
  1754.    │                               │    │                               │
  1755.    │                               │    │                               │
  1756.    └───────────────────────────────┘    └───────────────────────────────┘
  1757.  
  1758.  Figure 3.1  C Call to BASIC
  1759.  
  1760.  
  1761.  The example below demonstrates a BASIC program that calls a C function.
  1762.  The C function then calls a BASIC function that returns twice the number
  1763.  passed it and a BASIC subprogram that prints two numbers.
  1764.  
  1765.  
  1766.  ■  Example
  1767.  
  1768.  ' BASIC source
  1769.  '
  1770.  DEFINT A-Z
  1771.  DECLARE SUB Cprog CDECL()
  1772.  CALL Cprog
  1773.  END
  1774.  '
  1775.  FUNCTION Dbl(N) STATIC
  1776.      Dbl = N*2
  1777.  END FUNCTION
  1778.  '
  1779.  SUB Printnum(A,B) STATIC
  1780.      PRINT "The first number is ";A
  1781.      PRINT "The second number is ";B
  1782.  END SUB
  1783.  
  1784.  /* C source; compile in medium or large model */
  1785.  
  1786.  extern int fortran dbl(int near *);
  1787.  extern void fortran printnum(int near *, int near *);
  1788.  
  1789.  void cprog()
  1790.  {
  1791.          int near a = 5;   /* NEAR guarantees that the data  */
  1792.          int near b = 6;   /*   will be placed in default    */
  1793.                            /*   data segment (DGROUP)        */
  1794.  
  1795.          printf("Twice of 5 is %d\n", dbl(&a));
  1796.          printnum(&a, &b);
  1797.  }
  1798.  
  1799.  In the example above, note that the addresses of a and b are passed, since
  1800.  BASIC expects to receive addresses for parameters. Also note that the
  1801.  keyword near is used to declare each pointer; this keyword would be
  1802.  unnecessary if we knew the C module was compiled in medium model rather
  1803.  than large.
  1804.  
  1805.  Calling and naming conventions are resolved by the CDECL keyword in
  1806.  BASIC's declaration of Cprog, and by fortran in C's declaration of dbl and
  1807.  printnum.
  1808.  
  1809.  ───────────────────────────────────────────────────────────────────────────
  1810.  Note
  1811.    QuickBASIC 4.0 provides a number of "user-entry points," which are BASIC
  1812.    system-level functions that may be called directly from C. These
  1813.    functions provide memory management, C-string services, and I/O
  1814.    procedures. Check the README file provided with QuickBASIC 4.0 for
  1815.    further information.
  1816.  ───────────────────────────────────────────────────────────────────────────
  1817.  
  1818.  
  1819.  3.4  C Calls to FORTRAN
  1820.  
  1821.  This section applies the steps outlined in Section 3.1 to two examples of
  1822.  C-FORTRAN programs. A brief analysis follows each example.
  1823.  
  1824.  
  1825.  3.4.1  Calling FORTRAN from C--Subroutine Call
  1826.  
  1827.  The example below demonstrates a C main module calling a FORTRAN
  1828.  subroutine, maxpar. This subroutine adjusts the lower of two arguments to
  1829.  equal the higher argument.
  1830.  
  1831.  
  1832.  ■  Example
  1833.  
  1834.  /* C source file - calls FORTRAN subroutine */
  1835.  /* Compile in MEDIUM or LARGE model */
  1836.  
  1837.  extern void fortran maxpar (int near *, int near *);
  1838.  
  1839.  /* Declare as VOID, because there is no return value */
  1840.  /* FORTRAN keyword causes C to use BASIC/FORTRAN/Pascal
  1841.     calling and naming conventions    */
  1842.  /* Two integer params, passed by near reference */
  1843.  
  1844.  main()
  1845.  {
  1846.          int a = 5;
  1847.          int b = 7;
  1848.  
  1849.          printf("a = %d, b = %d", a, b);
  1850.          maxpar(&a, &b);
  1851.          printf("a = %d, b = %d", a, b);
  1852.  }
  1853.  
  1854.  C   FORTRAN source file, subroutine MAXPARAM
  1855.  C
  1856.          SUBROUTINE MAXPARAM (I, J)
  1857.          INTEGER*2 I [NEAR]
  1858.          INTEGER*2 J [NEAR]
  1859.  C
  1860.  C   I and J received by near reference, because of NEAR attribute
  1861.  C
  1862.  
  1863.          IF (I .GT. J) THEN
  1864.                  J = I
  1865.          ELSE
  1866.                  I = J
  1867.          ENDIF
  1868.          END
  1869.  
  1870.  Naming conventions: The fortran keyword directs C to call maxpar with the
  1871.  BASIC/FORTRAN/Pascal naming convention (as MAXPAR). Note that maxpar is six
  1872.  letters long; it cannot be any longer because FORTRAN only recognizes the
  1873.  first six characters of any name.
  1874.  
  1875.  Calling conventions: The fortran keyword directs C to call maxpar with the
  1876.  BASIC/FORTRAN/Pascal calling convention.
  1877.  
  1878.  Parameter-passing methods: Since the FORTRAN subroutine maxpar may alter
  1879.  the value of either parameter, both parameters must be passed by reference.
  1880.  In this case, near reference was chosen; this method is specified in C by
  1881.  the use of near pointers, and in FORTRAN by applying the NEAR keyword to
  1882.  the parameter declarations.
  1883.  
  1884.  Far reference could have been specified by using far pointers in C. In
  1885.  that case, the FORTRAN subroutine would not use the NEAR attribute (and
  1886.  would require the FAR attribute if compiled with medium memory model
  1887.  available with FORTRAN, Version 4.0).
  1888.  
  1889.  
  1890.  3.4.2  Calling FORTRAN from C--Function Call
  1891.  
  1892.  The example below demonstrates a C main module calling a FORTRAN function,
  1893.  fact. This function returns the factorial of an integer value.
  1894.  
  1895.  
  1896.  ■  Example
  1897.  
  1898.  /* C source file - calls FORTRAN function */
  1899.  /* Compile in MEDIUM or LARGE model */
  1900.  
  1901.  extern int fortran fact (int);
  1902.  
  1903.  /* FORTRAN keyword causes C to use BASIC/FORTRAN/Pascal
  1904.     calling and naming conventions    */
  1905.  /* Integer parameter passed by value, the C default */
  1906.  
  1907.  main()
  1908.  {
  1909.          int x = 3;
  1910.          int y = 4;
  1911.  
  1912.          printf("The factorial of x   is %4d", fact(x));
  1913.          printf("The factorial of y   is %4d", fact(y));
  1914.          printf("The factorial of x+y is %4d", fact(x+y));
  1915.  }
  1916.  
  1917.  C   FORTRAN source file - factorial function
  1918.  C
  1919.          INTEGER*2 FUNCTION FACT (N)
  1920.          INTEGER*2 N [VALUE]
  1921.  C
  1922.  C   N is received by value, because of VALUE attribute
  1923.  C
  1924.          INTEGER*2 I
  1925.          FACT = 1
  1926.          DO 100 I = 1, N
  1927.              FACT = FACT * I
  1928.    100       CONTINUE
  1929.          RETURN
  1930.          END
  1931.  
  1932.  Naming conventions: The fortran keyword directs C to call fact with the
  1933.  BASIC/FORTRAN/Pascal naming convention (as FACT). Note that word length is
  1934.  not an issue because FACT does not exceed six characters.
  1935.  
  1936.  Calling conventions: The fortran keyword directs C to call fact with the
  1937.  BASIC/FORTRAN/Pascal calling convention.
  1938.  
  1939.  Parameter-passing methods: When a parameter is passed that should not be
  1940.  changed, it is generally safest to pass the parameter by value. Passing by
  1941.  value is the default method in C, and is specified in FORTRAN by applying
  1942.  the VALUE attribute to the parameter declaration.
  1943.  
  1944.  
  1945.  3.5  C Calls to Pascal
  1946.  
  1947.  This section applies the steps outlined in Section 3.1 to two examples
  1948.  of C-Pascal programs. A brief analysis follows each example.
  1949.  
  1950.  
  1951.  3.5.1  Calling Pascal from C--Procedure Call
  1952.  
  1953.  The example below demonstrates a C main module calling a Pascal procedure,
  1954.  maxpar. This procedure adjusts the lower of two arguments to equal the
  1955.  higher argument.
  1956.  
  1957.  
  1958.  ■  Example
  1959.  
  1960.  /* C source file - calls Pascal procedure */
  1961.  /* Compile in MEDIUM or LARGE model */
  1962.  
  1963.  extern void pascal maxparam (int near *, int near *);
  1964.  
  1965.  /* Declare as VOID, because there is no return value */
  1966.  /* PASCAL keyword causes C to use BASIC/FORTRAN/Pascal
  1967.     calling and naming conventions    */
  1968.  /* Two integer params, passed by near reference */
  1969.  
  1970.  main()
  1971.  {
  1972.          int a = 5;
  1973.          int b = 7;
  1974.  
  1975.          printf("a = %d, b = %d", a, b);
  1976.          maxparam(&a, &b);
  1977.          printf("a = %d, b = %d", a, b);
  1978.  }
  1979.  
  1980.  { Pascal source code - Maxparam procedure. }
  1981.  
  1982.  module Psub;
  1983.   procedure Maxparam(var a:integer; var b:integer);
  1984.  
  1985.  { Two integer parameters are received by near reference. }
  1986.  { Near reference is specified with the VAR keyword. }
  1987.  
  1988.   begin
  1989.      if a > b then
  1990.          b := a
  1991.      else
  1992.          a := b
  1993.   end;
  1994.  end.
  1995.  
  1996.  Naming conventions: The pascal keyword directs C to call Maxparam with the
  1997.  BASIC/FORTRAN/Pascal naming convention (as MAXPARAM).
  1998.  
  1999.  Calling conventions: The pascal keyword directs C to call Maxparam with the
  2000.  BASIC/FORTRAN/Pascal naming convention.
  2001.  
  2002.  Parameter-passing methods: Since the procedure Maxparam may alter the
  2003.  value of either parameter, both parameters must be passed by reference. In
  2004.  this case, near reference is used; this method is specified in C by the use
  2005.  of near pointers, and in Pascal with the VAR keyword.
  2006.  
  2007.  Far reference could have been specified by using far pointers in C. In
  2008.  that case, the VARS keyword would be required instead of VAR in Pascal.
  2009.  
  2010.  
  2011.  3.5.2  Calling Pascal from C--Function Call
  2012.  
  2013.  The example below demonstrates a C main module calling a Pascal function,
  2014.  fact. This function returns the factorial of an integer value.
  2015.  
  2016.  
  2017.  ■  Example
  2018.  
  2019.  /* C source file - calls Pascal function */
  2020.  /* Compile in MEDIUM or LARGE model */
  2021.  
  2022.  extern int pascal fact (int);
  2023.  
  2024.  /* PASCAL keyword causes C to use BASIC/FORTRAN/Pascal
  2025.     calling and naming conventions    */
  2026.  /* Integer parameter passed by value, the C default */
  2027.  
  2028.  main()
  2029.  {
  2030.          int x = 3;
  2031.          int y = 4;
  2032.  
  2033.          printf("The factorial of x   is %4d", fact(x));
  2034.          printf("The factorial of y   is %4d", fact(y));
  2035.          printf("The factorial of x+y is %4d", fact(x+y));
  2036.  }
  2037.  
  2038.  { Pascal source code - factorial function. }
  2039.  
  2040.  module Pfun;
  2041.   function Fact (n : integer) : integer;
  2042.  
  2043.  {Integer parameters received by value, the Pascal default. }
  2044.  
  2045.   begin
  2046.      Fact := 1;
  2047.      while n > 0 do
  2048.          begin
  2049.              Fact := Fact * n;
  2050.              n := n - 1;           {Parameter n modified here.}
  2051.          end;
  2052.   end;
  2053.  end.
  2054.  
  2055.  Naming conventions: The pascal keyword directs C to call fact with the
  2056.  BASIC/FORTRAN/Pascal naming convention (as FACT).
  2057.  
  2058.  Calling conventions: The pascal keyword directs C to call fact with the
  2059.  BASIC/FORTRAN/Pascal calling convention.
  2060.  
  2061.  Parameter-passing methods: The Pascal function above should receive a
  2062.  parameter by value. Otherwise, the Pascal function will corrupt the param-
  2063.  eter's value in the calling module. Passing by value is the default method
  2064.  for both C and Pascal.
  2065.  
  2066.  
  2067.  
  2068.  CHAPTER 4  FORTRAN CALLS TO HIGH-LEVEL LANGUAGES
  2069.  
  2070.  ───────────────────────────────────────────────────────────────────────────
  2071.  
  2072.  4.1  The FORTRAN Interface to Other Languages
  2073.  
  2074.        4.1.1  The INTERFACE Statement
  2075.  
  2076.        4.1.2  Using ALIAS
  2077.  
  2078.  4.2  Alternative FORTRAN Interface to C
  2079.  
  2080.  4.3  FORTRAN Calls to BASIC
  2081.  
  2082.  4.4  FORTRAN Calls to C
  2083.  
  2084.        4.4.1  Calling C from FORTRAN--No Return Value
  2085.  
  2086.        4.4.2  Calling C from FORTRAN--Function Call
  2087.  
  2088.  4.5  FORTRAN Calls to Pascal
  2089.  
  2090.        4.5.1  Calling Pascal from FORTRAN--Procedure Call
  2091.  
  2092.        4.5.2  Calling Pascal from FORTRAN--Function Call
  2093.  
  2094.  
  2095.  
  2096.  Microsoft FORTRAN supports calls to routines written in Microsoft C and
  2097.  Pascal. Also, if the main program is in BASIC, then a FORTRAN routine can
  2098.  call a BASIC routine. This chapter describes the necessary syntax for
  2099.  calling other languages from FORTRAN, and then gives examples for each
  2100.  language. Only simple parameter lists are used in this chapter.
  2101.  
  2102.  For information on how to pass particular kinds of data, consult Part
  2103.  2, "Data Handling Reference." Chapter 9 describes how to use the VARYING
  2104.  attribute with FORTRAN to pass a variable number of parameters.
  2105.  
  2106.  
  2107.  4.1  The FORTRAN Interface to Other Languages
  2108.  
  2109.  To call another language routine from within a FORTRAN function, first
  2110.  write an interface to the routine with the INTERFACE statement. This
  2111.  statement allows you to use special keywords (attributes) that affect how
  2112.  FORTRAN carries out calls. These keywords allow you to adjust naming
  2113.  conventions, calling conventions, and parameter-passing methods so that you
  2114.  can make routines from other languages compatible with FORTRAN.
  2115.  
  2116.  
  2117.  4.1.1  The INTERFACE Statement
  2118.  
  2119.  Here are the recommended rules for writing correct interfaces to
  2120.  routines from other languages:
  2121.  
  2122.    1.  Write an INTERFACE statement for each routine you call.
  2123.  
  2124.        Write the interface to a FUNCTION if the routine returns a value, or
  2125.        to a SUBROUTINE if the routine does not return a value. The INTERFACE
  2126.        statement should precede any calls to the routine.
  2127.  
  2128.    2.  Apply the C attribute to the routine if it is written in C (unless
  2129.        the C module is compiled with /Gc or is modified with the fortran or
  2130.        pascal keyword).
  2131.  
  2132.        The C attribute causes the routine to be called with the C naming and
  2133.        calling conventions. It also changes the default parameter-passing
  2134.        method for all parameters to pass by value. To apply the C attribute,
  2135.        type [C] immediately after the name of the routine.
  2136.  
  2137.    3.  If the routine is called from Pascal, you may want to apply the
  2138.        PASCAL attribute to the routine; this keyword does not change calling
  2139.        or naming conventions, but changes the default parameter-passing
  2140.        method for all parameters to pass by value.
  2141.  
  2142.        To apply the PASCAL attribute, type [PASCAL] immediately after the
  2143.        name of the routine.
  2144.  
  2145.    4.  If the name of the routine is longer than six characters, use the
  2146.        ALIAS attribute. The use of ALIAS is explained in Section 4.1.2.
  2147.  
  2148.    5.  Adjust parameter-passing methods by applying the VALUE, NEAR, FAR,
  2149.        and REFERENCE attributes to parameter declarations.
  2150.  
  2151.        The REFERENCE attribute can be useful because the C and PASCAL
  2152.        keywords automatically change the default parameter-passing method to
  2153.        passing by value. For any given parameter, REFERENCE changes the
  2154.        method back to passing by reference. (By default, FORTRAN passes by
  2155.        far reference unless you are using medium memory model which is
  2156.        available with FORTRAN, Versions 4.0 and later.)
  2157.  
  2158.        To apply an attribute to a parameter declaration, put the attribute
  2159.        in brackets, along with any other attributes that modify the same
  2160.        object, and place the attribute(s) and brackets immediately after the
  2161.        parameter. (Refer to the examples below.)
  2162.  
  2163.    6.  Once the proper interface is set up, call the routine just as you
  2164.        would call any FORTRAN function or subroutine.
  2165.  
  2166.  
  2167.  ■  Examples
  2168.  
  2169.  In the examples below, the variables N, I, and J are not significant,
  2170.  except for their types and attributes.
  2171.  
  2172.       INTERFACE TO SUBROUTINE TEST [PASCAL] (N)
  2173.       INTEGER*2 N [NEAR, REFERENCE]
  2174.       END
  2175.  
  2176.  The first example declares the subroutine TEST with the PASCAL attribute.
  2177.  This subroutine takes one argument, N, which has both the NEAR and
  2178.  REFERENCE attributes. N is passed by near reference.
  2179.  
  2180.       INTERFACE TO FUNCTION REAL*8 CFUN [C] (I,J)
  2181.       REAL*8 I [REFERENCE]
  2182.       REAL*8 J
  2183.       END
  2184.  
  2185.  The second example declares a C function, CFUN, which returns a value of
  2186.  type REAL*8. The argument I is passed by far reference because of the
  2187.  REFERENCE attribute; the argument J is passed by value because the C
  2188.  attribute changes the default.
  2189.  
  2190.  
  2191.  4.1.2  Using ALIAS
  2192.  
  2193.  The ALIAS attribute is used with the following syntax
  2194.  
  2195.  ALIAS:'aliasname'
  2196.  
  2197.  where aliasname is the name that FORTRAN will actually place in the object
  2198.  code whenever the declared routine is called. When you use this feature,
  2199.  aliasname is precisely what FORTRAN will place in the object code;
  2200.  therefore, if you are linking to a C routine, be sure to type a leading
  2201.  underscore (_) before the name.
  2202.  
  2203.  The ALIAS feature is necessary when the name of a routine is longer
  2204.  than 6 characters. Without ALIAS, FORTRAN would place only the first 6
  2205.  characters into the object file, while the other language would place 7 or
  2206.  8 characters into the other object file (or up to 40 in the case of BASIC).
  2207.  This difference would prevent the linker from finding a match.
  2208.  
  2209.  
  2210.  ■  Example
  2211.  
  2212.  INTERFACE TO PRINTNUM [C, ALIAS:'_printnum'] (N)
  2213.  INTEGER*2 N
  2214.  END
  2215.  
  2216.  In the example above, ALIAS is used because PRINTNUM is longer than six
  2217.  characters. Note that the leading underscore should be used only when
  2218.  linking to a routine that uses the C naming convention.
  2219.  
  2220.  
  2221.  4.2  Alternative FORTRAN Interface to C
  2222.  
  2223.  Instead of modifying the behavior of FORTRAN with the C attribute, you can
  2224.  modify the behavior of C by applying the pascal or fortran keyword to the
  2225.  function definition heading. (These two keywords are functionally
  2226.  equivalent). Or you can compile the C module with the /Gc option, which
  2227.  specifies that all C functions, calls, and public symbols use the
  2228.  BASIC/FORTRAN/Pascal conventions.
  2229.  
  2230.  For example, the following C function uses the BASIC/FORTRAN/Pascal
  2231.  conventions to receive an integer parameter:
  2232.  
  2233.  int fortran fun1(n)
  2234.  int n;
  2235.  
  2236.  
  2237.  4.3  FORTRAN Calls to BASIC
  2238.  
  2239.  Calls to BASIC from FORTRAN programs are not directly supported. No BASIC
  2240.  routine can be executed unless the main program is in BASIC, because a
  2241.  BASIC routine requires the environment to be initialized in a way that is
  2242.  unique to BASIC. No other language will perform this special
  2243.  initialization.
  2244.  
  2245.  However, it is possible for a program to start up in BASIC, call a FORTRAN
  2246.  function that does most of the work of the program, and then call BASIC
  2247.  subprograms and function procedures as needed. Figure 4.1 illustrates how
  2248.  this can be done.
  2249.  
  2250.  Here are the recommended rules for calling BASIC from FORTRAN:
  2251.  
  2252.    1.  Start up in a BASIC main module. You will need to use QuickBASIC,
  2253.        Version 4.0 or later, and may want to use the DECLARE statement to
  2254.        write an interface to the principal FORTRAN routine. (See Chapter 2,
  2255.        "BASIC Calls to High-Level Languages," for more information.)
  2256.  
  2257.    2.  Write an interface in FORTRAN for each BASIC routine you plan to
  2258.        call. Since BASIC and FORTRAN use the same basic calling convention,
  2259.        no special keyword is required to make FORTRAN compatible with BASIC.
  2260.  
  2261.    3.  Make sure that all data are passed as a near pointer. BASIC can pass
  2262.        data in a variety of ways, but is unable to receive data in any form
  2263.        other than near reference.
  2264.  
  2265.        With near pointers, the program assumes that the data are in the
  2266.        default data segment. If you want to pass data that are not in the
  2267.        default data segment (this is only a consideration with large model
  2268.        programs), then first copy the data to a variable that is in the
  2269.        default data segment.
  2270.  
  2271.  
  2272.  ■  Example
  2273.  
  2274.  The example below demonstrates a BASIC program which calls a FORTRAN
  2275.  subroutine. The FORTRAN subroutine then calls a BASIC function that returns
  2276.  twice the number passed it, and a BASIC subprogram that prints two numbers.
  2277.  
  2278.  ' BASIC source
  2279.  '
  2280.  DEFINT A-Z
  2281.  DECLARE SUB Fprog ()
  2282.  CALL Fprog
  2283.  END
  2284.  '
  2285.  FUNCTION Dbl(N) STATIC
  2286.      Dbl = N*2
  2287.  END FUNCTION
  2288.  '
  2289.  SUB Printnum(A,B) STATIC
  2290.      PRINT "The first number is ";A
  2291.      PRINT "The second number is ";B
  2292.  END SUB
  2293.  
  2294.  C       FORTRAN subroutine
  2295.  C         Calls a BASIC function that receives one integer,
  2296.  C           and a BASIC subprogram that takes two integers.
  2297.  C
  2298.          INTERFACE TO INTEGER*2 FUNCTION DBL (N)
  2299.          INTEGER*2 N [NEAR]
  2300.          END
  2301.  C
  2302.  C       ALIAS attribute necessary because BASIC recognizes more
  2303.  C         than six characters of the name "Printnum"
  2304.  C
  2305.          INTERFACE TO SUBROUTINE PRINTN [ALIAS:'Printnum'] (N1, N2)
  2306.          INTEGER*2 N1 [NEAR]
  2307.          INTEGER*2 N2 [NEAR]
  2308.          END
  2309.  C
  2310.  C       Parameters must be declared NEAR in the paramete
  2311.  C         declarations; BASIC receives ONLY 2-byte pointers
  2312.  C
  2313.          SUBROUTINE FPROG
  2314.          INTEGER*2 DBL
  2315.          INTEGER*2 A,B
  2316.          A = 5
  2317.          B = 6
  2318.          WRITE (*,*) 'Twice of 5 is ', DBL(A)
  2319.          CALL PRINTN(A,B)
  2320.          END
  2321.  
  2322.  In the example above, note that the NEAR attribute is used in the FORTRAN
  2323.  routines, so that near addresses will be passed to BASIC instead of far
  2324.  addresses.
  2325.  
  2326.  
  2327.                 BASIC code                           FORTRAN code
  2328.      ┌───────────────────────────────┐     ┌───────────────────────────────┐
  2329.      │                               │     │                               │
  2330.      │  (BASIC start-up)             │     │                               │
  2331.      │                               │     │                               │
  2332.      │                               │     │                               │
  2333.      │  CALL Fsub ─────────────┐     │     │                               │
  2334.      │  END                    │     │     │                               │
  2335.      │                         └─────┼─────┼─SUBROUTINE FSUB              │
  2336.      │  (BASIC termination)          │     │  .                            │
  2337.      │                               │     │  .                            │
  2338.      │                               │     │  .                            │
  2339.      │                         ┌─────┼─────┼──CALL BTEST                   │
  2340.      │                         │     │     │  .                            │
  2341.      │  SUB Btest STATIC ─────┘     │     │  .                            │
  2342.      │  .                            │     │  .                            │
  2343.      │  .                            │     │  RETURN                       │
  2344.      │  .                            │     │  END                          │
  2345.      │  END SUB                      │     │                               │
  2346.      │                               │     │                               │
  2347.      │                               │     │                               │
  2348.      └───────────────────────────────┘     └───────────────────────────────┘
  2349.  
  2350.  Figure 4.1  FORTRAN Call to BASIC
  2351.  
  2352.  
  2353.  4.4  FORTRAN Calls to C
  2354.  
  2355.  Writing FORTRAN interfaces to C is fairly straightforward; however, if you
  2356.  are using Version 4.0 of FORTRAN, then linking requires some additional
  2357.  steps, which are described in Chapter 1.
  2358.  
  2359.  This section applies the steps outlined in Section 4.1 to two examples of
  2360.  FORTRAN-C programs. A brief analysis follows each example.
  2361.  
  2362.  
  2363.  4.4.1  Calling C from FORTRAN--No Return Value
  2364.  
  2365.  The example below demonstrates a FORTRAN main module calling a C function,
  2366.  maxparam. This function returns no value but adjusts the lower of two
  2367.  parameters to equal the higher argument.
  2368.  
  2369.  
  2370.  ■  Example
  2371.  
  2372.  C   FORTRAN SOURCE FILE - CALLS C FUNCTION, NO RETURN VALUE
  2373.  C
  2374.          INTERFACE TO SUBROUTINE MAXPARAM[C,ALIAS:'_maxparam'](I,J)
  2375.          INTEGER*2 I [NEAR, REFERENCE]
  2376.          INTEGER*2 J [NEAR, REFERENCE]
  2377.          END
  2378.  C
  2379.  C   C ATTRIBUTE DIRECTS FORTRAN TO USE C CONVENTIONS
  2380.  C   ALIAS NECESSARY BECAUSE 'MAXPARAM' LONGER THAN 6 CHARS.
  2381.  C   EACH PARAMETER PASSED BY NEAR REFERENCE
  2382.  C
  2383.          INTEGER*2 I,J
  2384.          I = 5
  2385.          J = 7
  2386.          WRITE (*,*) 'I = ',I,' J = ', J
  2387.          CALL MAXPARAM(I,J)
  2388.          WRITE (*,*) 'I = ',I,' J = ', J
  2389.          END
  2390.  
  2391.  /* C source file */
  2392.  /* Compile in MEDIUM or LARGE memory model */
  2393.  /* Maxparam declared VOID because no return value */
  2394.  
  2395.  void maxparam(p1, p2)
  2396.  int near *p1;       /* Integer params received by near ref. */
  2397.  int near *p2;       /* NEAR keyword not needed in MEDIUM model */
  2398.  {
  2399.          if (*p1 > *p2)
  2400.                  *p2 = *p1;
  2401.          else
  2402.                  *p1 = *p2;
  2403.  }
  2404.  
  2405.  Naming conventions: By default, FORTRAN only places the first six
  2406.  characters of MAXPARAM into the object file, whereas C places all eight.
  2407.  This conflict is resolved with the ALIAS attribute: both modules place
  2408.  _maxparam (consistent with the C naming convention) into an object file.
  2409.  
  2410.  Calling conventions: The C attribute (in the INTERFACE statement) causes
  2411.  MAXPARAM to be called with the C calling convention, which pushes
  2412.  parameters in reverse order and specifies other lower-level differences.
  2413.  
  2414.  Parameter-passing methods: Since the function maxparam may alter the value
  2415.  of either parameter, both must be passed by reference. Near reference is
  2416.  implemented in FORTRAN with the NEAR and REFERENCE attributes, and in C by
  2417.  using near pointers. The REFERENCE attribute is necessary in FORTRAN
  2418.  because the C keyword changes the default passing method to pass
  2419.  by value.
  2420.  
  2421.  Far reference could have been specified by leaving off the NEAR keyword
  2422.  from the FORTRAN parameter declarations. In that case, the C module
  2423.  would need to use far pointers.
  2424.  
  2425.  
  2426.  4.4.2  Calling C from FORTRAN--Function Call
  2427.  
  2428.  The example below demonstrates a FORTRAN main module calling a C function,
  2429.  fact. This function returns the factorial of an integer value.
  2430.  
  2431.  
  2432.  ■  Example
  2433.  
  2434.  C   FORTRAN SOURCE FILE - CALLS C FUNCTION
  2435.  C
  2436.          INTERFACE TO INTEGER*2 FUNCTION FACT [C] (N)
  2437.          INTEGER*2 N
  2438.          END
  2439.  C
  2440.  C   C ATTRIBUTE DIRECTS FORTRAN TO USE C CONVENTIONS
  2441.  C   PARAMETER PASSED BY VALUE, WHICH IS DEFAULT WHEN
  2442.  C      C ATTRIBUTE IS IN USE
  2443.  C
  2444.          INTEGER*2 FACT
  2445.          INTEGER*2 I,J
  2446.          I = 3
  2447.          J = 4
  2448.          WRITE (*,*) 'The factorial of I   is ',FACT(I)
  2449.          WRITE (*,*) 'The factorial of J   is ',FACT(J)
  2450.          WRITE (*,*) 'The factorial of I+J is ',FACT(I+J)
  2451.          END
  2452.  
  2453.  /* C source file */
  2454.  /* Compile in MEDIUM or LARGE model */
  2455.  /* Factorial function, returning integer */
  2456.  
  2457.  int fact(n)
  2458.  int n;         /* Integer received by value, the C default */
  2459.  {
  2460.          int  result = 1;
  2461.  
  2462.          while (n)
  2463.                  result *= n--; /* Parameter n modified here */
  2464.          return (result);
  2465.  }
  2466.  
  2467.  Naming conventions: The C attribute (in the INTERFACE statement) causes
  2468.  FACT to be called with the C naming convention (as _fact). Word length is
  2469.  not a concern; fact does not exceed six characters.
  2470.  
  2471.  Calling conventions: The C attribute (in the INTERFACE statement) causes
  2472.  FACT to be called with the C calling convention, which pushes parameters in
  2473.  reverse order and specifies other lower-level differences.
  2474.  
  2475.  Parameter-passing methods: The C function above should receive the
  2476.  parameter by value. Otherwise, the function will corrupt the parameter's
  2477.  value in the calling module. Passing by value is the default method for C;
  2478.  it is also the default method for FORTRAN whenever the C attribute is in
  2479.  use.
  2480.  
  2481.  
  2482.  4.5  FORTRAN Calls to Pascal
  2483.  
  2484.  Calling Pascal from FORTRAN is usually fairly simple, because the PASCAL
  2485.  attribute causes FORTRAN to use the Pascal default of passing data by
  2486.  value.
  2487.  
  2488.  This section applies the steps outlined in Section 4.1 to two examples of
  2489.  FORTRAN-Pascal programs. A brief analysis follows each example.
  2490.  
  2491.  
  2492.  4.5.1  Calling Pascal from FORTRAN--Procedure Call
  2493.  
  2494.  The example below demonstrates a FORTRAN main module calling a Pascal
  2495.  procedure, Maxparam. This procedure adjusts the lower of two parameters to
  2496.  equal the higher argument.
  2497.  
  2498.  
  2499.  ■  Example
  2500.  
  2501.  C   FORTRAN SOURCE FILE - CALLS PASCAL PROCEDURE
  2502.  C
  2503.          INTERFACE TO SUBROUTINE MAXPARAM [ALIAS:'MAXPARAM'] (I,J)
  2504.          INTEGER*2 I [NEAR]
  2505.          INTEGER*2 J [NEAR]
  2506.          END
  2507.  C
  2508.  C   ALIAS NECESSARY BECAUSE 'MAXPARAM' LONGER THAN 6 CHARS.
  2509.  C   EACH PARAMETER PASSED BY NEAR REFERENCE
  2510.  C
  2511.          INTEGER*2 I,J
  2512.          I = 5
  2513.          J = 7
  2514.          WRITE (*,*) 'I = ',I,' J = ', J
  2515.          CALL MAXPARAM(I,J)
  2516.          WRITE (*,*) 'I = ',I,' J = ', J
  2517.          END
  2518.  
  2519.  { Pascal source code - Maxparam procedure. }
  2520.  
  2521.  module Psub;
  2522.   procedure Maxparam(var a:integer; var b:integer);
  2523.  
  2524.  { Two integer parameters are received by near reference. }
  2525.  { Near reference is specified with the VAR keyword. }
  2526.  
  2527.   begin
  2528.       if a > b then
  2529.           b := a
  2530.       else
  2531.           a := b
  2532.   end;
  2533.  end.
  2534.  
  2535.  Naming conventions: By default, FORTRAN only places the first six
  2536.  characters of MAXPARAM into the object file, whereas Pascal places all
  2537.  eight. The ALIAS attribute resolves this conflict: both modules place
  2538.  MAXPARAM into an object file.
  2539.  
  2540.  Calling conventions: FORTRAN and Pascal use the same convention for
  2541.  calling.
  2542.  
  2543.  Parameter-passing methods: Since the procedure Maxparam may alter the
  2544.  value of either parameter, both must be passed by reference. Near reference
  2545.  was implemented in FORTRAN with the NEAR attributes, and in Pascal with the
  2546.  VAR keyword. The PASCAL attribute is not used here because no parameter is
  2547.  being passed by value.
  2548.  
  2549.  Far reference could have been specified by leaving off the NEAR keyword
  2550.  from the FORTRAN parameter declarations. In that case, the Pascal module
  2551.  would use VARS instead of VAR.
  2552.  
  2553.  
  2554.  4.5.2  Calling Pascal from FORTRAN--Function Call
  2555.  
  2556.  The example below demonstrates a FORTRAN main module calling a Pascal func-
  2557.  tion, Fact. This function returns the factorial of an integer value.
  2558.  
  2559.  
  2560.  ■  Example
  2561.  
  2562.  C   FORTRAN SOURCE FILE - CALLS PASCAL FUNCTION
  2563.  C
  2564.          INTERFACE TO INTEGER*2 FUNCTION FACT [PASCAL] (N)
  2565.          INTEGER*2 N
  2566.          END
  2567.  C
  2568.  C   PARAMETER PASSED BY VALUE, WHICH IS DEFAULT WHEN
  2569.  C     PASCAL ATTRIBUTE IS IN USE
  2570.  C
  2571.          INTEGER*2 FACT
  2572.          INTEGER*2 I,J
  2573.          I = 3
  2574.          J = 4
  2575.          WRITE (*,*) 'The factorial of I   is ',FACT(I)
  2576.          WRITE (*,*) 'The factorial of J   is ',FACT(J)
  2577.          WRITE (*,*) 'The factorial of I+J is ',FACT(I+J)
  2578.          END
  2579.  
  2580.  { Pascal source code - factorial function. }
  2581.  
  2582.  module Pfun;
  2583.   function Fact (n : integer) : integer;
  2584.  
  2585.  {Integer parameters received by value, the Pascal default. }
  2586.  
  2587.   begin
  2588.      Fact := 1;
  2589.      while n > 0 do
  2590.          begin
  2591.              Fact := Fact * n;
  2592.              n := n - 1;           {Parameter n modified here.}
  2593.          end;
  2594.   end;
  2595.  end.
  2596.  
  2597.  Naming conventions: FORTRAN and Pascal use a similar naming convention.The
  2598.  ALIAS attribute is not necessary because the function name does not exceed
  2599.  six characters.
  2600.  
  2601.  Calling conventions: FORTRAN and Pascal use the same calling convention.
  2602.  
  2603.  Parameter-passing methods: The Pascal function above should receive the
  2604.  parameter by value. Otherwise, the function will corrupt the parameter's
  2605.  value in the calling module. Passing by value is the default method for
  2606.  Pascal; it is also the default method for FORTRAN whenever the PASCAL
  2607.  attribute is in use.
  2608.  
  2609.  
  2610.  
  2611.  CHAPTER 5  PASCAL CALLS TO HIGH-LEVEL LANGUAGES
  2612.  
  2613.  ───────────────────────────────────────────────────────────────────────────
  2614.  
  2615.  5.1  The Pascal Interface to Other Languages
  2616.  
  2617.  5.2  Alternative Pascal Interface to C
  2618.  
  2619.  5.3  Pascal Calls to BASIC
  2620.  
  2621.  5.4  Pascal Calls to C
  2622.  
  2623.        5.4.1  Calling C from Pascal--No Return Value
  2624.  
  2625.        5.4.2  Calling C from Pascal--Function Call
  2626.  
  2627.  5.5  Pascal Calls to FORTRAN
  2628.  
  2629.        5.5.1  Calling FORTRAN from Pascal--Subroutine Call
  2630.  
  2631.        5.5.2  Calling FORTRAN from Pascal--Function Call
  2632.  
  2633.  
  2634.  
  2635.  Microsoft Pascal supports calls to routines written in Microsoft
  2636.  FORTRAN and C. Also, if the main program is in BASIC, then a Pascal routine
  2637.  can call a BASIC routine. This chapter describes the necessary syntax for
  2638.  calling these other languages, and then gives examples for each language.
  2639.  Only simple parameter lists are used in this chapter.
  2640.  
  2641.  For information on how to pass particular kinds of data, consult Part 2,
  2642.  "Data Handling Reference." Chapter 9 describes how to use the VARYING
  2643.  attribute with Pascal to pass a varying number of parameters.
  2644.  
  2645.  
  2646.  5.1  The Pascal Interface to Other Languages
  2647.  
  2648.  You can provide an interface from Pascal to a routine in a different
  2649.  programming language. This interface is created by writing an extern
  2650.  function or procedure declaration. This declaration informs Pascal that the
  2651.  routine is to be found in another module; furthermore, you can use special
  2652.  keywords with the declaration to affect how Pascal makes calls to the
  2653.  routine. These keywords allow you to adjust naming conventions, calling
  2654.  conventions, and parameter-passing methods, so that the other language
  2655.  routines will be compatible with Pascal.
  2656.  
  2657.  Here are the recommended steps for writing an extern declaration:
  2658.  
  2659.    1.  Declare a function (for routines that return values) or a procedure
  2660.        (for routines that do not); all normal rules of Pascal syntax apply
  2661.        to the heading. Instead of writing a procedure body, however, simply
  2662.        type the word extern, followed by a semicolon (;).
  2663.  
  2664.        The extern can be placed in the procedure declaration section of any
  2665.        Pascal function or procedure that needs to call the different
  2666.        language routine.
  2667.  
  2668.    2.  If you are calling a C function, attach the C attribute to the
  2669.        declaration. To use this attribute, type C in brackets, at the very
  2670.        end of the function or procedure heading (immediately before the
  2671.        semicolon).
  2672.  
  2673.        This attribute directs Pascal to use the C naming and calling
  2674.        conventions. There is no similar keyword for FORTRAN or BASIC; they
  2675.        use the same naming and calling conventions used by Pascal.
  2676.  
  2677.    3.  Decide how you want to pass each parameter. By default Pascal passes
  2678.        parameters by value. The VAR keyword, applied to individual
  2679.        parameters, specifies passing by near reference, and the VARS keyword
  2680.        specifies passing by far reference.
  2681.  
  2682.    4.  Once the routine is properly declared, call it just as though it were
  2683.        a Pascal function or procedure.
  2684.  
  2685.  
  2686.  ■  Examples
  2687.  
  2688.  procedure Calc(var i:integer; x:real) [C]; extern;
  2689.  
  2690.  In the example above, the C attribute directs Pascal to use the C calling
  2691.  and naming conventions.
  2692.  
  2693.  function Quadratic(a,b,c : integer) : real [C]; extern;
  2694.  
  2695.  In this example also, the C attribute directs Pascal to use the C calling
  2696.  and naming conventions.
  2697.  
  2698.  procedure Total (a,b,c : integer, var sum : integer); extern;
  2699.  
  2700.  The third example, by default, uses the BASIC/FORTRAN/Pascal standard
  2701.  naming and calling conventions.
  2702.  
  2703.  
  2704.  5.2  Alternative Pascal Interface to C
  2705.  
  2706.  Instead of modifying the behavior of Pascal with the C attribute, you can
  2707.  modify the behavior of C by applying the pascal or fortran keyword to the
  2708.  function definition heading. (These two keywords are functionally
  2709.  equivalent.) You can also compile the C module with the /Gc option, which
  2710.  specifies that all C functions, calls, and public symbols use the
  2711.  BASIC/FORTRAN/Pascal conventions.
  2712.  
  2713.  
  2714.  ■  Example
  2715.  
  2716.  int pascal fun1(n)
  2717.  int n;
  2718.  
  2719.  In the example above, the C function uses the BASIC/FORTRAN/Pascal
  2720.  conventions to receive an integer parameter.
  2721.  
  2722.  
  2723.  5.3  Pascal Calls to BASIC
  2724.  
  2725.  Calls to BASIC from Pascal programs are not directly supported. No BASIC
  2726.  routine can be executed unless the main program is in BASIC because a BASIC
  2727.  routine requires the environment to be initialized in a unique way. No
  2728.  other language will perform this special initialization.
  2729.  
  2730.  However, it is possible for a program to start up in BASIC, call a Pascal
  2731.  routine that does most of the work of the program, and then call BASIC
  2732.  subprograms and function procedures as needed. The following diagram
  2733.  illustrates how this can be done:
  2734.  
  2735.  
  2736.                 BASIC code                           Pascal code
  2737.      ┌───────────────────────────────┐     ┌───────────────────────────────┐
  2738.      │                               │     │                               │
  2739.      │  (BASIC start-up)             │     │                               │
  2740.      │                               │     │                               │
  2741.      │                               │     │                               │
  2742.      │  CALL Psub ─────────────┐     │     │                               │
  2743.      │  END                    │     │     │                               │
  2744.      │                         └─────┼─────┼─PROCEDURE Psub;              │
  2745.      │  (BASIC termination)          │     │  .                            │
  2746.      │                               │     │  .                            │
  2747.      │                               │     │  .                            │
  2748.      │                         ┌─────┼─────┼──BTEST;                       │
  2749.      │                         │     │     │  .                            │
  2750.      │  SUB Btest STATIC ─────┘     │     │  .                            │
  2751.      │  .                            │     │  .                            │
  2752.      │  .                            │     │  END.                         │
  2753.      │  .                            │     │                               │
  2754.      │  END SUB                      │     │                               │
  2755.      │                               │     │                               │
  2756.      │                               │     │                               │
  2757.      └───────────────────────────────┘     └───────────────────────────────┘
  2758.  
  2759.  Figure 5.1  Pascal Call to BASIC
  2760.  
  2761.  
  2762.  Observe the following steps when calling BASIC from Pascal:
  2763.  
  2764.    1.  Start up in a BASIC main module. You will need to use QuickBASIC,
  2765.        Version 4.0 or later, and may want to use the DECLARE statement to
  2766.        write an interface to the principal Pascal routine. (See Chapter 2,
  2767.        "BASIC Calls to High-Level Languages," for additional information.)
  2768.  
  2769.    2.  Once in Pascal code, declare each BASIC routine you plan to call, in
  2770.        an extern procedure or function declaration.
  2771.  
  2772.    3.  Make sure that all data are passed as a near pointer, by declaring
  2773.        each argument with VAR. BASIC can pass data in a variety of ways, but
  2774.        is unable to receive data in any form other than as a near pointer.
  2775.  
  2776.        With near pointers, the program assumes that the data are in the
  2777.        default data segment. If you want to pass data that are not in the
  2778.        default data segment (this is only a consideration with far-heap
  2779.        allocation), then first copy the data to a variable that is in the
  2780.        default data segment.
  2781.  
  2782.  
  2783.  ■  Example
  2784.  
  2785.  The following example demonstrates a BASIC program which calls a Pascal
  2786.  procedure. The Pascal procedure then calls a BASIC function that returns
  2787.  twice the number passed it, and a BASIC subprogram that prints two numbers.
  2788.  
  2789.  ' BASIC source
  2790.  '
  2791.  DEFINT A-Z
  2792.  DECLARE SUB Pprog ()
  2793.  CALL Pprog
  2794.  END
  2795.  '
  2796.  FUNCTION Dbl(N) STATIC
  2797.      Dbl = N*2
  2798.  END FUNCTION
  2799.  '
  2800.  SUB Printnum(A,B) STATIC
  2801.      PRINT "The first number is ";A
  2802.      PRINT "The second number is ";B
  2803.  END SUB
  2804.  
  2805.  {* Pascal procedure *}
  2806.  {* Calls a BASIC function and a BASIC subprogram *}
  2807.  
  2808.  module pproc;
  2809.  procedure Pprog();
  2810.  
  2811.  function Dbl (var n:integer):integer; extern;
  2812.  procedure Printnum (var n1,n2:integer); extern;
  2813.  var a,b:integer;
  2814.  
  2815.      begin
  2816.          a := 5;
  2817.          b := 6;
  2818.          writeln ('Twice of 5 is ', Dbl(a));
  2819.          Printnum(a,b);
  2820.      end;
  2821.  end.
  2822.  
  2823.  In the example above, note that every argument in the external declarations
  2824.  must be declared VAR, since BASIC can only receive near pointers as
  2825.  parameters.
  2826.  
  2827.  
  2828.  5.4  Pascal Calls to C
  2829.  
  2830.  This section applies the steps outlined in Section 5.1 to two examples of
  2831.  Pascal-C programs. A brief analysis follows each example.
  2832.  
  2833.  
  2834.  5.4.1  Calling C from Pascal--No Return Value
  2835.  
  2836.  The example below demonstrates a Pascal main module calling a C function,
  2837.  maxparam. This function returns no value, but adjusts the lower of two
  2838.  arguments to equal the higher.
  2839.  
  2840.  
  2841.  ■  Example
  2842.  
  2843.  { Pascal source file - calls C function, no return value }
  2844.  
  2845.  program Pcsub (input, output);
  2846.  procedure Maxparam (var i,j : integer) [C]; extern;
  2847.  
  2848.  { C attribute directs Pascal to use C conventions. }
  2849.  { VAR indicates each parameter passed by near reference. }
  2850.  
  2851.  var
  2852.      a, b : integer;
  2853.  begin
  2854.      a := 5;
  2855.      b := 7;
  2856.      writeln('a = ',a,'b = ',b);
  2857.      Maxparam(a,b);
  2858.      writeln('a = ',a,'b = ',b);
  2859.  end.
  2860.  
  2861.  /* C source file */
  2862.  /* Compile in MEDIUM or LARGE memory model */
  2863.  /* Maxparam declared VOID because no return value */
  2864.  
  2865.  void maxparam(p1, p2)
  2866.  int near *p1;       /* Integer params received by near ref. */
  2867.  int near *p2;       /* NEAR keyword not needed in MEDIUM model */
  2868.  {
  2869.          if (*p1 > *p2)
  2870.                  *p2 = *p1;
  2871.          else
  2872.                  *p1 = *p2;
  2873.  }
  2874.  
  2875.  Naming conventions: The C attribute causes Maxparam to be called with the C
  2876.  naming convention (as _maxparam).
  2877.  
  2878.  Calling conventions: The C attribute causes Maxparam to be called with
  2879.  the C calling convention, which pushes parameters in reverse order.
  2880.  
  2881.  Parameter-passing methods: Since the subprogram Maxparam may alter the
  2882.  value of either parameter, both arguments must be passed by reference. In
  2883.  this case, near reference was chosen; this method is specified in Pascal
  2884.  with the VAR keyword, and in C by using near pointers.
  2885.  
  2886.  Far reference could have been specified by using VARS instead of VAR; in
  2887.  that case, the C parameter declarations would use far pointers.
  2888.  
  2889.  
  2890.  5.4.2  Calling C from Pascal--Function Call
  2891.  
  2892.  The example below demonstrates a Pascal main module calling a C function,
  2893.  fact. This function returns the factorial of an integer value.
  2894.  
  2895.  
  2896.  ■  Example
  2897.  
  2898.  { Pascal source file - calls C function }
  2899.  
  2900.  program Pcfun (input, output);
  2901.  function Fact (n : integer) [C]; extern;
  2902.  
  2903.  { C attribute directs Pascal to use C conventions. }
  2904.  { Parameter passed by value, the default method. }
  2905.  
  2906.  var
  2907.      a, b : integer;
  2908.  begin
  2909.      a := 3;
  2910.      b := 4;
  2911.      writeln('The factorial of a   is ', Fact(a));
  2912.      writeln('The factorial of b   is ', Fact(b));
  2913.      writeln('The factorial of a+b is ', Fact(a+b));
  2914.  end.
  2915.  
  2916.  /* C source file */
  2917.  /* Compile in MEDIUM or LARGE model */
  2918.  /* Factorial function, returning integer */
  2919.  
  2920.  int fact(n)
  2921.  int n;         /* Integer received by value, the C default */
  2922.  {
  2923.          int     result = 1;
  2924.  
  2925.          while (n)
  2926.                  result *= n--; /* Parameter n modified here */
  2927.          return (result);
  2928.  }
  2929.  
  2930.  Naming conventions: The C attribute causes Fact to be called with the C
  2931.  naming convention (as _fact).
  2932.  
  2933.  Calling conventions: The C attribute causes Fact to be called with the C
  2934.  calling convention, which pushes parameters in reverse order, and specifies
  2935.  other low-level differences.
  2936.  
  2937.  Parameter-passing methods: The C function should receive the integer
  2938.  parameter by value. Otherwise, the function will corrupt the value of the
  2939.  parameter in the calling routine. Passing by value is the default
  2940.  method for both Pascal and C.
  2941.  
  2942.  
  2943.  5.5  Pascal Calls to FORTRAN
  2944.  
  2945.  This section applies the steps outlined in Section 5.1 to two examples of
  2946.  Pascal-FORTRAN programs. A brief analysis follows each example.
  2947.  
  2948.  
  2949.  5.5.1  Calling FORTRAN from Pascal--Subroutine Call
  2950.  
  2951.  The example below demonstrates a Pascal main module calling a FORTRAN sub-
  2952.  routine, MAXPARAM. This subroutine adjusts the lower of two arguments to
  2953.  equal the higher.
  2954.  
  2955.  
  2956.  ■  Example
  2957.  
  2958.  { Pascal source file - calls FORTRAN subroutine }
  2959.  
  2960.  program Pfsub (output);
  2961.  procedure Maxpar (var i,j : integer) ; extern;
  2962.  
  2963.  { Name must not exceed six characters. }
  2964.  { VAR indicates each parameter passed by near reference. }
  2965.  
  2966.  var
  2967.      a, b : integer;
  2968.  begin
  2969.      a := 5;
  2970.      b := 7;
  2971.      writeln('a = ',a,'b = ',b);
  2972.      Maxpar(a,b);
  2973.      writeln('a = ',a,'b = ',b);
  2974.  end.
  2975.  
  2976.  C   FORTRAN source file, subroutine MAXPARAM
  2977.  C
  2978.          SUBROUTINE MAXPARAM (I, J)
  2979.          INTEGER*2 I [NEAR]
  2980.          INTEGER*2 J [NEAR]
  2981.  C
  2982.  C   I and J received by near reference, because of NEAR attribute
  2983.  C
  2984.          IF (I .GT. J) THEN
  2985.                  J = I
  2986.          ELSE
  2987.                  I = J
  2988.          ENDIF
  2989.          END
  2990.  
  2991.  Naming conventions: By default, Pascal places all eight characters of
  2992.  Maxparam into the object file, whereas FORTRAN places only the first six.
  2993.  This conflict is resolved by shortening the name of the Pascal routine to
  2994.  six characters.
  2995.  
  2996.  Calling conventions: Pascal and FORTRAN use the same calling convention.
  2997.  
  2998.  Parameter-passing methods: Since the subprogram Maxparam may alter the
  2999.  value of either parameter, both arguments must be passed by reference.
  3000.  In this case, near reference was chosen; this method is specified in Pascal
  3001.  with the VAR keyword, and in FORTRAN by applying the NEAR attribute to each
  3002.  parameter declaration.
  3003.  
  3004.  Far reference could have been chosen by using VARS instead of VAR. In that
  3005.  case, the NEAR attribute would not be used in the FORTRAN parameter
  3006.  declarations.
  3007.  
  3008.  
  3009.  5.5.2  Calling FORTRAN from Pascal--Function Call
  3010.  
  3011.  The example below demonstrates a Pascal main module calling a FORTRAN func-
  3012.  tion, FACT. This function returns the factorial of an integer value.
  3013.  
  3014.  
  3015.  ■  Example
  3016.  
  3017.  { Pascal source file - calls FORTRAN function }
  3018.  
  3019.  program Pffun (output);
  3020.  function Fact (n : integer); extern;
  3021.  
  3022.  { Parameter passed by value, the default method. }
  3023.  
  3024.  var
  3025.      a, b : integer;
  3026.  begin
  3027.      a := 3;
  3028.      b := 4;
  3029.      writeln('The factorial of a   is ', Fact(a));
  3030.      writeln('The factorial of b   is ', Fact(b));
  3031.      writeln('The factorial of a+b is ', Fact(a+b));
  3032.  end.
  3033.  
  3034.  C   FORTRAN source file - factorial function
  3035.  C
  3036.          INTEGER*2 FUNCTION FACT (N)
  3037.          INTEGER*2 N [VALUE]
  3038.  C
  3039.  C   N is received by value, because of VALUE attribute
  3040.  C
  3041.          INTEGER*2 I
  3042.          FACT = 1
  3043.          DO 100 I = 1, N
  3044.              FACT = FACT * I
  3045.    100       CONTINUE
  3046.          RETURN
  3047.          END
  3048.  
  3049.  Naming conventions: There are no conflicts with naming conventions, because
  3050.  the function name (FACT) does not exceed six characters.
  3051.  
  3052.  Calling conventions: Pascal and FORTRAN use the same convention for
  3053.  calling.
  3054.  
  3055.  Parameter-passing methods: When passing a parameter that should not be
  3056.  changed, it is generally safest to pass the parameter by value. Passing by
  3057.  value is the default method in Pascal, and is specified in FORTRAN by
  3058.  applying the VALUE attribute to a parameter declaration.
  3059.  
  3060.  
  3061.  
  3062.  CHAPTER 6  ASSEMBLY-TO-HIGH-LEVEL INTERFACE
  3063.  
  3064.  ───────────────────────────────────────────────────────────────────────────
  3065.  
  3066.  6.1  Writing the Assembly Procedure
  3067.  
  3068.        6.1.1  Setting Up the Procedure
  3069.  
  3070.        6.1.2  Entering the Procedure
  3071.  
  3072.        6.1.3  Allocating Local Data (Optional)
  3073.  
  3074.        6.1.4  Preserving Register Values
  3075.  
  3076.        6.1.5  Accessing Parameters
  3077.  
  3078.        6.1.6  Returning a Value (Optional)
  3079.  
  3080.        6.1.7  Exiting the Procedure
  3081.  
  3082.  6.2  Calls from BASIC
  3083.  
  3084.  6.3  Calls from C
  3085.  
  3086.  6.4  Calls from FORTRAN
  3087.  
  3088.  6.5  Calls from Pascal
  3089.  
  3090.  6.6  Calling High-Level Languages from Assembly
  3091.  
  3092.  6.7  The Microsoft Segment Model
  3093.  
  3094.  
  3095.  
  3096.  With the Microsoft Macro Assembler you can write assembly modules that
  3097.  can be linked to modules developed with Microsoft BASIC, C, Pascal, or
  3098.  FORTRAN. This chapter first outlines the recommended programming guidelines
  3099.  for writing assembly routines compatible with Microsoft high-level
  3100.  languages; it then gives examples specific to each language.
  3101.  
  3102.  Writing assembly routines for Microsoft high-level languages is easiest
  3103.  when you use the simplified segment directives provided with the Macro
  3104.  Assembler, Version 5.0. In general, this manual assumes that you have
  3105.  Version 5.0. For information on writing assembly-language interfaces
  3106.  without the simplified segment directives, turn to Section 6.7 in order to
  3107.  look up SEGMENT, GROUP, and ASSUME statements.
  3108.  
  3109.  
  3110.  6.1  Writing the Assembly Procedure
  3111.  
  3112.  The Microsoft BASIC, C, FORTRAN, and Pascal compilers use roughly the same
  3113.  interface for procedure calls. This section describes the interface, so
  3114.  that you can call assembly procedures using essentially the same methods as
  3115.  Microsoft compiler-generated code. Procedures written with these methods
  3116.  can be called recursively and can be effectively used with the Stack Trace
  3117.  feature of the Microsoft CodeView(R) debugger.
  3118.  
  3119.  The standard assembly-interface method consists of these steps:
  3120.  
  3121.    ■  Setting up the procedure
  3122.  
  3123.    ■  Entering the procedure
  3124.  
  3125.    ■  Allocating local data (optional)
  3126.  
  3127.    ■  Preserving register values
  3128.  
  3129.    ■  Accessing parameters
  3130.  
  3131.    ■  Returning a value (optional)
  3132.  
  3133.    ■  Exiting the procedure
  3134.  
  3135.  Sections 6.1.1-6.1.7 describe each of these steps.
  3136.  
  3137.  
  3138.  6.1.1  Setting Up the Procedure
  3139.  
  3140.  The linker cannot combine the assembly procedure with the calling program
  3141.  unless compatible segments are used and unless the procedure itself is
  3142.  declared properly. The following points may be helpful:
  3143.  
  3144.    1.  Use the .MODEL directive at the beginning of the source file, if you
  3145.        have Version 5.0 of the Macro Assembler; this directive automatically
  3146.        causes the appropriate kind of returns to be generated (NEAR for
  3147.        small or compact model, FAR otherwise). Modules called from Pascal
  3148.        should be declared as .MODEL LARGE; modules called from BASIC should
  3149.        be .MODEL MEDIUM. If you have a version of the assembler previous to
  3150.        5.0, declare the procedure FAR (or NEAR if the calling program is
  3151.        small- or compact-model C).
  3152.  
  3153.    2.  If you have Version 5.0 or later of the Microsoft Macro Assembler,
  3154.        use the simplified segment directives .CODE to declare the code
  3155.        segment and .DATA to declare the data segment. (Having a code segment
  3156.        is sufficient if you do not have data declarations.) If you are using
  3157.        an earlier version of the assembler, look up SEGMENT, GROUP, and
  3158.        ASSUME directives in Section 6.7, "The Microsoft Segment Model."
  3159.  
  3160.    3.  The procedure label must be declared public with the PUBLIC
  3161.        directive. This declaration makes the procedure available to be
  3162.        called by other modules. Also, any data you want to make public to
  3163.        other modules must be declared as PUBLIC.
  3164.  
  3165.    4.  Global data or procedures accessed by the routine must be declared
  3166.        EXTRN. The safest way to use EXTRN is to place the directive outside
  3167.        of any segment definition (however, near data should generally go
  3168.        inside the data segment).
  3169.  
  3170.  
  3171.  6.1.2  Entering the Procedure
  3172.  
  3173.  Two instructions begin the procedure:
  3174.  
  3175.            push    bp
  3176.            mov     bp,sp
  3177.  
  3178.  This sequence establishes BP as the "framepointer." The framepointer is
  3179.  used to access parameters and local data, which are located on the stack.
  3180.  SP cannot be used for this purpose because it is not an index or base
  3181.  register. Also, the value of SP may change as more data are pushed onto
  3182.  the stack. However, the value of the base register BP will remain constant
  3183.  throughout the procedure, so that each parameter can be addressed as a
  3184.  fixed displacement off of BP.
  3185.  
  3186.  The instruction sequence above first saves the value of BP, since it will
  3187.  be needed by the calling procedure as soon as the current procedure
  3188.  terminates. Then BP is loaded with the value of SP in order to capture the
  3189.  value of the stack pointer at the time of entry to the procedure.
  3190.  
  3191.  
  3192.  6.1.3  Allocating Local Data (Optional)
  3193.  
  3194.  An assembly procedure can use the same technique for implementing local
  3195.  data that is used by high-level languages. To set up local data space,
  3196.  simply decrease the contents of SP in the third instruction of the
  3197.  procedure. (To ensure correct execution, you should always increase or
  3198.  decrease SP by an even amount.) Decreasing SP reserves space on the stack
  3199.  for the local data. The space must be restored at the end of the procedure.
  3200.  
  3201.            push    bp
  3202.            mov     bp,sp
  3203.            sub     sp,space
  3204.  
  3205.  In the text above, space is the total size in bytes of the local data.
  3206.  Local variables are then accessed as fixed, negative displacements off of
  3207.  BP.
  3208.  
  3209.  
  3210.  ■  Example
  3211.  
  3212.            push    bp
  3213.            mov     bp,sp
  3214.            sub     sp,4
  3215.            .
  3216.            .
  3217.            .
  3218.            mov     WORD PTR [bp-2],0
  3219.            mov     WORD PTR [bp-4],0
  3220.  
  3221.  The example above uses two local variables, each of which is two bytes in
  3222.  size. SP is decreased by 4, since there are four bytes total of local data.
  3223.  Later, each of the variables is initialized to 0. These variables are never
  3224.  formally declared with any assembler directive; the programmer must keep
  3225.  track of them manually.
  3226.  
  3227.  Local variables are also called dynamic, stack, or automatic variables.
  3228.  
  3229.  
  3230.  6.1.4  Preserving Register Values
  3231.  
  3232.  A procedure called from any of the Microsoft high-level languages should
  3233.  preserve the values of SI, DI, SS, and DS (in addition to BP, which is
  3234.  already saved). Therefore, push any of these register values that the pro-
  3235.  cedure alters. If the procedure does not change the value of any of these
  3236.  registers, then the registers do not need to be pushed.
  3237.  
  3238.  The recommended method (used by the high-level languages) is to save
  3239.  registers after the framepointer is set and local data (if any) are allo-
  3240.  cated.
  3241.  
  3242.            push    bp           ; Save old framepointer
  3243.            mov     bp,sp        ; Establish current framepointer
  3244.            sub     sp,4         ; Allocate local data space
  3245.            push    si           ; Save SI and DI
  3246.            push    di
  3247.            .
  3248.            .
  3249.            .
  3250.  
  3251.  In the example above, DI and SI (in that order) must be popped before the
  3252.  end of the procedure.
  3253.  
  3254.  
  3255.  6.1.5  Accessing Parameters
  3256.  
  3257.  Once you have established the procedure's framepointer, allocated local
  3258.  data space (if desired), and pushed any registers that need to be
  3259.  preserved, you can write the main body of the procedure. In order to write
  3260.  instructions that can access parameters, consider the general picture of
  3261.  the stack frame after a procedure call as illustrated in Figure 6.1.
  3262.  
  3263.  The stack frame for the procedure is established by the following sequence
  3264.  of events:
  3265.  
  3266.    1.  The calling program pushes each of the parameters on the stack, after
  3267.        which SP points to the last parameter pushed.
  3268.  
  3269.    2.  The calling program issues a CALL instruction, which causes the
  3270.        return address (the place in the calling program to which control
  3271.        will ultimately return) to be placed on the stack. This address may
  3272.        be either two bytes long (for near calls) or four bytes long (for far
  3273.        calls). SP now points to this address.
  3274.  
  3275.    3.  The first instruction of the called procedure saves the old value of
  3276.        BP, with the instruction push bp. SP now points to the saved copy of
  3277.        BP.
  3278.  
  3279.    4.  BP is used to capture the current value of SP, with the instruction
  3280.        mov bp,sp. BP therefore now points to the old value of BP.
  3281.  
  3282.    5.  Whereas BP remains constant throughout the procedure, SP may be
  3283.        decreased to provide room on the stack, for local data or saved
  3284.        registers.
  3285.  
  3286.  In general, the displacement (off of BP) for a parameter X is equal to:
  3287.  
  3288.       2 + size of return address
  3289.         + total size of parameters between X and BP
  3290.  
  3291.  For example, consider a FAR procedure that has received one parameter, a
  3292.  two-byte address. The displacement of the parameter would be:
  3293.  
  3294.       Argument's displacement =  2 + size of return address
  3295.                               =  2 + 4
  3296.                               =  6
  3297.  
  3298.  The argument can thus be loaded into BX with the following instruction:
  3299.  
  3300.            mov     bx,[bp+6]
  3301.  
  3302.  Once you determine the displacement of each parameter, you may want to use
  3303.  string equates or structures so that the parameter can be referenced with a
  3304.  single identifier name in your assembly source code. For example, the
  3305.  parameter above at BP+6 can be conveniently accessed if you put the follow-
  3306.  ing statement at the beginning of the assembly source file:
  3307.  
  3308.  Arg1      EQU     [bp+6]
  3309.  
  3310.  You could then refer to this parameter as Arg1 in any instruction. Use of
  3311.  this feature is optional.
  3312.  
  3313.  
  3314.                     High addresses
  3315.  
  3316.                         ┌═══════════════════╗
  3317.                         │     Parameter     ║
  3318.                         ├───────────────────╢
  3319.                         │     Parameter     ║
  3320.                         ├───────────────────╢
  3321.                         │          .        ║
  3322.                         │          .        ║
  3323.                         │          .        ║
  3324.                         ├───────────────────╢
  3325.       (Stack grows      │      Parameter    ║
  3326.       downward with     ├───────────────────╢
  3327.       each push or      │   Return address  ║
  3328.       call.)            ├───────────────────╢
  3329.                         │      Saved BP     ║ ─ Framepointer (BP)
  3330.             │           ├───────────────────╢    points here.
  3331.             │           │  Local data space ║
  3332.                        ├───────────────────╢
  3333.                         │      Saved SI     ║
  3334.                         ├───────────────────╢
  3335.                         │      Saved DI     ║ ─ SP points to last item
  3336.                         └───────────────────╜    placed on stack.
  3337.  
  3338.                     Low addresses
  3339.  
  3340.  Figure 6.1  The Stack Frame
  3341.  
  3342.  
  3343.  ───────────────────────────────────────────────────────────────────────────
  3344.  Note
  3345.    Microsoft high-level languages always push segment addresses before push-
  3346.    ing offset address. Furthermore, when pushing arguments larger than two
  3347.    bytes, high-order words are always pushed before low-order words.
  3348.  
  3349.    This standard for pushing segment addresses before pushing offset
  3350.    addresses facilitates the use of the LES instruction, as demonstrated in
  3351.    Section 6.4, "Calls from FORTRAN."
  3352.  ───────────────────────────────────────────────────────────────────────────
  3353.  
  3354.  
  3355.  6.1.6  Returning a Value (Optional)
  3356.  
  3357.  Microsoft BASIC, C, FORTRAN, and Pascal share similar conventions for
  3358.  receiving return values. The conventions are the same when the data type to
  3359.  be returned is simple (that is, not an array or structured type) and is no
  3360.  more than four bytes long. This includes all NEAR and FAR address types (in
  3361.  other words, all pointers and all parameters passed by reference).
  3362.  
  3363.    Data size        Returned in register
  3364.    ────────────────────────────────────────────────────────────────────────
  3365.    1 byte           AL
  3366.    2 bytes          AX
  3367.    4 bytes          High-order portion (or segment address) in DX;
  3368.                     low-order portion (or offset address) in AX
  3369.  
  3370.  When the return value is larger than four bytes, a procedure called by C
  3371.  must allocate space for the return value and then place its address in
  3372.  DX:AX. A convenient way to create space for the return value is to simply
  3373.  declare it in a data segment.
  3374.  
  3375.  If your assembly procedure is called by BASIC, FORTRAN or Pascal, then it
  3376.  must use a special convention in order to return floating-point values,
  3377.  records, user-defined types and arrays, and values larger than four bytes.
  3378.  This convention is presented below.
  3379.  
  3380.  
  3381.  ■  BASIC/FORTRAN/Pascal Long Return Values
  3382.  
  3383.  In order to create an interface for long return values, BASIC, FORTRAN and
  3384.  Pascal modules take the following actions before they call your procedure:
  3385.  
  3386.    1.  First they create space, somewhere in the stack segment, to hold the
  3387.        actual return value.
  3388.  
  3389.    2.  When the call to your procedure is made, an extra parameter is
  3390.        passed; this parameter contains the offset address of the actual
  3391.        return value. This parameter is placed immediately above the return
  3392.        address. (In other words, this parameter is the last one pushed.)
  3393.  
  3394.    3.  The segment address of the return value is contained in both SS
  3395.        and DS.
  3396.  
  3397.  The extra parameter (which contains the offset address of the return value)
  3398.  is always located at BP+6. Furthermore, its presence automatically
  3399.  increases the displacement of all other parameters by two, as shown in the
  3400.  following comparison:
  3401.  
  3402.  
  3403.       BASIC, FORTRAN, Pascal stack     BASIC, FORTRAN, Pascal stack
  3404.       without long return value        with long return value
  3405.  
  3406.       ┌═══════════════════╗                ┌═══════════════════╗
  3407.       │     Parameter     ║─ BP + 6       │     Parameter     ║─ BP + 8
  3408.       ├───────────────────╢                ├───────────────────╢
  3409.       │                   ║                │Return value offset║─ BP + 6
  3410.       │  Return address   ║      BP + 4    ├───────────────────╢
  3411.       │     (4 bytes)     ║                │                   ║      BP + 4
  3412.       │                   ║      BP + 2    │  Return address   ║
  3413.       ├───────────────────╢                │     (4 bytes)     ║      BP + 2
  3414.       │     Saved BP      ║─ BP           │                   ║
  3415.       └───────────────────╜                ├───────────────────╢
  3416.                                            │     Saved BP      ║─ BP
  3417.                                            └───────────────────╜
  3418.  
  3419.  Figure 6.2  BASIC/FORTRAN/Pascal Long Return Values
  3420.  
  3421.  
  3422.  Your assembly procedure will successfully return a long value if you follow
  3423.  these steps:
  3424.  
  3425.    1.  Put the data for the return value at the location pointed to by the
  3426.        return value offset.
  3427.  
  3428.    2.  Copy the return-value offset (located at BP+6) to AX, and copy SS to
  3429.        DX. This is necessary because the calling module expects DX:AX to
  3430.        point to the return value.
  3431.  
  3432.    3.  Exit the procedure as described in the next section.
  3433.  
  3434.  
  3435.  6.1.7  Exiting the Procedure
  3436.  
  3437.  Several steps may be involved in terminating the procedure:
  3438.  
  3439.    1.  If any of the registers SS, DS, SI, or DI have been saved, these must
  3440.        be popped off the stack in the reverse order that they were saved.
  3441.  
  3442.    2.  If local data space was allocated at the beginning of the procedure,
  3443.        SP must be restored with the instruction mov sp,bp.
  3444.  
  3445.    3.  Restore BP with pop bp. This step is always necessary.
  3446.  
  3447.    4.  Finally, return to the calling program with ret. If the BASIC,
  3448.        FORTRAN, or Pascal calling convention is in use, then use the ret n
  3449.        form of the instruction to adjust the stack with respect to the
  3450.        parameters that were pushed by the caller. (If the procedure is
  3451.        called by a C module, then the calling module will perform this
  3452.        adjustment.)
  3453.  
  3454.  
  3455.  ■  Examples
  3456.  
  3457.            pop     bp
  3458.            ret
  3459.  
  3460.  The example above shows the simplest possible exit sequence. No registers
  3461.  were saved, no local data space was allocated, and the C calling convention
  3462.  is in use.
  3463.  
  3464.            pop     di           ; Pop saved regs
  3465.            pop     si
  3466.                 mov     sp,bp        ; Remove local data space
  3467.            pop     bp           ; Restore old framepointer
  3468.            ret     6            ; Exit, and restore 6 byte of args
  3469.  
  3470.  The example above shows an exit sequence for a procedure that has
  3471.  previously saved SI and DI, allocated local data space, and uses a non-C
  3472.  calling convention. The procedure must therefore use ret 6 to restore the
  3473.  six bytes of parameters on the stack.
  3474.  
  3475.  
  3476.  6.2  Calls from BASIC
  3477.  
  3478.  A BASIC program can call an assembly procedure in another source file with
  3479.  the use of the CALL, CALLS, or DECLARE statement. In addition to the steps
  3480.  outlined in Section 6.1, "Writing the Assembly Procedure," the following
  3481.  guidelines may be helpful:
  3482.  
  3483.    1.  Declare procedures called from BASIC as FAR.
  3484.  
  3485.    2.  Observe the BASIC calling convention.
  3486.  
  3487.        a.  Upon exit, the procedure must reset SP to the value it had before
  3488.            the parameters were placed on the stack. This is accomplished
  3489.            with the instruction ret size, where size is the total size in
  3490.            bytes of all the parameters.
  3491.  
  3492.        b.  Parameters are placed on the stack in the same order in which
  3493.            they appear in the BASIC source code. The first parameter will be
  3494.            highest in memory (because it is also the first parameter to be
  3495.            placed on the stack, and the stack grows downward).
  3496.  
  3497.        c.  By default, BASIC parameters are passed by reference as two-byte
  3498.            addresses.
  3499.  
  3500.    3.  Observe the BASIC naming convention.
  3501.  
  3502.        BASIC outputs symbolic names in uppercase characters, which is also
  3503.        the default behavior of the assembler. BASIC recognizes up to 40
  3504.        characters of a name, whereas the assembler recognizes only the
  3505.        first 31, but this should rarely create a problem.
  3506.  
  3507.  In the following example program, QuickBASIC 4.0 calls an assembly
  3508.  procedure that calculates "A x 2^B," where A and B are the first and second
  3509.  parameters, respectively.  The calculation is performed by shifting the
  3510.  bits in A to the left, B times. (Note: with earlier versions of BASIC, you
  3511.  need to rewrite the example so that it calls a subprogram, not a function.)
  3512.  
  3513.  DEFINT A-Z
  3514.  PRINT "3 times 2 to the power of 5 is ";
  3515.  PRINT Power2(3,5)
  3516.  END
  3517.  
  3518.  To understand how to write the assembly procedure, consider how the
  3519.  parameters are placed on the stack:
  3520.  
  3521.  
  3522.                       High addresses
  3523.  
  3524.                           ┌═══════════════════╗
  3525.                        A  │   Arg 1 address   ║─ BP + 8
  3526.       (Stack grows        ├───────────────────╢
  3527.       downward with    B  │   Arg 2 address   ║─ BP + 6
  3528.       each push or        ├───────────────────╢
  3529.       call.)              │                   ║      BP + 4
  3530.                           │  Return address   ║
  3531.             │             │     (4 bytes)     ║      BP + 2
  3532.             │             │                   ║
  3533.                          ├───────────────────╢
  3534.                           │     Saved BP      ║─ BP
  3535.                           └───────────────────╜
  3536.  
  3537.                       Low addresses
  3538.  
  3539.  Figure 6.3  BASIC Stack Frame
  3540.  
  3541.  
  3542.  The return address is four bytes long because procedures called from BASIC
  3543.  must be FAR. Arg 1 (parameter 1) is higher in memory than Arg 2 because
  3544.  BASIC pushes arguments (parameters) in the same order in which they appear.
  3545.  Also, each argument is passed as a two-byte offset address, the BASIC
  3546.  default.
  3547.  
  3548.  The assembly procedure can be written as follows:
  3549.  
  3550.  .MODEL MEDIUM
  3551.  .CODE
  3552.            PUBLIC  Power2
  3553.  Power2    PROC
  3554.            push    bp              ; Entry sequence - saved old BP
  3555.            mov     bp,sp           ; Set stack framepointer
  3556.  
  3557.            mov     bx,[bp+8]       ; Load Arg1 into
  3558.            mov     ax,[bx]         ;   AX
  3559.            mov     bx,[bp+6]       ; Load Arg2 into
  3560.            mov     cx,[bx]         ;   CX
  3561.            shl     ax,cl           ; AX = AX * (2 to power of CX)
  3562.                                    ; Leave return value in AX
  3563.  
  3564.            pop     bp              ; Exit sequence - restore old BP
  3565.            ret     4               ; Return, and restore 4 bytes
  3566.  Power2    ENDP
  3567.            END
  3568.  
  3569.  Note that each parameter must be loaded in a two-step process because the
  3570.  address of each is passed rather than the value. Also, note that the stack
  3571.  is restored with the instruction ret 4 since the total size of the
  3572.  parameters is four bytes.
  3573.  
  3574.  
  3575.  6.3  Calls from C
  3576.  
  3577.  A C program can call an assembly procedure in another module, just as it
  3578.  would call a C function. In addition to the steps outlined in Section 6.1,
  3579.  "Writing the Assembly Procedure," the following guidelines may prove
  3580.  helpful:
  3581.  
  3582.    1.  Declare procedures called from C as FAR if the C module is compiled
  3583.        in large, huge, or medium model, and NEAR if the C module is compiled
  3584.        in small or compact model (although the near and far keywords can
  3585.        override these defaults). The correct declaration for the procedure
  3586.        is made implicitly when you use the .MODEL directive available in the
  3587.        Microsoft Macro Assembler, Version 5.0.
  3588.  
  3589.    2.  Observe the C calling convention.
  3590.  
  3591.        a.  Return with a simple ret instruction. Do not restore the stack
  3592.            with ret size, since the calling C routine will restore the stack
  3593.            itself, as soon as it resumes control.
  3594.  
  3595.        b.  Parameters are placed on the stack in the reverse order that they
  3596.            appear in the C source code. The first parameter will be lowest
  3597.            in memory (because it is the last parameter to placed on the
  3598.            stack, and the stack grows downward).
  3599.  
  3600.        c.  By default, C parameters are passed by value, except for arrays,
  3601.            which are passed by reference.
  3602.  
  3603.    3.  Observe the C naming convention.
  3604.  
  3605.        Include an underscore in front of any name which will be shared
  3606.        publicly with C. C recognizes only the first eight characters of any
  3607.        name, so do not make names shared with C longer than eight
  3608.        characters. Also, if you plan to link with the /NOIGNORECASE option,
  3609.        remember that C is case sensitive and does not convert names to
  3610.        uppercase. Assemble with the /MX option to prevent MASM from
  3611.        converting names to uppercase.
  3612.  
  3613.  In the following example program, C calls an assembly procedure that
  3614.  calculates "A x 2^B," where A and B are the first and second parameters,
  3615.  respectively. The calculation is performed by shifting the bits in A to
  3616.  the left, B times.
  3617.  
  3618.  The C program uses an extern declaration to create an interface with the
  3619.  assembly procedure. No special keywords are required because the assembly
  3620.  procedure will use the C calling convention.
  3621.  
  3622.  extern int power2(int, int);
  3623.  
  3624.  main()
  3625.  {
  3626.      printf("3 times 2 to the power of 5 is %d\n", power2(3,5));
  3627.  }
  3628.  
  3629.  To understand how to write the assembly procedure, consider how the
  3630.  parameters are placed on the stack, as illustrated in Figure 6.4.
  3631.  
  3632.  
  3633.                       High addresses
  3634.  
  3635.                           ┌═══════════════════╗
  3636.                        B  │       Arg 2       ║─ BP + 6
  3637.       (Stack grows        ├───────────────────╢
  3638.       downward with    A  │       Arg 1       ║─ BP + 4
  3639.       each push or        ├───────────────────╢
  3640.       call.)              │  Return address   ║      BP + 2
  3641.                           ├───────────────────╢
  3642.             │             │     Saved BP      ║─ BP
  3643.             │             └───────────────────╜
  3644.  
  3645.                       Low addresses
  3646.  
  3647.  Figure 6.4  C Stack Frame
  3648.  
  3649.  
  3650.  The return address is two bytes long, assuming that the C module is
  3651.  compiled in small or compact model. If the C module is compiled in large,
  3652.  huge, or medium model, then the addresses of Arg 1 and Arg 2 are each
  3653.  increased by two, to BP+6 and BP+8, respectively, because the return
  3654.  address will be four bytes long.
  3655.  
  3656.  Arg 1 (parameter 1) is lower in memory than Arg 2, because C pushes
  3657.  arguments in the reverse order that they appear. Each argument is passed by
  3658.  value.
  3659.  
  3660.  The assembly procedure can be written as follows:
  3661.  
  3662.  .MODEL SMALL
  3663.  .CODE
  3664.            PUBLIC  _power2
  3665.  _power2   PROC
  3666.            push    bp             ; Entry sequence - save old BP
  3667.            mov     bp,sp          ; Set stack framepointer
  3668.  
  3669.            mov     ax,[bp+4]      ; Load Arg1 into AX
  3670.            mov     cx,[bp+6]      ; Load Arg2 into CX
  3671.            shl     ax,cl          ; AX = AX * (2 to power of CX)
  3672.                                   ; Leave return value in AX
  3673.  
  3674.            pop     bp             ; Exit sequence - restore old BP
  3675.            ret                    ; Return
  3676.  _power2   ENDP
  3677.            END
  3678.  
  3679.  The example above assumes that the C module is compiled in small model. The
  3680.  parameter offsets and the .MODEL directive will change for different
  3681.  models.
  3682.  
  3683.  Note that ret without a size variable is used, since the caller will
  3684.  adjust the stack upon return from the call.
  3685.  
  3686.  
  3687.  6.4  Calls from FORTRAN
  3688.  
  3689.  A FORTRAN program can call an external assembly procedure with the use of
  3690.  the INTERFACE statement. However, the INTERFACE statement is not strictly
  3691.  necessary unless you intend to change one of the FORTRAN defaults. In
  3692.  addition to the steps outlined in Section 6.1, "Writing the Assembly
  3693.  Procedure," the following guidelines may be helpful:
  3694.  
  3695.    1.  Declare procedures called from FORTRAN as FAR.
  3696.  
  3697.    2.  Observe the FORTRAN calling convention.
  3698.  
  3699.        a.  Upon exit, the procedure must reset SP to the value it had before
  3700.            the arguments were placed on the stack. This is accomplished with
  3701.            the instruction ret size, where size is the total size of all the
  3702.            parameters.
  3703.  
  3704.        b.  Arguments are placed on the stack in the same order in which they
  3705.            appear in the FORTRAN source code. The first parameter will be
  3706.            highest in memory (because it is also the first parameter to be
  3707.            placed on the stack, and the stack grows downward).
  3708.  
  3709.        c.  By default, FORTRAN parameters are passed by reference as far
  3710.            addresses if the FORTRAN module is compiled in large or huge
  3711.            memory model, and as near addresses if the FORTRAN module is
  3712.            compiled in medium model. Versions of FORTRAN prior to Version
  3713.            4.0 are always large model.
  3714.  
  3715.    3.  Observe the FORTRAN naming convention.
  3716.  
  3717.        FORTRAN only recognizes the first 6 characters of any name, while the
  3718.        assembler recognizes the first 31. Names shared publicly with FORTRAN
  3719.        should not be longer than 6 characters, unless the FORTRAN module is
  3720.        using the ALIAS feature.
  3721.  
  3722.  In the following example, FORTRAN calls an assembly procedure that
  3723.  calculates "A x 2B," where A and B are the first and second parameters,
  3724.  respectively. This is done by shifting the bits in A to the left, B times.
  3725.  
  3726.  The FORTRAN module uses the INTERFACE statement, which is described in
  3727.  Section 4.1, "The FORTRAN Interface to Other Languages."
  3728.  
  3729.            INTERFACE TO INTEGER*2 POWER2(A,B)
  3730.            INTEGER*2 A,B
  3731.            END
  3732.  C
  3733.            INTEGER*2 A,B
  3734.            A = 3
  3735.            B = 5
  3736.            WRITE (*,*) '3 times 2 to the power of 5 is ',POWER2(A,B)
  3737.            END
  3738.  
  3739.  To understand how to write the assembly procedure, consider how the
  3740.  parameters are placed on the stack, as illustrated in Figure 6.5.
  3741.  
  3742.  Figure 6.5 assumes large-model FORTRAN. If you compile the FORTRAN module
  3743.  in medium model, then each argument will be passed as a two-byte, not
  3744.  four-byte address. The return address is four bytes long because procedures
  3745.  called from FORTRAN must always be FAR.
  3746.  
  3747.  Arg 1 (parameter 1) is higher in memory than Arg 2 because FORTRAN pushes
  3748.  arguments (parameters) in the same order that they appear.
  3749.  
  3750.  
  3751.                       High addresses
  3752.  
  3753.                           ┌═══════════════════╗
  3754.                        B  │   Arg 1 segment   ║      BP + 12
  3755.                           │                   ║
  3756.                        A  │   Arg 1 offset    ║─ BP + 10
  3757.                           ├───────────────────╢
  3758.                           │   Arg 2 segment   ║      BP + 8
  3759.       (Stack grows        │                   ║
  3760.       downward with       │   Arg 2 offset    ║─ BP + 6
  3761.       each push or        ├───────────────────╢
  3762.       call.)              │                   ║
  3763.                           │  Return address   ║      BP + 4
  3764.             │             │     (4 bytes)     ║
  3765.             │             │                   ║      BP + 2
  3766.                          ├───────────────────╢
  3767.                           │     Saved BP      ║─ BP
  3768.                           └───────────────────╜
  3769.  
  3770.                       Low addresses
  3771.  
  3772.  Figure 6.5  FORTRAN Stack Frame
  3773.  
  3774.  
  3775.  The assembly procedure can be written as follows:
  3776.  
  3777.  .MODEL LARGE
  3778.  .CODE
  3779.            PUBLIC  Power2
  3780.  Power2    PROC
  3781.            push    bp              ; Entry sequence - save old BP
  3782.            mov     bp,sp           ; Set stack framepointer
  3783.  
  3784.            les     bx,[bp+10]      ; Load Arg1 into
  3785.            mov     ax,es:[bx]      ;   AX
  3786.            les     bx,[bp+6]       ; Load Arg2 into
  3787.            mov     cx,es:[bx]      ;   CX
  3788.            shl     ax,cl           ; AX = AX * (2 to power of CX)
  3789.                                    ; Leave return value in AX
  3790.  
  3791.            pop     bp              ; Exit sequence - restore old BP
  3792.            ret     8               ; Return and restore 8 bytes
  3793.  Power2    ENDP
  3794.            END
  3795.  
  3796.  In the example above, each argument must be loaded using the four-byte
  3797.  address that was pushed onto the stack. The procedure loads four-byte
  3798.  addresses with the LES instruction, which loads the destination operand (in
  3799.  this case, BX) with the source operand, and also loads ES with the object
  3800.  two bytes higher in memory. Thus, the instruction
  3801.  
  3802.            les   bx,[bp+10]
  3803.  
  3804.  loads BX with the value at BP+10 (an offset address), and ES with the value
  3805.  at BP+12 (a segment address), which is necessary to set up the next
  3806.  instruction.
  3807.  
  3808.  Upon exit, the stack is restored with the instruction ret 8, since the
  3809.  total size of parameters pushed onto the stack is eight.
  3810.  
  3811.  
  3812.  6.5  Calls from Pascal
  3813.  
  3814.  A Pascal program can call an assembly procedure in another module just as
  3815.  it would call a Pascal routine. In addition to the steps outlined in
  3816.  Section 6.1, "Writing the Assembly Procedure," the following guidelines may
  3817.  be helpful:
  3818.  
  3819.    1.  Declare procedures called from Pascal as FAR. This is taken care of
  3820.        for you automatically if you use the MODEL directive available with
  3821.        the Microsoft Macro Assembler, Version 5.0 or later; specify LARGE.
  3822.  
  3823.    2.  Observe the Pascal calling convention.
  3824.  
  3825.        a.  Upon exit, the procedure must reset SP to the value it had before
  3826.            the parameters were placed on the stack. The procedure resets SP
  3827.            with the instruction ret size, where size is the total size of
  3828.            all the parameters pushed on the stack.
  3829.  
  3830.        b.  Parameters are placed on the stack in the same order in which
  3831.            they appear in the Pascal source code. The first parameter will
  3832.            be highest in memory (because it is also the first parameter to
  3833.            be placed on the stack, and the stack grows downward.)
  3834.  
  3835.        c.  By default, Pascal parameters are passed by value.
  3836.  
  3837.    3.  Observe the Pascal naming convention.
  3838.  
  3839.        Pascal only recognizes the first 8 characters of any name, while the
  3840.        assembler recognizes the first 31. Names shared publicly with Pascal
  3841.        should not be longer than 8 characters.
  3842.  
  3843.  In the following example program, Pascal calls an assembly procedure that
  3844.  calculates "A x 2^B," where A and B are the first and second parameters,
  3845.  respectively. The calculation is performed by shifting the bits in A to the
  3846.  left, B times.
  3847.  
  3848.  The Pascal module uses an extern declaration in its interface with the
  3849.  assembly procedure. No special keywords are required, because the assembly
  3850.  procedure will use the Pascal calling convention.
  3851.  
  3852.  program Asmtest(input, output);
  3853.  function Power2(a,b:integer):integer; extern;
  3854.  begin
  3855.      writeln('3 times 2 to the power of 5 is ',Power2(3,5));
  3856.  end.
  3857.  
  3858.  To understand how to write the assembly procedure, consider how the
  3859.  parameters are placed on the stack, as illustrated in Figure 6.6.
  3860.  
  3861.  
  3862.                       High addresses
  3863.  
  3864.                           ┌═══════════════════╗
  3865.                        A  │       Arg 1       ║─ BP + 8
  3866.       (Stack grows        ├───────────────────╢
  3867.       downward with    B  │       Arg 2       ║─ BP + 6
  3868.       each push or        ├───────────────────╢
  3869.       call.)              │                   ║      BP + 4
  3870.                           │  Return address   ║
  3871.             │             │     (4 bytes)     ║      BP + 2
  3872.             │             │                   ║
  3873.                          ├───────────────────╢
  3874.                           │     Saved BP      ║─ BP
  3875.                           └───────────────────╜
  3876.  
  3877.                       Low addresses
  3878.  
  3879.  Figure 6.6  Pascal Stack Frame
  3880.  
  3881.  
  3882.  Arg 1 (parameter 1) is higher in memory than Arg 2 because Pascal pushes
  3883.  arguments in the same order that they appear. Each argument is passed by
  3884.  value.
  3885.  
  3886.  The assembly procedure can be written as follows:
  3887.  
  3888.  .MODEL LARGE
  3889.  .CODE
  3890.            PUBLIC  Power2
  3891.  Power2    PROC
  3892.            push    bp              ; Entry sequence - save old BP
  3893.            mov     bp,sp           ; Set stack framepointer
  3894.  
  3895.            mov     ax,[bp+8]       ; Load Arg1 into AX
  3896.            mov     cx,[bp+6]       ; Load Arg2 into CX
  3897.            shl     ax,cl           ; AX = AX * (2 to power of CX)
  3898.                                    ; Leave return value in AX
  3899.  
  3900.            pop     bp              ; Exit sequence - restore old BP
  3901.            ret     4               ; Return and restore 4 bytes
  3902.  Power2    ENDP
  3903.            END
  3904.  
  3905.  The AX and CX registers can be loaded directly because the parameters were
  3906.  passed by value. Note that the ret 4 instruction is necessary to clear the
  3907.  stack of the four bytes of parameters.
  3908.  
  3909.  
  3910.  6.6  Calling High-Level Languages from Assembly
  3911.  
  3912.  High-level language routines assume that certain initialization code has
  3913.  previously been executed; you can ensure that the proper initialization is
  3914.  performed by starting in a high-level language module, and then calling an
  3915.  assembly procedure. The assembly procedure can then call high-level
  3916.  language routines as needed, as shown in Figure 6.7.
  3917.  
  3918.  To execute an assembly call to a high-level language, you need to observe
  3919.  the following guidelines:
  3920.  
  3921.    1.  Push each parameter onto the stack, observing the calling convention
  3922.        of the high-level language. Constants such as offset addresses must
  3923.        first be loaded into a register before being pushed.
  3924.  
  3925.    2.  With long parameters, always push the segment or high-order portion
  3926.        of the parameter first, regardless of the calling convention.
  3927.  
  3928.    3.  If you are using the BASIC/FORTRAN/Pascal calling convention with a
  3929.        function that returns a non integer value, then allocate an
  3930.        additional two-byte parameter. This additional parameter should
  3931.        contain the offset of the location where you want the value returned,
  3932.        and must be pushed onto the stack last.
  3933.  
  3934.    4.  Execute a call. The call must be far unless the high-level language
  3935.        routine is small model.
  3936.  
  3937.    5.  If the routine used the C calling convention, then immediately after
  3938.        the call you must clear the stack of parameters with the instruction
  3939.  
  3940.            add sp,size
  3941.  
  3942.        where size is the total size in bytes of all parameters that were
  3943.        pushed.
  3944.  
  3945.  
  3946.                   C code                             Assembly code
  3947.      ┌───────────────────────────────┐     ┌───────────────────────────────┐
  3948.      │                               │     │                               │
  3949.      │  (C start-up)                 │     │                               │
  3950.      │                               │     │                               │
  3951.      │  main(){                      │     │                               │
  3952.      │         asub(); ───────┐      │     │                               │
  3953.      │  }                     └──────┼─────┼PROC asub                     │
  3954.      │                               │     │ .                             │
  3955.      │  (C termination)              │     │ .                             │
  3956.      │                               │     │ .                             │
  3957.      │                        ┌──────┼─────┼─     call ctest               │
  3958.      │                        │      │     │ .                             │
  3959.      │                        │      │     │ .                             │
  3960.      │  ctest(){  ───────────┘      │     │ .                             │
  3961.      │  .                            │     │      ret                      │
  3962.      │  .                            │     │ ENDP asub                     │
  3963.      │  .                            │     │                               │
  3964.      │  }                            │     │                               │
  3965.      │                               │     │                               │
  3966.      │                               │     │                               │
  3967.      └───────────────────────────────┘     └───────────────────────────────┘
  3968.  
  3969.  Figure 6.7  Assembly Call to C
  3970.  
  3971.  6.7  The Microsoft Segment Model
  3972.  
  3973.  If you use the simplified segment directives by themselves, you do not need
  3974.  to know the names assigned for each segment. However, versions of the Macro
  3975.  Assembler prior to 5.0 do not support these directives. With older versions
  3976.  of the assembler, you should use the SEGMENT, GROUP, ASSUME, and ENDS
  3977.  directives equivalent to the simplified segment directives.
  3978.  
  3979.  Table 6.1 shows the default segment names created by each directive. Use
  3980.  of these segments ensures compatibility with Microsoft languages and will
  3981.  help you to access public symbols.  This table is followed by a list of
  3982.  three steps, illustrating how to make the actual declarations, and an
  3983.  example program.
  3984.  
  3985.  Table 6.1
  3986.  Default Segments and Types
  3987.  for Standard Memory Models
  3988. ╓┌────────┌───────────┌──────────┌───────┌────────┌─────────┌────────────────╖
  3989.  Model    Directive   Name       Align   Combine  Class      Group
  3990.  ────────────────────────────────────────────────────────────────────
  3991.  Small    .CODE       _TEXT      WORD    PUBLIC   'CODE'
  3992.  Model    Directive   Name       Align   Combine  Class      Group
  3993. Small    .CODE       _TEXT      WORD    PUBLIC   'CODE'
  3994.           .DATA       _DATA      WORD    PUBLIC   'DATA'     DGROUP
  3995.           .CONST      CONST      WORD    PUBLIC   'CONST'    DGROUP
  3996.           .DATA?      _BSS       WORD    PUBLIC   'BSS'      DGROUP
  3997.           .STACK      STACK      PARA    STACK    'STACK'    DGROUP
  3998.  ────────────────────────────────────────────────────────────────────
  3999.  Medium   .CODE       name_TEXT  WORD    PUBLIC   'CODE'
  4000.           .DATA       _DATA      WORD    PUBLIC   'DATA'     DGROUP
  4001.           .CONST      CONST      WORD    PUBLIC   'CONST'    DGROUP
  4002.           .DATA?      _BSS       WORD    PUBLIC   'BSS'      DGROUP
  4003.           .STACK      STACK      PARA    STACK    'STACK'    DGROUP
  4004.  ────────────────────────────────────────────────────────────────────
  4005.  Compact  .CODE       _TEXT      WORD    PUBLIC   'CODE'
  4006.           .FARDATA    FAR_DATA   PARA    private  'FAR_DATA'
  4007.           .FARDATA?   FAR_BSS    PARA    private  'FAR_BSS'
  4008.           .DATA       _DATA      WORD    PUBLIC   'DATA'     DGROUP
  4009.           .CONST      CONST      WORD    PUBLIC   'CONST'    DGROUP
  4010.           .DATA?      _BSS       WORD    PUBLIC   'BSS'      DGROUP
  4011.           .STACK      STACK      PARA    STACK    'STACK'    DGROUP
  4012.  ────────────────────────────────────────────────────────────────────
  4013.  Model    Directive   Name       Align   Combine  Class      Group
  4014. ────────────────────────────────────────────────────────────────────
  4015.  Large    .CODE       name_TEXT  WORD    PUBLIC   'CODE'
  4016.           .FARDATA    FAR_DATA   PARA    private  'FAR_DATA'
  4017.           .FARDATA?   FAR_BSS    PARA    private  'FAR_BSS'
  4018.           .DATA       _DATA      WORD    PUBLIC   'DATA'     DGROUP
  4019.           .CONST      CONST      WORD    PUBLIC   'CONST'    DGROUP
  4020.           .DATA?      _BSS       WORD    PUBLIC   'BSS'      DGROUP
  4021.           .STACK      STACK      PARA    STACK    'STACK'    DGROUP
  4022.  ────────────────────────────────────────────────────────────────────
  4023.  
  4024.  The directives in Table 6.1 refer to the following kinds of segments:
  4025. ╓┌─────────────────────┌─────────────────────────────────────────────────────╖
  4026.    Directive           Description of Segment
  4027.  ─────────────────────────────────────────────────────────────────────────
  4028.    .CODE               The segment containing all the code for the module.
  4029.  
  4030.    .DATA               Initialized data.
  4031.  
  4032.    .DATA?              Uninitialized data. Microsoft compilers store
  4033.                        uninitialized data separately because it can be more
  4034.    Directive           Description of Segment
  4035.                       uninitialized data separately because it can be more
  4036.                        efficiently stored than initialized data.
  4037.  
  4038.    .FARDATA and        Data placed here will not be combined with the
  4039.    .FARDATA?           corresponding segments in other modules. The segment
  4040.                        of data placed here can always be determined,
  4041.                        however, with the assembler SEG operator.
  4042.  
  4043.    .CONST              Constant data. Microsoft compilers use this segment
  4044.                        for such items as string and floating-point
  4045.                        constants.
  4046.  
  4047.    .STACK              Stack. Normally, this segment is declared in the main
  4048.                        module for you and should not be redeclared.
  4049.  
  4050.  The following steps describe how to use Table 6.1 to create directives:
  4051.  
  4052.    1.  Determine what memory model you are using. Then refer to Table 6.1
  4053.        to look up the segment name, align type, combine type, and class for
  4054.        your code and data segments. Use all of these attributes when you
  4055.        define a segment.  For example, the code segment for small model is
  4056.        declared as follows:
  4057.  
  4058.        _TEXT      SEGMENT   WORD PUBLIC 'CODE'
  4059.  
  4060.        The name _TEXT and all the attributes are taken from Table 6.1. If
  4061.        the combine type is private, simply do not use any combine type.
  4062.  
  4063.    2.  If you have segments in DGROUP, put them into DGROUP with the GROUP
  4064.        directive, as in:
  4065.  
  4066.        GROUP      DGROUP   _DATA _BSS
  4067.  
  4068.    3.  Use ASSUME and ENDS as you would normally. Upon entry, DS and SS will
  4069.        both point to DGROUP; therefore, a small-model procedure that makes
  4070.        use of DGROUP should include the following ASSUME directive:
  4071.  
  4072.        ASSUME     CS:TEXT, DS:DGROUP, SS:DGROUP
  4073.  
  4074.        A large-model procedure will assume a different code segment, and may
  4075.        assume a far data segment for ES.
  4076.  
  4077.  The following example shows the C-assembly program from Section 6.3,
  4078.  without the simplified segment directives from Version 5.0 of the
  4079.  Microsoft Macro Assembler:
  4080.  
  4081.  _TEXT     SEGMENT WORD PUBLIC 'CODE'
  4082.            ASSUME  cs:_TEXT
  4083.            PUBLIC  _Power2
  4084.  _Power2   PROC
  4085.            push    bp          ; Entry sequence - save BP
  4086.            mov     bp,sp       ; Set stack frame
  4087.  
  4088.            mov     ax,[bp+4]   ; Load Arg1 into AX
  4089.            mov     cx,[bp+6]   ; Load Arg2 into CX
  4090.            shl     ax,cl       ; AX = AX * (2 to power of CX)
  4091.                                ; Leave return value in AX
  4092.  
  4093.            pop     bp          ; Exit sequence - restore BP
  4094.            ret                 ; Return
  4095.  _Power2   ENDP
  4096.  _TEXT     ENDS
  4097.            END
  4098.  
  4099.  
  4100.  
  4101.  PART 2--DATA HANDLING REFERENCE
  4102.  
  4103.  ───────────────────────────────────────────────────────────────────────────
  4104.  
  4105.  CHAPTERS
  4106.  
  4107.      7    Passing by Reference or Value
  4108.      8    Numerical, Logical, and String Data
  4109.      9    Special Data Types
  4110.  
  4111.  
  4112.  
  4113.  Part 2 explains how to pass types of data, with focus on those types of
  4114.  data (such as strings of text) that are stored in a different format by
  4115.  each language.  This part also summarizes parameter-passing methods and
  4116.  describes alternative methods for sharing data between modules.
  4117.  
  4118.  
  4119.  
  4120.  CHAPTER 7  PASSING BY REFERENCE OR VALUE
  4121.  
  4122.  ───────────────────────────────────────────────────────────────────────────
  4123.  
  4124.  7.1  BASIC Arguments
  4125.  
  4126.  7.2  C Arguments
  4127.  
  4128.  7.3  FORTRAN Arguments
  4129.  
  4130.  7.4  Pascal Arguments
  4131.  
  4132.  
  4133.  
  4134.  Chapter 2 introduced the general concepts of passing by reference and
  4135.  passing by value. Chapter 2 also listed the default method used by each
  4136.  language. For example, BASIC passes by reference, and Pascal passes by
  4137.  value.
  4138.  
  4139.  This chapter describes features in each language that override the
  4140.  default. For example, using the BYVAL keyword in a DECLARE statement will
  4141.  cause BASIC to pass a given parameter by value rather than by reference.
  4142.  
  4143.  This chapter is divided into four sections, each of which summarizes
  4144.  parameter-passing methods in a particular language, discussing how to pass
  4145.  arguments by value, by near reference, and by far reference. To write a
  4146.  successful mixed-language interface, you must consider how each parameter
  4147.  is passed by the calling routine and how each is received by the called
  4148.  routine.
  4149.  
  4150.  
  4151.  7.1  BASIC Arguments
  4152.  
  4153.  The default for BASIC is to pass all arguments by near reference.
  4154.  
  4155.  ───────────────────────────────────────────────────────────────────────────
  4156.  Note
  4157.    Every BASIC subprogram or function always receives parameters by near
  4158.    reference. The rest of this section describes how BASIC passes parameters
  4159.    only.
  4160.  ───────────────────────────────────────────────────────────────────────────
  4161.  
  4162.  
  4163.  ■  Passing BASIC Arguments by Value
  4164.  
  4165.  An argument is passed by value when the called routine is first declared
  4166.  with a DECLARE statement, and the BYVAL keyword is applied to the argument.
  4167.  The use of CALLS overrides this default and passes by far reference
  4168.  instead, as mentioned below.
  4169.  
  4170.  
  4171.  ■  Passing BASIC Arguments by Near Reference
  4172.  
  4173.  The BASIC default is to pass by near reference. Use of SEG, BYVAL, or CALLS
  4174.  changes this default.
  4175.  
  4176.  
  4177.  ■  Passing BASIC Arguments by Far Reference
  4178.  
  4179.  BASIC will pass each argument in a call by far reference when CALLS is used
  4180.  to invoke a routine. Using SEG to modify a parameter in a preceding DECLARE
  4181.  statement will also cause BASIC to pass that parameter by far reference.
  4182.  
  4183.  
  4184.  ■  Examples
  4185.  
  4186.  DECLARE SUB Test(BYVAL a%, b%, SEG c%)
  4187.  .
  4188.  .
  4189.  .
  4190.  CALL Test(x%, y%, z%)
  4191.  
  4192.  The example above passes the first argument (a%) by value, the second
  4193.  argument (b%) by near reference, and the third argument (c%) by far
  4194.  reference.
  4195.  
  4196.  CALLS Test2(x%, y%, z%)
  4197.  
  4198.  The example above passes each argument by far reference.
  4199.  
  4200.  
  4201.  7.2  C Arguments
  4202.  
  4203.  The default for C is to pass all arrays by reference (near or far,
  4204.  depending on the memory model) and all other data types by value. C uses
  4205.  far data pointers for compact, large, and huge model, and near data
  4206.  pointers for small and medium model.
  4207.  
  4208.  
  4209.  ■  Passing C Arguments by Value
  4210.  
  4211.  The C default is to pass all nonarrays (which includes all data types other
  4212.  than those explicitly declared as arrays) by value.
  4213.  
  4214.  Arrays can be passed by value by being declared as the only member of a
  4215.  structure. The following example passes all 100 bytes of x directly to the
  4216.  function test().
  4217.  
  4218.  struct x_struct {int x[100]} xs;
  4219.  .
  4220.  .
  4221.  .
  4222.  test(xs);
  4223.  
  4224.  The function test, in turn, receives the array by declaring a parameter of
  4225.  type x_struct. A C routine would interpret this data object as a structure,
  4226.  so that structure syntax would be used to manipulate an array element, as
  4227.  in the following example:
  4228.  
  4229.  test(x_arrs)
  4230.  struct  x_struct        x_arrs;
  4231.  {
  4232.          x_arrs.x[0] = 1;  /* set first element to 1 */
  4233.  
  4234.  Routines written in other languages, however, would not require structure
  4235.  or record syntax. FORTRAN, for example, would access the first element
  4236.  simply as X(1).
  4237.  
  4238.  
  4239.  ■  Passing C Arguments by Reference (Near or Far)
  4240.  
  4241.  In C, passing a pointer to an object is equivalent to passing the object
  4242.  itself by reference. After control is passed to the called function, each
  4243.  reference to the parameter itself is prefixed by *.
  4244.  
  4245.  ───────────────────────────────────────────────────────────────────────────
  4246.  Note
  4247.    To pass a pointer to a object, prefix the parameter in the call statement
  4248.    with &. To receive a pointer to an object, prefix the parameter's
  4249.    declaration with *. In the latter case, this may mean adding a second *
  4250.    to a parameter which already has a *. For example, to receive a pointer
  4251.    by value, declare it as
  4252.  
  4253.    int        *ptr;
  4254.  
  4255.    but to receive the same pointer by reference, declare it as
  4256.  
  4257.    int        **ptr;
  4258.  
  4259.  ───────────────────────────────────────────────────────────────────────────
  4260.  
  4261.  The default for arrays is to pass by reference.
  4262.  
  4263.  
  4264.  ■  Effect of Memory Models on Size of Reference
  4265.  
  4266.  Near reference is the default for passing pointers in small and medium
  4267.  model C. Far reference is the default in the compact, large, and huge
  4268.  models.
  4269.  
  4270.  Near pointers can be specified with the near keyword, which overrides
  4271.  the default pointer size. However, if you are going to override the default
  4272.  pointer size of a parameter, then you must explicitly declare the parameter
  4273.  type in function declarations as well as function definitions.
  4274.  
  4275.  Far pointers can be specified with the far keyword, which overrides the
  4276.  default pointer size.
  4277.  
  4278.  
  4279.  7.3  FORTRAN Arguments
  4280.  
  4281.  The FORTRAN default is to pass and receive all arguments by reference. The
  4282.  size of the address passed depends on the memory model.
  4283.  
  4284.  
  4285.  ■  Passing FORTRAN Arguments by Value
  4286.  
  4287.  A parameter is passed by value when declared with the VALUE attribute. This
  4288.  declaration can occur either in a FORTRAN INTERFACE statement (which
  4289.  determines how to pass a parameter) or in a function or subroutine
  4290.  declaration (which determines how to receive a parameter).
  4291.  
  4292.  A function or subroutine declared with the PASCAL or C attribute will pass
  4293.  by value all parameters declared in its parameter list (except for
  4294.  parameters declared with the REFERENCE attribute). This change in default
  4295.  passing method applies to function and subroutine definitions, as well as
  4296.  to an INTERFACE statement.
  4297.  
  4298.  
  4299.  ■  Passing FORTRAN Arguments by Reference (Near or Far)
  4300.  
  4301.  Passing by reference is the default for FORTRAN. However, if either the C
  4302.  or PASCAL attribute is applied to a function or subroutine declaration,
  4303.  then you need to apply the REFERENCE attribute to any parameter of the
  4304.  routine that you want passed by reference.
  4305.  
  4306.  
  4307.  ■  Use of Memory Models and FORTRAN Reference Parameters
  4308.  
  4309.  Near reference is the default for medium-model FORTRAN programs; far
  4310.  reference is the default for large-model and huge-model programs.
  4311.  
  4312.  ───────────────────────────────────────────────────────────────────────────
  4313.  Note
  4314.    Versions of FORTRAN prior to 4.0 always compile in large memory model.
  4315.  ───────────────────────────────────────────────────────────────────────────
  4316.  
  4317.  You can apply the NEAR attribute to reference parameters in order to
  4318.  specify near reference. You can apply the FAR attribute to reference
  4319.  parameters in order to specify far reference. These keywords enable you to
  4320.  override the default. They have no effect when they specify the same method
  4321.  as the default.
  4322.  
  4323.  You may need to apply more than one attribute to a given parameter. In
  4324.  that case, enclose both attributes in brackets, separated by a comma:
  4325.  
  4326.            REAL*4 X [NEAR, REFERENCE]
  4327.  
  4328.  
  4329.  7.4  Pascal Arguments
  4330.  
  4331.  The Pascal default is to pass all arguments by value.
  4332.  
  4333.  
  4334.  ■  Passing Pascal Arguments by Near Reference
  4335.  
  4336.  Parameters are passed by near reference when declared as VAR or CONST.
  4337.  
  4338.  Parameters are also passed by near reference when the ADR of a variable,
  4339.  or a pointer to a variable, is passed by value. In other words, the address
  4340.  of the variable is first determined. Then, this address is passed by value.
  4341.  (This is essentially the same method employed in C.)
  4342.  
  4343.  
  4344.  ■  Passing Pascal Arguments by Far Reference
  4345.  
  4346.  Parameters are passed by far reference when declared as VARS or CONSTS.
  4347.  
  4348.  Parameters are also passed by far reference when the ADRS of a variable is
  4349.  passed by value.
  4350.  
  4351.  
  4352.  
  4353.  CHAPTER 8  NUMERICAL, LOGICAL, AND STRING DATA
  4354.  
  4355.  ───────────────────────────────────────────────────────────────────────────
  4356.  
  4357.  8.1  Integer and Real Numbers
  4358.  
  4359.  8.2  FORTRAN COMPLEX Types
  4360.  
  4361.  8.3  FORTRAN LOGICAL Type
  4362.  
  4363.  8.4  Strings
  4364.  
  4365.        8.4.1  String Formats
  4366.  
  4367.        8.4.2  Passing BASIC Strings
  4368.  
  4369.        8.4.3  Passing C Strings
  4370.  
  4371.        8.4.4  Passing FORTRAN Strings
  4372.  
  4373.        8.4.5  Passing Pascal Strings
  4374.  
  4375.  
  4376.  
  4377.  This chapter considers the details of passing and receiving kinds of
  4378.  data. Discussion focuses on the differences in string format and on the
  4379.  methods of passing strings between each combination of languages.
  4380.  
  4381.  
  4382.  8.1  Integer and Real Numbers
  4383.  
  4384.  Integers and reals are usually the simplest kinds of data to pass between
  4385.  languages. However, the type of numerical data is named differently in each
  4386.  language; furthermore, not all data types are available in every language,
  4387.  and another type may have to be substituted in some cases.
  4388.  
  4389.  Table 8.1 shows equivalent data types in each language.
  4390.  
  4391.  ───────────────────────────────────────────────────────────────────────────
  4392.  Warning
  4393.    As noted in Table 8.1, C sometimes performs automatic data conversions
  4394.    which the other languages do not perform. You can prevent C from
  4395.    performing such conversions by declaring a variable as the only member of
  4396.    a structure and then passing this structure. For example, you can pass a
  4397.    variable x of type float, by first declaring the structure:
  4398.  
  4399.    struct {
  4400.               float     x;
  4401.    } x_struct;
  4402.  
  4403.    If you pass a variable of type char or float by value and do not take
  4404.    this precaution, then the C conversion may cause the program to fail.
  4405.  ───────────────────────────────────────────────────────────────────────────
  4406.  
  4407.  
  4408.  8.2  FORTRAN COMPLEX Types
  4409.  
  4410.  The FORTRAN types COMPLEX*8 and COMPLEX*16 are not directly implemented in
  4411.  any other language. However, you can write structures in C, records in
  4412.  Pascal, and user-defined types in BASIC that are precisely equivalent.
  4413.  
  4414.  The type COMPLEX*8 has two fields: the first is a four-byte floating-point
  4415.  number that contains the real component, and the second is a four-byte
  4416.  floating point number that contains the imaginary component.
  4417.  
  4418.  
  4419.  Table 8.1
  4420.  Equivalent Numeric Data Types
  4421. ╓┌────────────────┌──────────────────────┌─────────────────┌─────────────────╖
  4422.  BASIC            C                      FORTRAN           Pascal
  4423.  ────────────────────────────────────────────────────────────────────
  4424.  x%               short                  INTEGER*2         INTEGER2
  4425.  INTEGER          int                                      INTEGER
  4426.                                                             (default)
  4427.  ────────────────────────────────────────────────────────────────────
  4428.  ...              unsigned short1       ...               WORD
  4429.                   unsigned
  4430.  ────────────────────────────────────────────────────────────────────
  4431.  x&               long                   INTEGER*4         INTEGER4
  4432.  LONG                                    INTEGER
  4433.  BASIC            C                      FORTRAN           Pascal
  4434. LONG                                    INTEGER
  4435.                                           (default)
  4436.  ────────────────────────────────────────────────────────────────────
  4437.  ...              unsigned long1        ...               ...
  4438.  ────────────────────────────────────────────────────────────────────
  4439.  x!               float2                REAL*4            REAL4
  4440.  x                                       REAL              REAL
  4441.   (default)                                                 (default)
  4442.  SINGLE
  4443.  ────────────────────────────────────────────────────────────────────
  4444.  x#               double                 REAL*8            REAL8
  4445.  DOUBLE                                  DOUBLE
  4446.                                          PRECISION
  4447.  ────────────────────────────────────────────────────────────────────
  4448.  ...              unsigned char4        CHARACTER4       BOOLEAN
  4449.  ────────────────────────────────────────────────────────────────────
  4450.  
  4451.  The type COMPLEX*16 is similar to COMPLEX*8, with the only difference
  4452.  being that each field contains an eight-byte floating-point number.
  4453.  
  4454.  The type COMPLEX is equivalent to the type COMPLEX*8.
  4455.  
  4456.  
  4457.  ┌═════════════════════════════════╤═════════════════════════════════╗
  4458.       │      Float real component       │    Float imaginary component    ║
  4459.       └─────────────────────────────────┴─────────────────────────────────╜
  4460.        ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  4461.                        
  4462.                     4 bytes                           4 bytes
  4463.  
  4464.  Figure 8.1  FORTRAN COMPLEX Data Format
  4465.  
  4466.  
  4467.  8.3  FORTRAN LOGICAL Type
  4468.  
  4469.  The FORTRAN LOGICAL type is not equivalent to either the Pascal BOOLEAN or
  4470.  C char type. Instead, a FORTRAN LOGICAL*2 is stored as a one-byte indicator
  4471.  value (1=true, 0=false) followed by an unused byte. A FORTRAN LOGICAL*4 is
  4472.  stored as a one-byte indicator value followed by three unused bytes. The
  4473.  type LOGICAL is equivalent to LOGICAL*4, unless $STORAGE:2 is in effect.
  4474.  
  4475.  To pass or receive a FORTRAN LOGICAL type, declare a C structure, Pascal
  4476.  record, or BASIC user-defined type, with the appropriate fields.
  4477.  
  4478.  
  4479.  8.4  Strings
  4480.  
  4481.  Strings are stored in a variety of formats. Therefore, some transformation
  4482.  is frequently required to pass strings between languages.
  4483.  
  4484.  This section presents the string format(s) used in each language, and
  4485.  then describes methods for passing strings within specific combinations of
  4486.  languages.
  4487.  
  4488.  
  4489.  8.4.1  String Formats
  4490.  
  4491.  The following section describes how a string is stored by each language, as
  4492.  well as how a string is passed as an argument.
  4493.  
  4494.  
  4495.  ■  BASIC String Format
  4496.  
  4497.  Strings are stored in BASIC as four-byte string descriptors:
  4498.  
  4499.  
  4500.       ┌═════════════════╤═════════════════╗
  4501.       │     Length      │Address (offset) ║
  4502.       └─────────────────┴─────────────────╜
  4503.        ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  4504.                
  4505.             2 bytes          2 bytes
  4506.  
  4507.  Figure 8.2  BASIC String Descriptor Format
  4508.  
  4509.  
  4510.  The first field of the string descriptor contains a two-byte integer
  4511.  indicating the length of the actual string text. The second field contains
  4512.  the address of this text. This address is an offset into the default data
  4513.  area and is assigned by BASIC's string-space management routines. These
  4514.  management routines need to be available to reassign this address whenever
  4515.  the length of the string changes, yet these management routines are only
  4516.  available to BASIC. Therefore, other languages should not alter the length
  4517.  of a BASIC string.
  4518.  
  4519.  
  4520.  ■  C String Format
  4521.  
  4522.  C stores strings as simple arrays of bytes and uses a null character
  4523.  (numerical 0, ASCII NUL) as delimiter. For example, consider the string
  4524.  declared as follows:
  4525.  
  4526.  char str[] = "String of text"
  4527.  
  4528.  The string is stored in 15 bytes of memory as:
  4529.  
  4530.  
  4531.  ┌════╤════╤════╤════╤════╤════╤═══╤════╤════╤═══╤════╤════╤════╤════╤════╗
  4532.  │ S  │ t  │ r  │ i  │ n  │ g  │   │ o  │ f  │   │ t  │ e  │ x  │ t  │ \O ║
  4533.  └────┴────┴────┴────┴────┴────┴───┴────┴────┴───┴────┴────┴────┴────┴────╜
  4534.  
  4535.  Figure 8.3  C String Format
  4536.  
  4537.  
  4538.  Since str is an array like any other, it is passed by reference, just as
  4539.  other C arrays are. To pass by value, declare the array as a member of a
  4540.  structure. (See Section 7.2, "C Arguments," for more information.)
  4541.  
  4542.  
  4543.  ■  FORTRAN String Format
  4544.  
  4545.  FORTRAN stores strings as a series of bytes at a fixed location in memory.
  4546.  There is no delimiter at the end of the string as in C. Consider the string
  4547.  declared as follows:
  4548.  
  4549.            STR = 'String of text'
  4550.  
  4551.  The string is stored in 14 bytes of memory as:
  4552.  
  4553.  
  4554.  ┌════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╗
  4555.  │ S  │ t  │ r  │ i  │ n  │ g  │    │ o  │ f  │    │ t  │ e  │ x  │ t  ║
  4556.  └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────╜
  4557.  
  4558.  Figure 8.4  FORTRAN String Format
  4559.  
  4560.  
  4561.  Strings are passed by reference, just as other FORTRAN data are. Although
  4562.  Version 4.0 of the FORTRAN Optimizing Compiler has a method for passing
  4563.  length, the variable length FORTRAN strings cannot be used in a mixed-
  4564.  language interface because other languages cannot access the temporary
  4565.  variable that FORTRAN uses to communicate string length.
  4566.  
  4567.  
  4568.  ■  Pascal String Format
  4569.  
  4570.  Pascal has two types of strings, each of which uses a different format: a
  4571.  fixed-length type STRING and the variable-length type LSTRING.
  4572.  
  4573.  The format used for STRING is identical to the FORTRAN string format,
  4574.  described above.
  4575.  
  4576.  The format of an LSTRING stores the length in the first byte. For example,
  4577.  consider an LSTRING declared as:
  4578.  
  4579.  VAR STR:LSTRING(14);
  4580.  STR := 'String of text'
  4581.  
  4582.  The string is stored in 15 bytes of memory. The first byte indicates the
  4583.  length of the string text. The remaining bytes contain the string text
  4584.  itself:
  4585.  
  4586.  
  4587.  ╒════╤════╤════╤════╤════╤════╤════╤═══╤════╤════╤═══╤════╤════╤════╤════╗
  4588.  │ 14 │ S  │ t  │ r  │ i  │ n  │ g  │   │ o  │ f  │   │ t  │ e  │ x  │ t  ║
  4589.  └────┴────┴────┴────┴────┴────┴────┴───┴────┴────┴───┴────┴────┴────┴────╜
  4590.  
  4591.  Figure 8.5  Pascal String Format
  4592.  
  4593.  
  4594.  8.4.2  Passing BASIC Strings
  4595.  
  4596.  When a BASIC string (such as A$) appears in an argument list, BASIC passes
  4597.  a string descriptor rather than the string data itself. The BASIC string
  4598.  descriptor is not compatible with the string formats of the other
  4599.  languages.
  4600.  
  4601.  ───────────────────────────────────────────────────────────────────────────
  4602.  Warning
  4603.    When you pass a string from BASIC to another language, the called routine
  4604.    should under no circumstances alter the length of the string. Other
  4605.    languages lack BASIC's string-space management routines. Therefore,
  4606.    altering the length of a BASIC string is liable to corrupt parts of
  4607.    the BASIC string space. Changes that do not affect length, however, are
  4608.    relatively safe.
  4609.  
  4610.    The routine that receives the string must not call any BASIC routine. If
  4611.    it does, BASIC's string-space management routines may change the location
  4612.    of the string data without warning.
  4613.  ───────────────────────────────────────────────────────────────────────────
  4614.  
  4615.  However, the SADD and LEN functions extract parts of the string descrip-
  4616.  tor. SADD extracts the address of the actual string data, and LEN extracts
  4617.  the length. The results of these functions can then be passed to other
  4618.  languages.
  4619.  
  4620.  BASIC should pass the result of the SADD function by value. Bear in mind
  4621.  that the string's address, not the string itself, will be passed by value.
  4622.  This amounts to passing the string itself by reference. The BASIC module
  4623.  passes the string address, and the other module receives the string
  4624.  address. The address returned by SADD is declared as type integer, but is
  4625.  actually equivalent to a C near pointer or Pascal ADR variable.
  4626.  
  4627.  Pass LEN(A$) as you would normally pass a two-byte integer.
  4628.  
  4629.  
  4630.  ■  Passing BASIC Strings to C
  4631.  
  4632.  Before attempting to pass a BASIC string to C, you may want to first append
  4633.  a null byte on the end, with an instruction such as:
  4634.  
  4635.  A$ = A$ + CHR$(0)
  4636.  
  4637.  The string now conforms to the C string format. Note that when used in a
  4638.  BASIC string expression the + indicates concatenation, or joining, of two
  4639.  strings.
  4640.  
  4641.  There are two methods for passing a string from BASIC to C. The first
  4642.  method is to pass the string address and string length as separate
  4643.  arguments, using the SADD and LEN functions. If you are linking to a C
  4644.  library routine, this is the only workable method.
  4645.  
  4646.  DECLARE SUB Test CDECL(BYVAL S%, BYVAL N%)
  4647.  CALL Test(SADD(A$), LEN(A$))
  4648.  .
  4649.  .
  4650.  .
  4651.  void Test(s, n)
  4652.  char near *s;
  4653.  int  n;
  4654.  {
  4655.  
  4656.  In the example above, SADD(A$) returns the near address of the string data.
  4657.  This address must be passed by value, since it is equivalent to a pointer
  4658.  (even though treated by BASIC as an integer). Passing by reference would
  4659.  attempt to pass the address of the address, rather than the address itself.
  4660.  
  4661.  C must receive a near pointer since only the near (offset) address is
  4662.  being passed by BASIC. Near pointers are the default pointer size in
  4663.  medium-model C.
  4664.  
  4665.  The second method is to pass the string descriptor itself, with a call
  4666.  statement such as:
  4667.  
  4668.  CALL Test2(A$)
  4669.  
  4670.  In this case, the C function must declare a structure for the parameter,
  4671.  which has the appropriate fields (length and address) for a BASIC string
  4672.  descriptor. The C function should then expect to receive a pointer to a
  4673.  structure of this type.
  4674.  
  4675.  
  4676.  ■  Passing BASIC Strings to FORTRAN
  4677.  
  4678.  FORTRAN variable-length strings (available in Version 4.0) cannot be used
  4679.  in a mixed-language interface.
  4680.  
  4681.  Use the SADD function to pass the address of a BASIC string. The FORTRAN
  4682.  routine should declare a character variable of the same length (which is
  4683.  fixed).
  4684.  
  4685.  DECLARE SUB Test(BYVAL S%)
  4686.  A$="abcd"
  4687.  CALL(SADD(A$))
  4688.  .
  4689.  .
  4690.  .
  4691.  C       FORTRAN SOURCE
  4692.  C
  4693.          SUBROUTINE  TEST(STRINGA)
  4694.          CHARACTER*4 STRINGA [NEAR]
  4695.  
  4696.  In the example above, SADD(A$) should be passed by value, since it is actu-
  4697.  ally an address and not an integer. (Passing a string by reference is
  4698.  equivalent to passing the string address by value.) Note that CHARACTER*4
  4699.  STRINGA [NEAR] declares a fixed-length parameter received by near
  4700.  reference.
  4701.  
  4702.  FORTRAN must receive by near reference. The NEAR attribute makes this
  4703.  adjustment, since the FORTRAN default is to receive by far reference.
  4704.  
  4705.  
  4706.  ■  Passing BASIC Strings to Pascal
  4707.  
  4708.  The same technique used to pass a string to FORTRAN can be used to pass a
  4709.  string to Pascal. However, the Pascal routine should declare the string as
  4710.  a VAR parameter, in order to receive the string by near reference. The
  4711.  Pascal code must declare the fixed-length type string(4) in a separate
  4712.  statement, then use the declared type in a procedure declaration.
  4713.  
  4714.  DECLARE SUB Test(BYVAL S%)
  4715.  A$="abcd"
  4716.  CALL Test(SADD(A$))
  4717.  .
  4718.  .
  4719.  .
  4720.  type stype4=string(4);
  4721.  procedure Test(VAR StringA:stype4);
  4722.  
  4723.  
  4724.  8.4.3  Passing C Strings
  4725.  
  4726.  When a C string appears in an argument list, C passes the address of the
  4727.  string. (A C string is just an array and so is passed by reference.) C can
  4728.  easily pass data to a fixed-length FORTRAN or Pascal string, or to BASIC in
  4729.  the form of a string descriptor.
  4730.  
  4731.  
  4732.  ■  Passing C Strings to BASIC
  4733.  
  4734.  To pass a C string to BASIC, first allocate a string in C. Then create a
  4735.  structure identical to a BASIC string descriptor. Pass this structure by
  4736.  near reference, as in the example below:
  4737.  
  4738.  char cstr[] = "ABC";
  4739.  struct {
  4740.          char    *sd_addr;
  4741.          int     sd_len;
  4742.  } str_des;
  4743.  str_des.sd_addr = cstr;
  4744.  str_des.sd_len = strlen(cstr);
  4745.  bsub(&str_des);
  4746.  
  4747.  Make sure that the string originates in C, not in BASIC. Otherwise, BASIC
  4748.  may attempt to move the string around in memory.
  4749.  
  4750.  
  4751.  ■  Passing C Strings to FORTRAN and Pascal
  4752.  
  4753.  To pass strings to FORTRAN and Pascal, it is only necessary to make sure
  4754.  that the called routine receives the string by reference and allocates suf-
  4755.  ficient space. FORTRAN and Pascal should expect to receive fixed-length
  4756.  strings; to declare a fixed-length string parameter in Pascal you must
  4757.  first declare a type, as shown below.
  4758.  
  4759.  
  4760.  ■  Example
  4761.  
  4762.  /* C code - calls Pascal and FORTRAN */
  4763.  /* large memory model assumed */
  4764.  
  4765.  char a[]="abcd";
  4766.  
  4767.  Test1(a);               /* call to FORTRAN */
  4768.  Test2(a);               /* call to Pascal */
  4769.  
  4770.  
  4771.  {* Pascal *}
  4772.  module Ptest1;
  4773.  type stype4 : string(4);
  4774.  procedure Test1(vars StringA : stype4)
  4775.  
  4776.  
  4777.  C        FORTRAN
  4778.  C
  4779.           SUBROUTINE TEST2(A)
  4780.           CHARACTER*4 A
  4781.  
  4782.  However, C cannot pass variable-length strings to FORTRAN; the FORTRAN
  4783.  string data are not placed on the stack, but require special low-level
  4784.  variables found only in a FORTRAN program.
  4785.  
  4786.  
  4787.  8.4.4  Passing FORTRAN Strings
  4788.  
  4789.  Variable-length FORTRAN strings of type CHARACTER*(*) (available in
  4790.  Versions 4.0 and later) cannot be effectively passed to other languages.
  4791.  However, fixed-length strings can be passed without much difficulty; the
  4792.  principal limitation is that the FORTRAN INTERFACE must declare the length
  4793.  of the string in advance.
  4794.  
  4795.  By default, FORTRAN passes strings by reference. However, if you apply the
  4796.  C or PASCAL attribute to a routine, then the default changes to passing by
  4797.  value. The actual string data do not include a delimiter, unless you use
  4798.  the C-string feature described below.
  4799.  
  4800.  
  4801.  ■  Passing FORTRAN Strings to BASIC
  4802.  
  4803.  FORTRAN cannot directly pass strings to BASIC because BASIC expects to
  4804.  receive a string descriptor when passed a string. Yet there is an indirect
  4805.  method for passing FORTRAN strings to BASIC. First, allocate a fixed-length
  4806.  string in FORTRAN, declare an array of two-byte integers, and treat the
  4807.  array as a string descriptor. Next, assign the address of the string to the
  4808.  first element (using the LOC function), and assign the length of the string
  4809.  to the second element. Finally, pass the integer array itself by reference.
  4810.  BASIC can receive and process this array just as it would a string
  4811.  descriptor.
  4812.  
  4813.  
  4814.  ■  Passing FORTRAN Strings to C
  4815.  
  4816.  The C-string feature overrides the normal FORTRAN format and produces
  4817.  strings that can be effectively manipulated by C. When the C-string feature
  4818.  is used, a null byte is appended to the end of the string, and backslashes
  4819.  that appear in a literal-string text are treated as escapes.
  4820.  
  4821.  You convert FORTRAN strings to C strings by simply typing C immediately
  4822.  after a string constant. Do not insert commas or any other intervening
  4823.  punctuation, only spaces. Note that the length of the string is increased
  4824.  by one because of the null byte that is appended. You need to allow for
  4825.  this when you declare string variables.
  4826.  
  4827.  The following example passes the address of a string to C. The string is
  4828.  in the C format.
  4829.  
  4830.  
  4831.  ■  Example
  4832.  
  4833.            INTERFACE TO SUBROUTINE CONV [C] (S1)
  4834.            CHARACTER*5 S1 [REFERENCE]
  4835.            END
  4836.  C
  4837.           CHARACTER*5 S1
  4838.           S1 = 'abcd' C
  4839.           CALL CONV (S1)
  4840.  
  4841.  In the example above, note that an additional byte is allocated for S1, in
  4842.  consideration of the null byte added by the C-string conversion (done on
  4843.  the line above the call). Also note that the REFERENCE keyword was neces-
  4844.  sary because the C attribute in the first line changes the parameter-
  4845.  passing default to calling by value.
  4846.  
  4847.  
  4848.  ■  Passing FORTRAN Strings to Pascal
  4849.  
  4850.  The FORTRAN and Pascal fixed-length string types are equivalent and there-
  4851.  fore can be easily passed between FORTRAN and Pascal.
  4852.  
  4853.  FORTRAN modules should only pass fixed-length strings to Pascal. The
  4854.  Pascal routines, in turn, should expect to receive fixed-length strings. To
  4855.  specify a fixed-length string parameter in Pascal, you first need to
  4856.  declare a type, as in the example below.
  4857.  
  4858.  
  4859.  ■  Example
  4860.  
  4861.  C     FORTRAN SOURCE CODE
  4862.  C
  4863.            INTERFACE TO SUBROUTINE PS (S1)
  4864.            CHARACTER*4 S1
  4865.            END
  4866.  C
  4867.            S1 = 'wxyz'
  4868.            CALL PS (S1)
  4869.            END
  4870.  
  4871.  { Pascal module}
  4872.  
  4873.  module Psmod;
  4874.  type stype4 = string(4);
  4875.  procedure ps (vars str1 : stype4);
  4876.  
  4877.  
  4878.  8.4.5  Passing Pascal Strings
  4879.  
  4880.  The Pascal data type LSTRING is not compatible with the formats used by the
  4881.  other languages. You can pass an LSTRING indirectly, however, by first
  4882.  assigning it to a STRING variable. Pascal supports such assignments by per-
  4883.  forming a conversion of the data.
  4884.  
  4885.  ───────────────────────────────────────────────────────────────────────────
  4886.  Important
  4887.    Pascal passes an additional, two-byte parameter that indicates string
  4888.    length whenever you pass a parameter of type STRING or of type LSTRING.
  4889.    To suppress the passing of this additional parameter, you first declare a
  4890.    fixed-length type, as shown in the example in the section, "Passing
  4891.    Pascal Strings to C," below.
  4892.  ───────────────────────────────────────────────────────────────────────────
  4893.  
  4894.  
  4895.  ■  Passing Pascal Strings to BASIC
  4896.  
  4897.  To pass a Pascal string to BASIC, first allocate a string in Pascal.
  4898.  Next, create a record identical to a BASIC string descriptor. Initialize
  4899.  this record with the string address and length, and then pass the record by
  4900.  near reference. Make sure that the string originates in Pascal, not in
  4901.  BASIC; otherwise, BASIC may attempt to move the string data around in
  4902.  memory.
  4903.  
  4904.  
  4905.  ■  Passing Pascal Strings to C
  4906.  
  4907.  To pass a string to C, first append a null character (numerical 0, ASCII
  4908.  NUL) to the end of the string by using the concatenation operator (*).
  4909.  
  4910.  Then pass the string to C by reference (by declaring the string argument
  4911.  as CONST, CONSTS, VAR, or VARS). Remember to first declare the fixed-length
  4912.  string type.
  4913.  
  4914.  
  4915.  ■  Example
  4916.  
  4917.  program Passtr(input, output);
  4918.  type
  4919.          stype6 = string(6);
  4920.  var
  4921.          str : stype6;
  4922.  procedure Passtoc (var s1 : stype6) [C]; extern;
  4923.  begin
  4924.          str := 'abcde' * chr(0);
  4925.          Passtoc(str);
  4926.  
  4927.  You can achieve more flexibility in passing Pascal strings by declaring a
  4928.  value parameter of type ADRMEM or ADSMEM and then passing the address of
  4929.  the argument. For instance, the example above could be implemented by first
  4930.  declaring the parameter with the statement,
  4931.  
  4932.  procedure Passtoc (s1adr : ADRMEM) [C]; extern;
  4933.  
  4934.  Then you could make the call with
  4935.  
  4936.          Passtoc(ADR str);
  4937.  
  4938.  With this method, you can pass strings of different lengths to the
  4939.  procedure Passtoc.
  4940.  
  4941.  
  4942.  ■  Passing Pascal Strings to FORTRAN
  4943.  
  4944.  The Pascal STRING and the FORTRAN CHARACTER*n types are equivalent. There-
  4945.  fore Pascal fixed-length string variables can be freely passed to FORTRAN.
  4946.  Usually, you will find it most efficient to pass strings by reference (by
  4947.  declaring the string argument as VAR or VARS). Remember to first declare
  4948.  the fixed-length type before using it.
  4949.  
  4950.  program Passtr(input, output)
  4951.  type
  4952.          stype6 = string(6);
  4953.  var
  4954.          str : stype6;
  4955.  procedure PasstoF (var s1 : stype6); extern;
  4956.  begin
  4957.          PasstoF(str);
  4958.  
  4959.  As explained previously, you can use ADRMEM and ADSMEM to achieve more
  4960.  flexibility in passing strings from Pascal.
  4961.  
  4962.  
  4963.  
  4964.  CHAPTER 9  SPECIAL DATA TYPES
  4965.  
  4966.  ───────────────────────────────────────────────────────────────────────────
  4967.  
  4968.  9.1  Arrays
  4969.  
  4970.        9.1.1  Passing Arrays from BASIC
  4971.  
  4972.        9.1.2  Array Declaration and Indexing
  4973.  
  4974.  9.2  Structures, Records, and User-defined Types
  4975.  
  4976.  9.3  External Data
  4977.  
  4978.  9.4  Pointers and Address Variables
  4979.  
  4980.  9.5  Common Blocks
  4981.  
  4982.        9.5.1  Passing the Address of the Common Block
  4983.  
  4984.        9.5.2  Accessing Common Blocks Directly
  4985.  
  4986.  9.6  Using a Varying Number of Parameters
  4987.  
  4988.  
  4989.  
  4990.  This chapter considers special types of data that are either structured
  4991.  (i.e., contain more than one field) or are accessed externally.
  4992.  
  4993.  
  4994.  9.1  Arrays
  4995.  
  4996.  When you program in only one language, arrays do not present special
  4997.  problems; the language is consistent in its handling of arrays. When you
  4998.  program with more than one language, however, you need to be aware of two
  4999.  special problems that may arise with arrays:
  5000.  
  5001.    1.  Arrays are implemented differently in BASIC, so that you must take
  5002.        special precautions when you pass an array from BASIC to another
  5003.        language (including assembly).
  5004.  
  5005.    2.  Arrays are declared and indexed differently in each language.
  5006.  
  5007.  This section considers each of these problems in turn.
  5008.  
  5009.  ───────────────────────────────────────────────────────────────────────────
  5010.  Note
  5011.    As explained in Chapter 7, arrays cannot be passed by value in C, unless
  5012.    declared within a structure. However, it is usually most efficient to
  5013.    pass arrays by reference.
  5014.  ───────────────────────────────────────────────────────────────────────────
  5015.  
  5016.  
  5017.  9.1.1  Passing Arrays from BASIC
  5018.  
  5019.  Most Microsoft languages permit you to reference arrays directly. In C, for
  5020.  example, an address name is equivalent to the address of the first element.
  5021.  FORTRAN and Pascal are similar. This simple implementation is possible
  5022.  because the location of data for an array never changes.
  5023.  
  5024.  BASIC uses an array descriptor, however, which is similar in some respects
  5025.  to a BASIC string descriptor. The array descriptor is necessary because
  5026.  BASIC may shift the location of array data in memory; BASIC handles memory
  5027.  allocation for arrays dynamically.
  5028.  
  5029.  C, FORTRAN, and Pascal do not have any equivalent of the BASIC array
  5030.  descriptor. More importantly, they lack access to BASIC's space management
  5031.  routines for arrays. Therefore, you may safely pass arrays from BASIC only
  5032.  if you follow three rules:
  5033.  
  5034.    1.  Pass the array's address by applying the VARPTR function to the first
  5035.        element of the array and passing the result by value. To pass the far
  5036.        address of the array, apply both the VARPTR and VARSEG functions and
  5037.        pass each result by value. The receiving language gets the address of
  5038.        the first element and considers it to be the address of the entire
  5039.        array. It can then access the array with its normal array-indexing
  5040.        syntax. The example below illustrates how this works.
  5041.  
  5042.    2.  The routine that receives the array must not, under any circum-
  5043.        stances, make a call back to BASIC. If it does, then the location of
  5044.        the array data may change, and the address that was passed to the
  5045.        routine will become meaningless.
  5046.  
  5047.    3.  BASIC may pass any member of an array by value. With this method, the
  5048.        above precautions do not apply.
  5049.  
  5050.  The following example demonstrates how a BASIC array can be passed to
  5051.  FORTRAN.
  5052.  
  5053.  
  5054.  ■  Example
  5055.  
  5056.  REM   BASIC SOURCE FILE
  5057.  OPTION BASE 1
  5058.  DEFINT A-Z
  5059.  DIM A(20)
  5060.  DECLARE SUB ArrFix(BYVAL Addr AS INTEGER)
  5061.  .
  5062.  .
  5063.  .
  5064.  CALL ArrFix(VARPTR(A(1)))
  5065.  PRINT A(1)
  5066.  END
  5067.  
  5068.  C   FORTRAN SOURCE FILE
  5069.  C
  5070.  
  5071.            SUBROUTINE ARRFIX (ARR)
  5072.            INTEGER*2 ARR [NEAR] (20)
  5073.            ARR(1) = 5
  5074.            END
  5075.  
  5076.  In the example above, BASIC considers that the argument passed is the near
  5077.  address of an array element. FORTRAN considers it to be the near address of
  5078.  the array itself. Both languages are correct. You can use essentially the
  5079.  same method for passing BASIC arrays to Pascal or C.
  5080.  
  5081.  The parameter was declared BYVAL Addr AS INTEGER because a near (two-byte)
  5082.  address needed to be passed. If you wanted to pass a far (four-byte)
  5083.  address, then the proper code would be:
  5084.  
  5085.  DECLARE SUB ArrFix (BYVAL SegAddr AS INTEGER, BYVAL Addr AS INTEGER)
  5086.  CALL ArrFix (VARSEG(A(0)), VARPTR(A(0)))
  5087.  
  5088.  The first field is the segment returned by VARSEG. If you use CDECL then be
  5089.  sure to pass the offset address before the segment address, because CDECL
  5090.  causes parameters to be passed in reverse order:
  5091.  
  5092.  DECLARE SUB ArrFix CDECL (BYVAL Addr AS INTEGER, BYVAL SegAddr AS INTEGER)
  5093.  CALL ArrFix(VARPTR(A((0)), VARSEG(A(0)))
  5094.  
  5095.  ───────────────────────────────────────────────────────────────────────────
  5096.  Note
  5097.    You can apply LBOUND and UBOUND to a BASIC array, to determine lower and
  5098.    upper bounds, and then pass the results to another routine. This way, the
  5099.    size of the array does not need to be determined in advance. See the
  5100.    Microsoft BASIC Language Reference for more information on LBOUND
  5101.    and UBOUND.
  5102.  ───────────────────────────────────────────────────────────────────────────
  5103.  
  5104.  9.1.2  Array Declaration and Indexing
  5105.  
  5106.  Each language varies somewhat in the way that arrays are declared and
  5107.  indexed. Array indexing is purely a source-level consideration and involves
  5108.  no transformation of data. There are two differences in the way that
  5109.  elements are indexed by each language:
  5110.  
  5111.    1.  Lower bounds.
  5112.  
  5113.        By default, FORTRAN indexes the first element of an array as 1. BASIC
  5114.        and C index it as 0. Pascal lets the programmer begin indexing at any
  5115.        integer value. Recent versions of BASIC and FORTRAN also give the
  5116.        user the option of specifying lower bounds at any integer values.
  5117.  
  5118.    2.  Row-major order vs. column-major order.
  5119.  
  5120.        This issue only affects arrays with more than one dimension. With
  5121.        row-major order (used by C and Pascal) the leftmost dimension changes
  5122.        the fastest. With column-major order (used by FORTRAN, and BASIC by
  5123.        default), the rightmost dimension changes the fastest. Thus, in
  5124.        Pascal the first four elements of array X(3,3) are:
  5125.  
  5126.        X[1,1]   X[1,2]   X[1,3]   X[2,1]
  5127.  
  5128.        In FORTRAN, the four elements are:
  5129.  
  5130.        X(1,1)   X(2,1)   X(3,1)   X(1,2)
  5131.  
  5132.  The example above assumes that both the Pascal and FORTRAN arrays use lower
  5133.  bounds of 1. Table 9.1 shows equivalences for array declarations in each
  5134.  language. In this table, r is the number of elements of the row dimension
  5135.  (which changes most slowly), and c is the number of elements of the column
  5136.  dimension (which changes most quickly).
  5137.  
  5138.  
  5139.         Table 9.1
  5140.         Equivalent Array Declarations
  5141. ╓┌──────────────────────┌──────────────────────────────────┌─────────────────╖
  5142.         Language        Array Declaration                  Notes
  5143.         ────────────────────────────────────────────────────────────────────
  5144.         BASIC           DIM x(c-1,r-1)                     with default
  5145.                                                            lower bounds of 0
  5146.         ────────────────────────────────────────────────────────────────────
  5147.         Language        Array Declaration                  Notes
  5148.        ────────────────────────────────────────────────────────────────────
  5149.         C               type x[r][c]                       when passed by
  5150.                                                            reference
  5151.                         struct {                           when passed by
  5152.                          type x[r][c];}x                   value
  5153.         ────────────────────────────────────────────────────────────────────
  5154.         FORTRAN         type x(c,r)                        with default
  5155.                                                            lower bounds of 1
  5156.         ────────────────────────────────────────────────────────────────────
  5157.         Pascal          x:array[a..a+r-1,b..b+c-1]         ...
  5158.                         of type
  5159.         ────────────────────────────────────────────────────────────────────
  5160.  
  5161.  The declarations above extend to any number of dimensions that you may use.
  5162.  For example, the C declaration
  5163.  
  5164.            int     arr1 [2][10][15][20]
  5165.  
  5166.  is equivalent to the FORTRAN declaration
  5167.  
  5168.            INTEGER*2 ARR1(20, 15, 10, 2)
  5169.  
  5170.  
  5171.  ■  Example
  5172.  
  5173.  The following references all refer to the same place in memory for an
  5174.  array:
  5175.  
  5176.  arr1[2][8]             (in C)
  5177.  
  5178.  Arr1[3,9]              (in Pascal, assuming lower bounds of 1)
  5179.  
  5180.  ARR1(9,3)              (in FORTRAN, assuming lower bounds of 1)
  5181.  
  5182.  ARR1(8,2)              (in BASIC, assuming lower bounds of 0)
  5183.  
  5184.  When you use BASIC with the BC command line, you can select the /R compile
  5185.  option, which specifies that row-major order is to be used, rather column-
  5186.  major order.
  5187.  
  5188.  ───────────────────────────────────────────────────────────────────────────
  5189.  Note
  5190.    The constants used in a C array declaration represent dimensions, not
  5191.    upper bounds as they do in other languages. Therefore, the last element
  5192.    in the C array declared as int arr[5][5] is not arr[5][5], but arr[4][4].
  5193.  ───────────────────────────────────────────────────────────────────────────
  5194.  
  5195.  9.2  Structures, Records, and User-defined Types
  5196.  
  5197.  The C struct type, the BASIC user-defined type, and the Pascal record type
  5198.  are equivalent. Therefore, these data types can be passed between C,
  5199.  Pascal, and BASIC.
  5200.  
  5201.  However, these types may be affected by the storage method. By default, C
  5202.  and Pascal use word alignment (unpacked storage) for all data except byte-
  5203.  sized objects and arrays of byte-sized objects. This storage method
  5204.  specifies that occasional bytes may be added as padding, so that word and
  5205.  double-word objects start on an even boundary. (In addition, all nested
  5206.  structures and records start on a word boundary.) The following
  5207.  illustration shows the the contrast between packed and unpacked storage:
  5208.  
  5209.  
  5210.       Packed                       Word-aligned
  5211.       (C, Pascal, BASIC)           (C, Pascal only)
  5212.  
  5213.       ┌═════════════════╗          ┌═════════════════╗
  5214.       │      fld 1      ║          │      fld 1      ║
  5215.       ├ ─ ─ ─ ─┬────────╢          ├ ─ ─ ─ ─┬────────╢
  5216.       │  fld 1 │  fld 2 ║          │  fld 1 │▒▒▒▒▒▒▒▒║
  5217.       ├────────┴ ─ ─ ─ ─╢          ├────────┴────────╢
  5218.       │      fld 2      ║          │      fld 2      ║
  5219.       ├ ─ ─ ─ ─┬────────╢          ├ ─ ─ ─ ─ ─ ─ ─ ─ ╢
  5220.       │  fld 2 │  fld 3 ║          │      fld 2      ║
  5221.       ├────────┴ ─ ─ ─ ─╢          ├─────────────────╢
  5222.       │      fld 3      ║          │      fld 3      ║
  5223.       └─────────────────╜          ├ ─ ─ ─ ─┬────────╢
  5224.                                    │  fld 3 │▒▒▒▒▒▒▒▒║
  5225.                                    └────────┴────────╜
  5226.  
  5227.  Figure 9.1  Structure and Record Storage
  5228.  
  5229.  
  5230.  If a structure or record is being passed between them, it is important that
  5231.  a calling routine and the called routine agree on storage method.
  5232.  Otherwise, data will not be properly received. The simplest method for
  5233.  ensuring compatibility between all three languages is simply to turn on
  5234.  packing for C and Pascal modules. The packed storage method may sacrifice
  5235.  some speed, but it has the advantage of creating smaller executable files.
  5236.  
  5237.  
  5238.  9.3  External Data
  5239.  
  5240.  You can always share data between two languages by passing parameters. In
  5241.  the case of local variables and all BASIC variables, passing parameters is
  5242.  the only convenient way to share data.
  5243.  
  5244.  However, C, FORTRAN, and Pascal routines can access data directly that are
  5245.  external. The term "external" refers to data that are both static and
  5246.  public; in other words, the data are stored in a set place in memory
  5247.  (static, unlike dynamic or local data, which are allocated on the stack),
  5248.  and the data have been made publicly available to other modules. Compilers
  5249.  make a data object (variable, structure or array) available by placing its
  5250.  name, along with size and type information, into the object file.
  5251.  
  5252.  External data (data that can be directly accessed by any other module) can
  5253.  be defined in a C, FORTRAN, Pascal, or assembly module. Note that a data
  5254.  definition is distinct from an external declaration. A definition causes
  5255.  a compiler to create a data object; an external declaration informs a
  5256.  compiler that the object is to be found in another module.
  5257.  
  5258.  There are three requirements for programs that share external data between
  5259.  languages:
  5260.  
  5261.    1.  One of the modules must define the static data.
  5262.  
  5263.        You can define a static data object in a C or FORTRAN module by
  5264.        defining a data object outside all functions and subroutines. (Do not
  5265.        use the static keyword in C with a data object you wish to be
  5266.        public.)
  5267.  
  5268.    2.  The other modules that will access the data must declare the data as
  5269.        external.
  5270.  
  5271.        In C, you can declare data as external by using an extern declara-
  5272.        tion, similar to the extern declaration for functions. In FORTRAN and
  5273.        Pascal, you can declare data as external by adding the EXTERN
  5274.        attribute to the data declaration.
  5275.  
  5276.    3.  Resolve naming-convention differences.
  5277.  
  5278.        In C, you can adopt the BASIC/FORTRAN/Pascal naming convention by
  5279.        applying fortran or pascal to the data declaration. In FORTRAN and
  5280.        Pascal, you can adopt the C naming convention by applying the C
  5281.        attribute to the data declaration.
  5282.  
  5283.  The examples below help illustrate the general language features of
  5284.  external data just described.
  5285.  
  5286.  
  5287.  ■  Examples
  5288.  
  5289.  /* C source code */
  5290.  
  5291.  int       thing1;         /* Thing1 is public and static */
  5292.  extern    int  thing2;    /* Thing2 is defined in another module */
  5293.  static    int  thing3;    /* Thing3 is static, but not public */
  5294.  
  5295.  ctest()
  5296.  {
  5297.  .
  5298.  .
  5299.  .
  5300.  C   FORTRAN SOURCE CODE
  5301.  C
  5302.            INTEGER*2 THING1 [C, EXTERN]
  5303.            INTEGER*2 THING2 [C]
  5304.  C
  5305.  C   THING1 DEFINED IN ANOTHER MODULE, USING C CONVENTION (_thing1)
  5306.  C   THING2 DEFINED HERE, USING C CONVENTION (_thing2)
  5307.  .
  5308.  .
  5309.  .
  5310.  { Pascal source code }
  5311.  
  5312.  module Ptest;
  5313.   procedure Test;
  5314.      var
  5315.         thing1 [C, EXTERN] : integer; { Both vars defined elsewhere }
  5316.         thing2 [C, EXTERN] : integer; {  and use C naming convention }
  5317.  .
  5318.  .
  5319.  .
  5320.  
  5321.  In the examples above, the variables thing1 and thing2 are defined and
  5322.  declared with the C naming convention so that they will be placed into each
  5323.  object file as _thing1 and _thing2. However, you can just as easily specify
  5324.  the BASIC/FORTRAN/Pascal naming convention, by using the following C
  5325.  statements:
  5326.  
  5327.  int       fortran  thing1;
  5328.  extern    int  fortran   thing2;
  5329.  
  5330.  The C attribute can then be dropped from the FORTRAN and Pascal source
  5331.  code. Each object file will contain the names THING1 and THING2.
  5332.  
  5333.  
  5334.  9.4  Pointers and Address Variables
  5335.  
  5336.  Rather than passing data directly, you may want to pass the address of a
  5337.  piece of data. Passing the address amounts to passing the data itself by
  5338.  reference. In some cases, such as BASIC arrays (see Section 9.1.1),
  5339.  passing an address is the only way to share particular kinds of data
  5340.  between two languages.
  5341.  
  5342.  The Pascal ADR and ADS types are equivalent to near and far pointers,
  5343.  respectively, in C. You can pass ADR and ADS variables as ADRMEM or ADSMEM.
  5344.  BASIC and FORTRAN do not have formal address types. However, they do pro-
  5345.  vide ways for storing and passing addresses.
  5346.  
  5347.  BASIC programs can access a variable's segment address with VARSEG and its
  5348.  offset address with VARPTR. The values returned by these
  5349.  intrinsic functions should then be passed or stored as ordinary integer
  5350.  variables. If you pass them to another language, pass by value. Otherwise
  5351.  you will be attempting to pass the address of the address, rather than the
  5352.  address itself.
  5353.  
  5354.  To pass a near address, pass only the offset; if you need to pass a far
  5355.  address, you may need to pass the segment and offset separately. Pass the
  5356.  segment address first, unless CDECL is in effect.
  5357.  
  5358.  FORTRAN programs can determine near and far addresses with the LOC and
  5359.  LOCFAR functions. Store the result as INTEGER*2 (with the LOC function) or
  5360.  as INTEGER*4 (with the LOCFAR function).
  5361.  
  5362.  As with BASIC, if you pass the result of LOC or LOCFAR to another
  5363.  language, be sure to pass by value.
  5364.  
  5365.  
  5366.  9.5  Common Blocks
  5367.  
  5368.  You can pass individual members of a FORTRAN or BASIC common block in an
  5369.  argument list, just as you can with any data. However, you can also give a
  5370.  different language module access to the entire common block
  5371.  at once.
  5372.  
  5373.  Pascal and C modules can reference the items of a common block by first
  5374.  declaring a structure or record, with fields that correspond to the common
  5375.  block variables. (For an example, see the next section.) BASIC modules can
  5376.  also employ a user-defined type to access the fields of a FORTRAN common
  5377.  block.
  5378.  
  5379.  Having defined a structure, record, or user-defined type with the
  5380.  appropriate fields, the Pascal or C module must then connect with the com-
  5381.  mon block itself. The next two sections each present a method for gaining
  5382.  access to common blocks.
  5383.  
  5384.  
  5385.  9.5.1  Passing the Address of the Common Block
  5386.  
  5387.  To pass the address of a common block, simply pass the address of the first
  5388.  variable in the block. (In other words, pass the first variable by
  5389.  reference.) The receiving C or Pascal module should expect to receive a
  5390.  structure (or record) by reference.
  5391.  
  5392.  
  5393.  ■  Example
  5394.  
  5395.  In the example below, the C function initcb receives the address of the
  5396.  variable N, which it considers to be a pointer to a structure with three
  5397.  fields:
  5398.  
  5399.  C   FORTRAN SOURCE CODE
  5400.  C
  5401.          COMMON /CBLOCK/N,X,Y
  5402.          INTEGER*2 N
  5403.          REAL*8 X,Y
  5404.  .
  5405.  .
  5406.  .
  5407.          CALL INITCB(N)
  5408.  .
  5409.  .
  5410.  .
  5411.  /* C source code */
  5412.  
  5413.  struct block_type {
  5414.          int     n;
  5415.          double  x;
  5416.          double  y;
  5417.  };
  5418.  
  5419.  initcb(block_hed)
  5420.  struct block_type *block_hed;
  5421.  {
  5422.          block_hed->n = 1;
  5423.          block_hed->x = 10.0;
  5424.          block_hed->y = 20.0;
  5425.  }
  5426.  
  5427.  
  5428.  9.5.2  Accessing Common Blocks Directly
  5429.  
  5430.  You can access FORTRAN common blocks directly by defining a structure (or
  5431.  record in Pascal) with the appropriate fields and then using the methods
  5432.  described in Section 9.3, "External Data."
  5433.  
  5434.  
  5435.  ■  Example
  5436.  
  5437.  In the example below, cblock is declared as an external structure. You can
  5438.  reference the individual fields of cblock which will correspond to those of
  5439.  the common block CBLOCK in the FORTRAN source file.
  5440.  
  5441.  struct block_type {
  5442.          int     n;
  5443.          double  x;
  5444.          double  y;
  5445.  };
  5446.  
  5447.  extern struct block_type fortran cblock;
  5448.  
  5449.  
  5450.  9.6  Using a Varying Number of Parameters
  5451.  
  5452.  Some C functions, most notably printf, can be called with a different
  5453.  number of arguments each time. To call such a function from another lan-
  5454.  guage, you need to suppress the type-checking that normally forces a call
  5455.  to be made with a fixed number of parameters. In BASIC, you can remove this
  5456.  type checking by omitting from the DECLARE statement a parameter list, as
  5457.  explained in Section 2.2, "Alternative BASIC Interfaces." In FORTRAN or
  5458.  Pascal, you can call routines with a variable number of parameters by
  5459.  including the VARYING attribute in your interface to the routine, along
  5460.  with the C attribute. You must use the C attribute because a variable
  5461.  number of parameters is only feasible with the C calling convention.
  5462.  
  5463.  The VARYING attribute prevents FORTRAN or Pascal from enforcing a matching
  5464.  number of parameters. Each time you call the routine, you will be able to
  5465.  pass more or fewer parameters than are declared in the interface to the
  5466.  routine. However, each actual parameter that you pass will be type-checked
  5467.  against whatever formal parameters you may have declared in the interface.
  5468.  FORTRAN or Pascal will compare the type of the first actual parameter to
  5469.  the first formal parameter (if any), the second actual parameter to the
  5470.  second formal parameter, and so on.
  5471.  
  5472.  Because the number of parameters is not fixed, the routine you call should
  5473.  have some mechanism for determining how many parameters to expect. Often
  5474.  this information is indicated by the first parameter. For example, the C
  5475.  function printf scans the format string passed as the first parameter. The
  5476.  number of fields in the format string determines how many additional param-
  5477.  eters the function should expect.
  5478.  
  5479.  The example below demonstrates the use of the VARYING attribute to call
  5480.  printf directly from Pascal (the program needs to be compiled and linked to
  5481.  the C large memory model so that printf is linked in).
  5482.  
  5483.  
  5484.  ■  Example
  5485.  
  5486.  program Test (input, output);
  5487.  type
  5488.          stype30 : string(30);
  5489.  var
  5490.          str1 : string(30);
  5491.          str2 : string(10);
  5492.          n    : integer;
  5493.  procedure printf (vars s1 : stype30) [C, VARYING]; extern;
  5494.  begin
  5495.          str1 = 'This is %s string, number %d.' * chr(0);
  5496.          str2 = 'formatted' * chr(0);
  5497.          n = 1;
  5498.          printf(str1, str2, n);
  5499.  end.
  5500.  
  5501.  In Pascal, you can write the interface to printf so that the format string
  5502.  can be of varying lengths, by using the ADRMEM feature. See Section 8.4.5,
  5503.  "Passing Pascal Strings," for more information.
  5504.  
  5505.  
  5506.  
  5507.  
  5508.  Index
  5509.  
  5510.  
  5511.  Symbols
  5512.  ──────────────────────────────────────────────────────────────────────────
  5513.  *, C indirection operator
  5514.  &,
  5515.      C address operator
  5516.      type declaration character
  5517.  !, type declaration character
  5518.  #, type declaration character
  5519.  $, type declaration character
  5520.  %, type declaration character
  5521.  
  5522.  
  5523.  A
  5524.  ──────────────────────────────────────────────────────────────────────────
  5525.  Address sizes
  5526.      code
  5527.      data
  5528.  Address variables
  5529.  ADR
  5530.      address type
  5531.      address variable
  5532.      keyword
  5533.  ADRMEM, address type
  5534.  ADS, address variable
  5535.  ADSMEM, address type
  5536.  ALIAS keyword
  5537.      BASIC, use in
  5538.      FORTRAN, use in
  5539.  Array descriptors
  5540.  Arrays
  5541.  AS keyword
  5542.  Assembly
  5543.      calling from
  5544.          BASIC
  5545.          C
  5546.          FORTRAN
  5547.          Pascal
  5548.      interfaces
  5549.          address parameters, used with
  5550.          BASIC
  5551.          C
  5552.          entry sequences
  5553.          exit sequences
  5554.          FORTRAN
  5555.          local data
  5556.          Pascal
  5557.          register considerations
  5558.          return value
  5559.      parameters, accessing
  5560.      passing by
  5561.          far reference
  5562.          near reference
  5563.          value
  5564.      procedures
  5565.  ASSUME directive
  5566.  Attributes, FORTRAN
  5567.  Automatic variables
  5568.  
  5569.  
  5570.  B
  5571.  ──────────────────────────────────────────────────────────────────────────
  5572.  BASIC
  5573.      arrays
  5574.      AS keyword
  5575.      BYVAL keyword
  5576.      calling convention
  5577.      calling from
  5578.          C
  5579.          FORTRAN
  5580.          Pascal
  5581.      CALLS statement
  5582.      calls to
  5583.          C
  5584.          FORTRAN
  5585.          other languages
  5586.          Pascal
  5587.      common blocks
  5588.      compiling
  5589.      initialization
  5590.      naming convention
  5591.      parameter-passing
  5592.          defaults
  5593.          methods
  5594.      parameters, list of
  5595.      passing by
  5596.          far reference
  5597.          near reference
  5598.          value
  5599.      procedures
  5600.      SEG keyword
  5601.      string format
  5602.      type declaration characters
  5603.      types, user-defined
  5604.      VARPTR keyword
  5605.      VARSEG keyword
  5606.  BOOLEAN data type
  5607.  BYVAL keyword
  5608.  
  5609.  
  5610.  C
  5611.  ──────────────────────────────────────────────────────────────────────────
  5612.  C attribute
  5613.      FORTRAN, used in
  5614.      Pascal, used in
  5615.  C language
  5616.      arrays
  5617.      calling convention
  5618.      calling from
  5619.          BASIC
  5620.          FORTRAN
  5621.          Pascal
  5622.      calls to
  5623.          BASIC
  5624.          FORTRAN
  5625.          other languages
  5626.          Pascal
  5627.      compiling
  5628.      extern statement
  5629.      far keyword
  5630.      fortran keyword
  5631.      FORTRAN, linking with
  5632.      functions
  5633.      /Gc compile option
  5634.      memory models
  5635.      naming convention
  5636.      near keyword
  5637.      parameter-passing
  5638.          defaults
  5639.          methods
  5640.      pascal keyword
  5641.      passing by
  5642.          far reference
  5643.          near reference
  5644.          value
  5645.      pointers
  5646.      return value
  5647.      string format
  5648.      structures
  5649.      type declarations
  5650.  Calling conventions
  5651.  CALLS statement
  5652.  CDECL keyword
  5653.  "\&.CODE directive"
  5654.  CodeView debugger
  5655.  Column-major order
  5656.  Common blocks
  5657.  Compact memory model
  5658.  COMPLEX data type, FORTRAN
  5659.  CONST keyword
  5660.  CONSTS keyword
  5661.  C-string feature, FORTRAN
  5662.  
  5663.  
  5664.  D
  5665.  ──────────────────────────────────────────────────────────────────────────
  5666.  Data address size
  5667.  "\&.DATA directive"
  5668.  DECLARE statement
  5669.  Default pointer size, C
  5670.  Default segment names
  5671.  DGROUP
  5672.  Double-precision reals
  5673.  Dynamic variables
  5674.  
  5675.  
  5676.  E
  5677.  ──────────────────────────────────────────────────────────────────────────
  5678.  EQU directive
  5679.  extern statement
  5680.      C, used in
  5681.      Pascal, used in
  5682.  External data
  5683.  
  5684.  
  5685.  F
  5686.  ──────────────────────────────────────────────────────────────────────────
  5687.  FAR attribute
  5688.  far keyword
  5689.  Far reference parameters
  5690.      BASIC
  5691.      C
  5692.      FORTRAN
  5693.      Pascal
  5694.  "\&.FARDATA directive"
  5695.  Floating-point numbers
  5696.  fortran keyword
  5697.  FORTRAN
  5698.      ALIAS keyword
  5699.      arrays
  5700.      C attribute
  5701.      C, linking with
  5702.      calling convention
  5703.      calling from
  5704.          BASIC
  5705.          C
  5706.          Pascal
  5707.      calls to
  5708.          BASIC
  5709.          C
  5710.          other languages
  5711.          Pascal
  5712.      common blocks
  5713.      compiling
  5714.      COMPLEX data type
  5715.      functions and subroutines
  5716.      INTERFACE statement
  5717.      LOC function
  5718.      LOCFAR function
  5719.      LOGICAL data type
  5720.      naming convention
  5721.      parameter-passing
  5722.          defaults
  5723.          keywords
  5724.          methods
  5725.      PASCAL attribute
  5726.      passing by
  5727.          far reference
  5728.          near reference
  5729.          value
  5730.      return value
  5731.      string formats
  5732.  Framepointer
  5733.  FUNCTION procedures
  5734.  functions
  5735.  
  5736.  
  5737.  G
  5738.  ──────────────────────────────────────────────────────────────────────────
  5739.  /Gc compile option
  5740.  GROUP directive
  5741.  
  5742.  
  5743.  H
  5744.  ──────────────────────────────────────────────────────────────────────────
  5745.  Huge memory model, use with C
  5746.  
  5747.  
  5748.  I
  5749.  ──────────────────────────────────────────────────────────────────────────
  5750.  Integers
  5751.  INTERFACE statement, FORTRAN
  5752.  
  5753.  
  5754.  L
  5755.  ──────────────────────────────────────────────────────────────────────────
  5756.  Large memory model
  5757.  LES instruction
  5758.  LOC, FORTRAN function
  5759.  LOCFAR, FORTRAN function
  5760.  LOGICAL data type, FORTRAN
  5761.  Lower bounds, arrays
  5762.  LSTRING
  5763.  
  5764.  
  5765.  M
  5766.  ──────────────────────────────────────────────────────────────────────────
  5767.  Macro Assembler. See also Assembly
  5768.  Macro Assembler
  5769.      assembly interfaces, writing
  5770.      EQU directive
  5771.      simplified segment directives
  5772.  Medium memory model
  5773.  Memory models
  5774.  Microsoft segment model
  5775.  Mixed-language programs
  5776.      compiling
  5777.      linking
  5778.  "\&.MODEL directive"
  5779.  
  5780.  
  5781.  N
  5782.  ──────────────────────────────────────────────────────────────────────────
  5783.  Naming conventions
  5784.  NEAR attribute, FORTRAN
  5785.  near keyword, C
  5786.  Near reference parameters
  5787.      assembly
  5788.      BASIC
  5789.      C
  5790.      FORTRAN
  5791.      Pascal
  5792.  /NOI linker option
  5793.  
  5794.  
  5795.  P
  5796.  ──────────────────────────────────────────────────────────────────────────
  5797.  Packed storage
  5798.  Parameter list, BASIC
  5799.  Parameter type declarations, in C
  5800.  Parameter-passing methods
  5801.  Parameters. See also Passing by
  5802.  Parameters
  5803.      assembly, accessing from
  5804.      calling conventions, effect of
  5805.      passing
  5806.      varying number of
  5807.  PASCAL attribute
  5808.  pascal keyword
  5809.  Pascal
  5810.      address variables
  5811.      arrays
  5812.      C attribute
  5813.      calling convention
  5814.      calling from
  5815.          BASIC
  5816.          FORTRAN
  5817.      calls to
  5818.          BASIC
  5819.          C
  5820.          FORTRAN
  5821.          other languages
  5822.      compiling
  5823.      functions and procedures
  5824.      LSTRING
  5825.      naming convention
  5826.      parameter-passing
  5827.          defaults
  5828.          methods
  5829.      passing by
  5830.          far reference
  5831.          near reference
  5832.          value
  5833.      records
  5834.      return value
  5835.      string formats
  5836.  Passing by
  5837.      far reference
  5838.          assembly
  5839.          BASIC
  5840.          C
  5841.          FORTRAN
  5842.          Pascal
  5843.      near reference
  5844.          assembly
  5845.          BASIC
  5846.          C
  5847.          FORTRAN
  5848.          Pascal
  5849.      value
  5850.          assembly
  5851.          BASIC
  5852.          C
  5853.          FORTRAN
  5854.          Pascal
  5855.  Pointers
  5856.  Procedures
  5857.  Public data
  5858.  PUBLIC directive
  5859.  
  5860.  
  5861.  R
  5862.  ──────────────────────────────────────────────────────────────────────────
  5863.  Real numbers
  5864.  Receiving parameters and calling conventions
  5865.  Records
  5866.  REFERENCE attribute
  5867.  Return value, offset
  5868.  Row-major order
  5869.  
  5870.  
  5871.  S
  5872.  ──────────────────────────────────────────────────────────────────────────
  5873.  SEG keyword
  5874.  SEGMENT directive
  5875.  Segment directives, simplified
  5876.  Segments
  5877.  Single-precision reals
  5878.  Small memory model
  5879.      C, use with
  5880.      procedures, setting up
  5881.  Special data types
  5882.  Stack frame
  5883.  Stack Trace, CodeView feature
  5884.  Stack variables
  5885.  Static data
  5886.  Strings
  5887.      formats
  5888.      passing from
  5889.          BASIC
  5890.          C
  5891.          FORTRAN
  5892.          Pascal
  5893.  Structured data types
  5894.  Structures
  5895.  Subprograms
  5896.  Subroutines
  5897.  
  5898.  
  5899.  T
  5900.  ──────────────────────────────────────────────────────────────────────────
  5901.  Type declaration characters
  5902.  
  5903.  
  5904.  U
  5905.  ──────────────────────────────────────────────────────────────────────────
  5906.  Unpacked storage
  5907.  Unsigned integers
  5908.  User-defined types
  5909.  
  5910.  
  5911.  V
  5912.  ──────────────────────────────────────────────────────────────────────────
  5913.  VALUE keyword
  5914.  Value parameters
  5915.      BASIC
  5916.      C
  5917.      FORTRAN
  5918.      Pascal
  5919.      passing
  5920.  VAR keyword
  5921.  Variables
  5922.      address
  5923.      automatic
  5924.      dynamic
  5925.  VARPTR keyword
  5926.  VARS keyword
  5927.  VARSEG keyword
  5928.  VARYING attribute
  5929.