|
Hello All, Many of you probably saw Leif's test program, the code for which he posted, to retrieve the machine serial number. Well, for those of you on this list who are still MI challenged, and are waiting to learn something, let's introduce you to MI, by breaking down Leif's code. You should also read this in conjunction with the System API Reference Manual, chapter 67, Program and CL Command APIs section. This section describes the syntax for MI programs and will expand on the usage of the definitions. Here's the original code: DCL SPCPTR .MACHINE-ATTR INIT(MACHINE-ATTR); DCL DD MACHINE-ATTR CHAR(2608) BDRY(16); DCL DD MAT-MAX-SIZE BIN(4) DEF(MACHINE-ATTR) POS(1) INIT(2608); DCL DD MAT-ACT-SIZE BIN(4) DEF(MACHINE-ATTR) POS(5); DCL DD MAT-P-SNBR CHAR(10) DEF(MACHINE-ATTR) POS(1125); ENTRY * EXT; MATMATR .MACHINE-ATTR, X'012C'; CPYBLAP MSG-TEXT, MAT-P-SNBR, " "; CVTHC MSG-TEXT-HEX, MAT-P-SNBR; CALLI SHOW-MESSAGE, *, .SHOW-MESSAGE; RTX *; /* SHOW A MESSAGE */ DCL SYSPTR .SEPT(6440) BAS(PCO-POINTER); DCL SPC PROCESS-COMMUNICATION-AREA BASPCO; DCL SPCPTR PCO-POINTER DIR; DCL SPCPTR .MSG-ID INIT(MSG-ID); DCL DD MSG-ID CHAR (7) INIT(" "); DCL SPCPTR .MSG-FILE INIT(MSG-FILE); DCL DD MSG-FILE CHAR(20) INIT(" "); DCL SPCPTR .MSG-TEXT INIT(MSG-TEXT); DCL DD MSG-TEXT CHAR(40); DCL DD MSG-TEXT-HEX CHAR(20) DEF(MSG-TEXT) POS(20); DCL SPCPTR .MSG-SIZE INIT(MSG-SIZE); DCL DD MSG-SIZE BIN( 4) INIT(40); DCL SPCPTR .MSG-TYPE INIT(MSG-TYPE); DCL DD MSG-TYPE CHAR(10) INIT("*INFO "); DCL SPCPTR .MSG-QS INIT(MSG-QS); DCL DD MSG-QS CHAR(20) INIT("*REQUESTER "); DCL SPCPTR .MSG-QSN INIT(MSG-QSN); DCL DD MSG-QSN BIN( 4) INIT(1); DCL SPCPTR .REPLY-Q INIT(REPLY-Q); DCL DD REPLY-Q CHAR(20) INIT(" "); DCL SPCPTR .MSG-KEY INIT(MSG-KEY); DCL DD MSG-KEY CHAR( 4); DCL SPCPTR .ERR-CODE INIT(ERR-CODE); DCL DD ERR-CODE BIN( 4) INIT(0); DCL OL QMHSNDM (.MSG-ID, .MSG-FILE, .MSG-TEXT, .MSG-SIZE, .MSG-TYPE, .MSG-QS, .MSG-QSN, .REPLY-Q, .MSG-KEY, .ERR-CODE) ARG; DCL INSPTR .SHOW-MESSAGE; ENTRY SHOW-MESSAGE INT; CALLX .SEPT(4268), QMHSNDM, *; /* SEND MSG TO MSGQ */ B .SHOW-MESSAGE; PEND; OK, still with me ? Good, let's begin... Let's look at the first 5 lines; DCL SPCPTR .MACHINE-ATTR INIT(MACHINE-ATTR); DCL DD MACHINE-ATTR CHAR(2608) BDRY(16); DCL DD MAT-MAX-SIZE BIN(4) DEF(MACHINE-ATTR) POS(1) INIT(2608); DCL DD MAT-ACT-SIZE BIN(4) DEF(MACHINE-ATTR) POS(5); DCL DD MAT-P-SNBR CHAR(10) DEF(MACHINE-ATTR) POS(1125); Those of you know RPG, may actually see some similarity, if you look hard enough. The first line declares a variable of type SPCPTR [a OS/400 space pointer] called '.MACHINE-ATTR' and the pointer is initialized with the address of a something called 'MACHINE-ATTR'. The next 4 lines define what that something called 'MACHINE-ATTR' is. This time the code is declaring a 'scalar-data-object' called 'MACHINE-ATTR' of type CHAR, size 2608, that is on a 16 byte boundary with three other variables defined across it. No, stop right there. Don't move this email to your deleted mail folder. It's not as bad as it looks, really. If you were to think in RPG, look at those four lines again. Look familiar ? What if I was to say that the following RPG is basically the same; D MACHINE-ATTR DS 2608 D MAT-MAX-SIZE 1 4B 0 Inz(2608) D MAT-ACT-SIZE 5 8B 0 D MAT-P-SNBR 16A Overlay(MACHINE-ATTR:1125) And the very first line of the MI program could be written as; D .MACHINE-ATTR S * Inz(%Addr(MACHINE-ATTR)) See, not that bad after all. OK, on with the next bit of code. ENTRY * EXT; MATMATR .MACHINE-ATTR, X'012C'; CPYBLAP MSG-TEXT, MAT-P-SNBR, " "; CVTHC MSG-TEXT-HEX, MAT-P-SNBR; CALLI SHOW-MESSAGE, *, .SHOW-MESSAGE; RTX *; OK, the first line of this section should be easy, it's an entry point - we've finally reached some real code !. The entry point definition in this code is specifying a unnamed entry point, by using '*', and that this entry point will be externally visible, by using the 'EXT' directive. Now, don't get too brave, all subroutines in MI also use the same syntax, as we'll see later, but generally only one will be unnamed (as it's difficult to jump to an unnamed subroutine !) and this one can then normally be assumed to be the program entry point. So we've found the program entry point, what's next ? Well, welcome to your first MI instruction - MATMATR. This instruction is documented in the 'MI Functional Reference' and also in the 'ILE/C MI Library Reference' manuals. Basically it MATerializes Machine ATtRibutes, which really means it retrieves data about the AS/400 from various different locations on the machine and combines them into one huge great block of data. But hold on, what's that X'012C' business ? Well, to limit the amount of data returned from the instruction (this is a beast of an instruction and has over 30 pages for it in the manual), you can select what kind of data is to be materialized. In this case, X'012C' means 'return the vital product info' which among other things will return the serial number. So to recap, the MATMATR instruction is being called to materialize just the vital product information into the .MACHINE_ATTR variable. Then we have the CPYBLAP instruction, again reading the manual is recommended, but basically this instruction means 'CoPY Bytes Left-Adjusted with Pad' so we're moving data from MAT-P-SNBR into the left most part of MSG-TEXT and padding anything left over in MSG-TEXT with " ". To illustrate this, if MAT-P-SNBR contains 'ABCDEF' and MSG-TEXT contains 'XXXXXXXXX', after the instruction CPYBLAP, MSG-TEXT will hold 'ABCDEF ' Following this, we have a CVTHC instruction, ConVerT Hex to Character, which is used in this code to convert the MAT-P-SNBR from hex to character and store the converted data in MSG-TEXT-HEX. Next up is a CALLI instruction, CALL Internal, which calls a subroutine, defined in the source. The syntax for CALLI is; CALLI <entry-point-name> <args> <return-target> So in this code, we're calling subroutine SHOW-MESSAGE, with no args (as specified by using '*'), and the return target from the call to SHOW-MESSAGE is to be the location pointed to by the instruction pointer .SHOW-MESSAGE. This <return-target> operand allows you to jump all over the code, but we'll leave that for another day. Finally in this section of code, we have a RTX *. This means ReTurn External, and in our example code will end the program. AUK, the next 3 lines of code; DCL SYSPTR .SEPT(6440) BAS(PCO-POINTER); DCL SPC PROCESS-COMMUNICATION-AREA BASPCO; DCL SPCPTR PCO-POINTER DIR; Are there to look up the program QMHSNDM via the SEPT, which is the System Entry Point Table - a table on the AS/400 that contains a list of some of the callable IBM API's - from a pointer in the current jobs process communication area. Following this is a series of; DCL SPCPTR .MSG-ID INIT(MSG-ID); DCL DD MSG-ID CHAR (7) INIT(" "); Which are declaring variables, and declaring pointers to these variables. After all the variables have been declared, we hit the following lines of code; DCL OL QMHSNDM (.MSG-ID, .MSG-FILE, .MSG-TEXT, .MSG-SIZE, .MSG-TYPE, .MSG-QS, .MSG-QSN, .REPLY-Q, .MSG-KEY, .ERR-CODE) ARG; Which is setting up the argument list, called QMHSNDM, needed when calling the QMHSNDM API. Next we have; DCL INSPTR .SHOW-MESSAGE; Remember the .SHOW_MESSAGE return target in the CALLI instruction ? Well this is the instruction pointer .SHOW_MESSAGE being defined, but note it's not being initialized with anything, we'll see why in a moment. Finally we have; ENTRY SHOW-MESSAGE INT; CALLX .SEPT(4268), QMHSNDM, *; /* SEND MSG TO MSGQ */ B .SHOW-MESSAGE; Which is the SHOW-MESSAGE subroutine we were calling in the CALLI. This subroutine calls, using the CALLX instruction, the program number 4268 in the SEPT, which turns out to be QMHSNDM, passing the argument list QMHSNDM. The next line of code is one of those weird things in MI programming. It's a branch instruction, branching to instruction pointer .SHOW-MESSAGE, which due to the weirdness on MI actually causes the subroutine to return to the place where it was called from. In our example this is back to the RTX instruction after the CALLI instruction. The very last line of code; PEND; is just there really to keep the compiler happy ! There we have it, one MI program that you understand - crack open those MI manuals, and read some more ! --phil +--- | This is the MI Programmers Mailing List! | To submit a new message, send your mail to MI400@midrange.com. | To subscribe to this list send email to MI400-SUB@midrange.com. | To unsubscribe from this list send email to MI400-UNSUB@midrange.com. | Questions should be directed to the list owner/operator: dr2@cssas400.com +---
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.