Metal C - Parms from Assembler Program

359 views
Skip to first unread message

John Parke

unread,
Aug 6, 2013, 1:57:45 PM8/6/13
to ASSEMBL...@listserv.uga.edu
Hi:

I am having a problem passing a parm from an Assembler program to a Metal-C
created Assembler routine. The main Assembler routine is loading R1 with the
address of the parameter list and then branching to the Metal-C routine. The
Metal-C routine abends with an 0C4. When I look to where R1 is pointing in the
dump, it appears to be where a program would pick up a parm if executed in
batch; i.e, parm=’someparm.’ But the C program is not a “main” program.
Can anybody point me in the right direction? I have read the manual repeatedly
and can’t see where I am going wrong.
I appreciate any help.
John

Steve Comstock

unread,
Aug 6, 2013, 2:15:19 PM8/6/13
to ASSEMBL...@listserv.uga.edu
On 8/6/2013 11:57 AM, John Parke wrote:
> Hi:
>
> I am having a problem passing a parm from an Assembler program to a Metal-C
> created Assembler routine. The main Assembler routine is loading R1 with the
> address of the parameter list and then branching to the Metal-C routine. The
> Metal-C routine abends with an 0C4. When I look to where R1 is pointing in the
> dump, it appears to be where a program would pick up a parm if executed in
> batch; i.e, parm=’someparm.’ But the C program is not a “main†program.
> Can anybody point me in the right direction? I have read the manual repeatedly
> and can’t see where I am going wrong.
> I appreciate any help.
> John
>

Well, it would help to see more of your code.

Precision matters here: R1 should point to an address that
points to the parm data. Is that how you are doing it (your
post implies otherwise)?

-Steve Comstock

Farley, Peter x23353

unread,
Aug 6, 2013, 2:22:54 PM8/6/13
to ASSEMBL...@listserv.uga.edu
Are you passing the parm as if it was coming from a main (i.e., EXEC PGM=) program? If so you have to code the MetalC program as if it were a main routine and include a "main" procedure to be executed on entry.

To use a non-main MetalC routine you have to set up the MetalC stack and environment first, which may be easily done with a MetalC "main stub program" that just invokes your assembler program with an inline __asm CALL or BAS. "Normal" MetalC subroutines have an expectation that their stack is already set up and that they were called by a MetalC program that used MetalC parameter passing conventions and entry/exit logic.

Or you could use the NOPROLOG option (I may not be remembering that option name correctly, but there is something in MetalC that allows you to do that) for the MetalC subroutine and code the subroutine entry/exit logic yourself using a macro or inline __asm. BTDT, works a charm.

Does that help?

Peter

-----Original Message-----
From: IBM Mainframe Assembler List [mailto:ASSEMBL...@LISTSERV.UGA.EDU] On Behalf Of John Parke
Sent: Tuesday, August 06, 2013 1:58 PM
To: ASSEMBL...@LISTSERV.UGA.EDU
Subject: Metal C - Parms from Assembler Program

Hi:

I am having a problem passing a parm from an Assembler program to a Metal-C
created Assembler routine. The main Assembler routine is loading R1 with the
address of the parameter list and then branching to the Metal-C routine. The
Metal-C routine abends with an 0C4. When I look to where R1 is pointing in the
dump, it appears to be where a program would pick up a parm if executed in
batch; i.e, parm=’someparm.’ But the C program is not a “main†program.
Can anybody point me in the right direction? I have read the manual repeatedly
and can’t see where I am going wrong.
I appreciate any help.
John

This message and any attachments are intended only for the use of the addressee and may contain information that is privileged and confidential. If the reader of the message is not the intended recipient or an authorized representative of the intended recipient, you are hereby notified that any dissemination of this communication is strictly prohibited. If you have received this communication in error, please notify us immediately by e-mail and delete the message and any attachments from your system.

John Parke

unread,
Aug 6, 2013, 2:33:52 PM8/6/13
to ASSEMBL...@listserv.uga.edu
Well, here is what I have:

Assembler program (hand written):

LA R1,parmlist
L R15,=V(INTERF#C)
BALR R14,R15

parmlist DS 0FD
DC AD(inputBufferPtr)
DC AD(ouputBufferPtr)
DC AD(inputBufferLength)
DC AD(inputBufferLength)

C Program:
#pragma prolog(interfd,"ZPROLOG")
#pragma epilog(interfd,"ZEPILOG")
typedef struct
{
void *inputBufferPtr;
void *ouputBufferPtr;
int inputBufferLength;
int outputBufferLength;
int level;
int feof;
int entry;
} mtl_parm_t;

int interfd(mtl_parm_t *plist)
{

if (plist ->entry == 1)
....

I have provided prolog code:

LARL R15,@@LIT@2
Using @@LIT@2,R15
STMG R14,R12,8(R13)
LGR R9,R1 Save R1
LGR R2,R0
LGHI R0,312
LA R1,1
SLL R1,20
AGR R0,R1
Storage Obtain
LGR R15,R1
STG R15,136(,R13) Addr of Next Savearea
STG R13,128(,R15) Addr of Previous Savearea
LGR R13,R15 Point R13 to this DSA
LGR R0,R2 WSA address - Amode 64
LGR R1,R9 Restore R1

Maybe I am way off base.

John Parke

unread,
Aug 6, 2013, 2:48:25 PM8/6/13
to ASSEMBL...@listserv.uga.edu
Perhaps that is where I am going wrong.

Steve Comstock

unread,
Aug 6, 2013, 3:43:54 PM8/6/13
to ASSEMBL...@listserv.uga.edu
On 8/6/2013 12:48 PM, John Parke wrote:
> Perhaps that is where I am going wrong.
>

Well, I don't know Metal C linkages, but
some things look suspect to me:

* your parm list is 64-bit addresses - does
Metal C work with that as default?

* as mentioned, you might need to have R1 point
to a pointer to your parm list: and the pointer
should be a 31-bit address

so maybe

LA R1,Parms
.
.
.
Parms dc a(parmlist)


* Your prolog disturbs me a bit; although I
am not aware of the Metal C interface it
seems to go against several conventions:

LARL R15,@@LIT@2
Using @@LIT@2,R15
STMG R14,R12,8(R13)
LGR R9,R1 Save R1

LGR R2,R0 <-- Save R0
LGHI R0,312 <-- Load x'0138' into R0, pad left with binary 0's
LA R1,1 <-- Load x'00000001' into right hand word (RHW) of R0
SLL R1,20 <-- this shift results in x'00100000' in RHW of R0
AGR R0,R1 <-- R0 now contains x'00000000 00100138' (why?)
<-- and why such a convoluted path to get, essentially,
<-- a constant result?

Storage Obtain <-- what parameters are you specifying?

.
.
.

-Steve Comstock

John Parke

unread,
Aug 6, 2013, 3:54:22 PM8/6/13
to ASSEMBL...@listserv.uga.edu
On Tue, 6 Aug 2013 13:43:54 -0600, Steve Comstock <st...@trainersfriend.com>
wrote:
Some good questions. If you compile C code with LP64 then you get Amode 64,
so 8 byte addresses are correct. The 312 into R0 is the length of my DSA
(prolog code is from IBM sample). The value in R1 is the called programs
DSA, in this case 2**20. So the total Storage Obtain will be for 2**20 +
312.

STORAGE OBTAIN,LENGTH=(0),BNDRY=PAGE

I thought the problem was PLIST(HOST) vs. PLIST(OS). This tells the compiler
whether to use normal "main" passing of R1, i.e. to args. I tried PLIST(OS),
but it is ignored when IPA is used. Why? Who knows.

Convoluted? Well it is IBM :-)

Tom Marchant

unread,
Aug 6, 2013, 4:07:01 PM8/6/13
to ASSEMBL...@listserv.uga.edu
On Tue, 6 Aug 2013 13:57:45 -0400, John Parke wrote:

>Hi:
>
>The main Assembler routine is loading R1 with the
>address of the parameter list and then branching to the Metal-C routine.

Ok so far.

>The
>Metal-C routine abends with an 0C4. When I look to where R1 is pointing
>in the
>dump, it appears to be where a program would pick up a parm if executed in
>batch; i.e, parm=’someparm.’

What do you mean by that? The system uses standard linkage to
provide the PARM from the JCL to the program. Register 1 contains
the address of a parameter list. The parameter list is one fullword
containing the address of the parameter.

>But the C program is not a “main” program.

That doesn't make any difference for z/OS linkage conventions.

>I have read the manual repeatedly

What manual is that? The Assembler Programmer's Guide, chapter 2?
Preferably release 12 or later.

--
Tom Marchant

Tom Marchant

unread,
Aug 6, 2013, 4:25:34 PM8/6/13
to ASSEMBL...@listserv.uga.edu
On Tue, 6 Aug 2013 14:33:52 -0400, John Parke wrote:

>I have provided prolog code:
>
>LARL R15,@@LIT@2
>Using @@LIT@2,R15

Why do you set R15 here, before saving the caller's registers? Note
that register 15 is not a good one to use for a base register.

>STMG R14,R12,8(R13)
>LGR R9,R1 Save R1
>LGR R2,R0
>LGHI R0,312
>LA R1,1
>SLL R1,20
>AGR R0,R1
>Storage Obtain
>LGR R15,R1

In case STORAGE didn't clobber your base register, the LGR did,
but the USING is still in effect.

>STG R15,136(,R13) Addr of Next Savearea
>STG R13,128(,R15) Addr of Previous Savearea
>LGR R13,R15 Point R13 to this DSA

It looks like you intend to use F4SA format to save your caller's
registers, but you have not marked your save area with "F4SA" to
indicate that you have done that.

--
Tom Marchant

John Parke

unread,
Aug 6, 2013, 4:28:46 PM8/6/13
to ASSEMBL...@listserv.uga.edu
On Tue, 6 Aug 2013 16:07:01 -0400, Tom Marchant <m42tom-...@YAHOO.COM>
wrote:
Manual(s) Read:
z/OS V1R13.0 Metal C Programming Guide and Reference
z/OS V1R13.0 XL C/C++ User’s Guide

The program I am referring to is written in Assembler and is calling a
metal-C subroutine (assembled with HLASM).

I execute the program like this:

//TESTDRV EXEC PGM=TESTDRV <= hand written test program in ASM

This program is supposed to set up the parm list address then branch to
Metal-C program. When the program TESTDRV is executed it abends with an 0C4.

I looked into the dump and saw R1 value of something like 00006FF8.

I thought that this address looked like it was rather low in storage, so I
re-submitted the job with:

//TESTDRV EXEC PGM=TESTDRV,PARM='someparm' <= not the way I want to
execute

Now when the program abends, I see the text "someparm" at the address
(preceded by half word length field).

This leads me to believe that the parm list is not being passed correctly.

I confirmed the instruction being executed at abend:

ACTIVE LOAD MODULE ADDRESS=1E800000 OFFSET=0000A78E
NAME=TESTDRV
DATA AT PSW 1E80A788 - E3401000 0004E55C 40200001

Which corresponds to:
000000E8 E340 1000 0004 00000000 183 LG 4,@79plist
000000EE E55C 4020 0001 00000020 184 CHSI 32(4),1


Thanks for the help and suggestions.

John

John Parke

unread,
Aug 6, 2013, 4:35:58 PM8/6/13
to ASSEMBL...@listserv.uga.edu
On Tue, 6 Aug 2013 16:25:34 -0400, Tom Marchant <m42tom-...@YAHOO.COM>
wrote:
Tom:

The prolog code I am using is sample code from IBM. R15 is not a good idea,
I agree. The LGR R9,R1 was my attempt to save parm list address (act of
desperation). I later attempt to restore it with LGR R1,R9.

The sample code executes:

LLILH 12,X'C6F4'
OILL 12,X'E2C1'
ST 12,4(,13)

Which is IBM's way of marking savearea with "F4SA".

Thanks,

John

John Parke

unread,
Aug 6, 2013, 7:29:44 PM8/6/13
to ASSEMBL...@listserv.uga.edu
Finally found the problem. It was a user error. The main driver program was
the one that abended. It starts in AMODE=64 and bombed on a STMG. Not sure
why.

Thanks all.

Martin Truebner

unread,
Aug 7, 2013, 3:15:02 AM8/7/13
to ASSEMBL...@listserv.uga.edu
John,

(I was about to ask for the source of the caller- but you found it)

now:

>> The main driver program was the one that abended.

and

>> It starts in AMODE=64 and bombed on a STMG. Not sure why.

Is it so that the hosting operating system you are using does
guarantee that it calls you in the AMODE you specify at link/binder
time?

If not I would insert a SAM64 and make sure that all registers have
proper values in the high word (once you get high).

--
Martin

Pi_cap_CPU - all you ever need around MWLC/SCRT/CMT in z/VSE
more at http://www.picapcpu.de

John Parke

unread,
Aug 7, 2013, 7:51:11 AM8/7/13
to ASSEMBL...@listserv.uga.edu
On Wed, 7 Aug 2013 09:15:02 +0200, Martin Truebner <Mar...@pi-sysprog.de>
wrote:
Martin:

Thanks to you and all for your suggestions. It's great that people find the
time to help.

Kirk Talman

unread,
Aug 7, 2013, 12:59:22 PM8/7/13
to ASSEMBL...@listserv.uga.edu
IBM Mainframe Assembler List <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
08/06/2013 04:35:58 PM:

> From: John Parke <par...@BELLSOUTH.NET>

> LLILH 12,X'C6F4'
> OILL 12,X'E2C1'
> ST 12,4(,13)

which is ok for z900. if you have a z9, this does the trick:

LLILF 12,X'C6F4E2C1'
ST 12,4(,13)

-----------------------------------------
The information contained in this communication (including any
attachments hereto) is confidential and is intended solely for the
personal and confidential use of the individual or entity to whom
it is addressed. If the reader of this message is not the intended
recipient or an agent responsible for delivering it to the intended
recipient, you are hereby notified that you have received this
communication in error and that any review, dissemination, copying,
or unauthorized use of this information, or the taking of any
action in reliance on the contents of this information is strictly
prohibited. If you have received this communication in error,
please notify us immediately by e-mail, and delete the original
message. Thank you

John Parke

unread,
Aug 7, 2013, 2:04:58 PM8/7/13
to ASSEMBL...@listserv.uga.edu
Thanks!

-----Original Message-----
From: IBM Mainframe Assembler List [mailto:ASSEMBL...@LISTSERV.UGA.EDU]

John Parke

unread,
Aug 7, 2013, 2:06:55 PM8/7/13
to ASSEMBL...@listserv.uga.edu
The Metal-C option doesn't seem very intuitive. Maybe if more examples were
supplied?

Lloyd Fuller

unread,
Aug 7, 2013, 8:42:21 AM8/7/13
to ASSEMBL...@listserv.uga.edu
The C program will treat R1 as 64-bits so you need to clear the high part of the register.  Also R15 (the entry to the C program) must be 64-bit address and R14 (your return) needs to be 64-bit.
 
We are successfully calling a 64-bit Metal C set of programs from assembler without issue after a lot of debugging to cleanup the assembler code which had been calling the same set of programs in 31-bit mode.
 
Lloyd


>________________________________
> From: John Parke <par...@BELLSOUTH.NET>
>To: ASSEMBL...@LISTSERV.UGA.EDU
>Sent: Tuesday, August 6, 2013 4:28 PM


>Subject: Re: Metal C - Parms from Assembler Program
>
>

Tom Marchant

unread,
Aug 12, 2013, 11:40:12 AM8/12/13
to ASSEMBL...@listserv.uga.edu
On Tue, 6 Aug 2013 16:35:58 -0400, John Parke wrote:

>The prolog code I am using is sample code from IBM...
>
>The sample code executes:
>
>LLILH 12,X'C6F4'
>OILL 12,X'E2C1'
>ST 12,4(,13)
>
>Which is IBM's way of marking savearea with "F4SA".

This may be the way that Metal C does it, but it is not the way it is
documented in the Assembler Services Guide, which is the authoritative
reference for linkage conventions.

The above fragment might do the correct thing, depending upon when the
above sequence is included in the code. I know that Metal C was doing
it incorrectly a few years ago and it is my understanding that their
code has since been changed, but I don't know when.

"F4SA" must be stored in the new save area. In other words, the above
sequence does the correct thing only if it is AFTER register 13 is
loaded with the address of the new save area. If you store it in the
caller's save area, you will cause a problem when your caller tries to
return to its caller.

--
Tom Marchant

Steve Comstock

unread,
Aug 12, 2013, 12:37:44 PM8/12/13
to ASSEMBL...@listserv.uga.edu
On 8/12/2013 9:40 AM, Tom Marchant wrote:
> On Tue, 6 Aug 2013 16:35:58 -0400, John Parke wrote:
>
>> The prolog code I am using is sample code from IBM...
>>
>> The sample code executes:
>>
>> LLILH 12,X'C6F4'
>> OILL 12,X'E2C1'
>> ST 12,4(,13)
>>
>> Which is IBM's way of marking savearea with "F4SA".
>
> This may be the way that Metal C does it, but it is not the way it is
> documented in the Assembler Services Guide, which is the authoritative
> reference for linkage conventions.
>
> The above fragment might do the correct thing, depending upon when the
> above sequence is included in the code. I know that Metal C was doing
> it incorrectly a few years ago and it is my understanding that their
> code has since been changed, but I don't know when.
>
> "F4SA" must be stored in the new save area.

Really? "Must"? Is there anything that won't work correctly
if I omit that string? I think not.

--

Kind regards,

-Steve Comstock
The Trainer's Friend, Inc.

303-355-2752
http://www.trainersfriend.com

* To get a good Return on your Investment, first make an investment!
+ Training your people is an excellent investment

* Try our tool for calculating your Return On Investment
for training dollars at
http://www.trainersfriend.com/ROI/roi.html

Tom Marchant

unread,
Aug 12, 2013, 3:14:16 PM8/12/13
to ASSEMBL...@listserv.uga.edu
On Mon, 12 Aug 2013 10:37:44 -0600, Steve Comstock wrote:

>On 8/12/2013 9:40 AM, Tom Marchant wrote:
>>
>> "F4SA" must be stored in the new save area.
>
>Really? "Must"? Is there anything that won't work correctly
>if I omit that string? I think not.

What I meant was that when a program marks the format of the save area
that it used to save its caller's registers, it must do so in the new
save area, not in the caller's save area.

Consider the case where A calls B, then B calls C. If B saved A's
registers in standard 72-byte format, offset 4 of B's save area
contains the address of A's save area. If C then saves B's registers
in F4SA format, C marks its own save area with "F4SA". If it were to
mark B's save area with "F4SA", then B would not be able to find the
save area that it used to save A's registers.

The only thing that won't work correctly if it is omitted is any
program that has to follow the save areas to determine the calling
sequence, such as a dump formatter. We rely on it in Abend-AID.

--
Tom Marchant
Abend-AID development
Compuware
Reply all
Reply to author
Forward
0 new messages