Example: Writing an MI program

This example shows how to write a simple MI program that receives two packed-decimal parameters and returns the larger value through a third parameter.

This MI program demonstrates how to perform the following operations:

  • Define an external entry point.
  • Define and access parameters.
  • Use conditional branching.
  • Assign a value to a scalar object.
  • End the program.

Setting the entry point

First the program, MI01 in this example, needs an ENTRY directive statement to designate its external entry point. The following directive declares an unnamed (the *) external (the EXT) entry point, which is called with a parameter list corresponding to PARM_LIST (defined later in the source code):

ENTRY * (PARM_LIST) EXT;

Setting the declare statements

IBM® i programs typically pass parameters by reference as part of the high-level language (HLL) calling convention. Because IBM i programs pass by reference (that is, address and not value), the program also needs to define three space pointers (how storage is referenced) to represent the three parameters being passed. This is accomplished by the following directives:

DCL     SPCPTR      ARG1@      PARM;
DCL     SPCPTR      ARG2@      PARM;
DCL     SPCPTR      RESULT@    PARM;

To associate these three space pointers with the parameters being passed to the program, the following operand list (OL) is declared:

DCL     OL          PARM_LIST         /* Name of OL is PARM_LIST  */
                   (ARG1@,            /* The first parameter      */
                    ARG2@,            /* The second parameter     */
                    RESULT@)          /* The third parameter      */
                    PARM       EXT;   /* External parameter list  */

The names ARG1@, ARG2@, RESULT@, and PARM_LIST are chosen by you and are not mandated by the system. You can choose any valid name for any object data element. For a definition of what constitutes a valid name, see "Name" in the Program syntax topic of the Create Program (QPRCRTPG) API.

Now that the program has established addressability (the space pointers) to the three parameters, the program needs to declare how to map (or view) the storage addressed. The following declarations define the storage addressed (the BAS argument) by the three space pointer parameters as being packed-decimal (PKD) scalar data objects (DD) with 15 digits, 5 digits being to the right of the decimal point:


DCL     DD          ARG1       PKD(15,5)     BAS(ARG1@);
DCL     DD          ARG2       PKD(15,5)     BAS(ARG2@);
DCL     DD          RESULT     PKD(15,5)     BAS(RESULT@);

The names ARG1, ARG2, and RESULT are chosen arbitrarily, but, for ease of reading, are similar to the basing space pointers ARG1@, ARG2@, and RESULT@. The declarations of packed 15,5 are used for consistency with CL. The declared type and size could be of any other valid type and size. The true requirement is that the calling program and the MI program agree on the type and size.

Starting the instruction stream

With all the needed declarations now done, the instruction stream definition, where the program will compare the numeric values (CMPNV instruction) of parameters one and two, is started:

        CMPNV(B)    ARG1,ARG2  / LO(ITS2);

The program then branches (the (B) extender to CMPNV) to label ITS2 if ARG1 is less than ARG2 (the /LO branch target).

Note: MI instructions, such as CMPNV, are defined in IBM i Machine Interface. Pervasive instruction extenders, such as branch (B) and target keywords (LO, HI, EQ, and so on), are defined under Instruction Statement, which is a subheading in the Program Syntax section of the Create Program (QPRCRTPG) API topic.

If ARG1 is not low (LO) when compared to ARG2, the next MI instruction in the source stream is run. When the next MI instruction is run, it copies the numeric value (CPYNV instruction) of ARG1 to RESULT and, following that, branches to label RETURN:

        CPYNV       RESULT,ARG1;
        B           RETURN;

If ARG2 was greater than ARG1, the CPYNV instruction at label ITS2 is run, setting RESULT to the value of ARG2:

ITS2:   CPYNV       RESULT,ARG2;

The program has now finished processing and ends:

RETURN: RTX         *;
        PEND;

The previous return external (RTX) instruction is not needed because it is implied by the PEND directive. The RTX instruction is included to add clarity to the program flow.

MI01 program complete code example

Put all together, the program looks like this:

Note: By using the code examples, you agree to the terms of the codedisclaimer.htm.

/********************************************************************/
/********************************************************************/
/*                                                                  */
/*     Program Name: MI01                                           */
/*                                                                  */
/*     Programming Language: MI                                     */
/*                                                                  */
/*     Description: Return the larger of two packed arguments.      */
/*                                                                  */
/*                                                                  */
/*     Header Files Included: None                                  */
/*                                                                  */
/*                                                                  */
/********************************************************************/
ENTRY * (PARM_LIST) EXT;
DCL     SPCPTR      ARG1@      PARM;
DCL     SPCPTR      ARG2@      PARM;
DCL     SPCPTR      RESULT@    PARM;
DCL     OL          PARM_LIST
                   (ARG1@,
                    ARG2@,
                    RESULT@)
                    PARM       EXT;
DCL     DD          ARG1       PKD(15,5)     BAS(ARG1@);
DCL     DD          ARG2       PKD(15,5)     BAS(ARG2@);
DCL     DD          RESULT     PKD(15,5)     BAS(RESULT@);
        CMPNV(B)    ARG1,ARG2  / LO(ITS2);
        CPYNV       RESULT,ARG1;
        B           RETURN;
ITS2:   CPYNV       RESULT,ARG2;
RETURN: RTX         *;
        PEND;