But aren't both Example 1 & 2 still passing the address of literal =F'3'
to the called routine, a literal that is only set at assembly time? If
there is a bug in the called routine that allows it to store a value
back at that address at run time, it actually changes the value in the
literal pool of the calling program, and the next time that call is
executed the value may no longer be "3". What's worse, if =F'3' is used
in another totally different context in the calling program, it is
probably using the same fullword "constant" in the literal pool and no
longer getting a value of "3" there either. The "CALL MF=(E,...)"
dynamically builds the list of parameter addresses, but it does not
re-initialize any literal constants referenced by that list. A literal
like =F'3' is just shorthand for the-address-of a DC F'3' created out of
line by the Assembler. It implies there is no intent to store a
different value there, but unless the program is running from read-only
storage, the hardware doesn't prevent overwriting with a different value
if you use the address of =F'3' as the target of a move or store. A
program that overwrites a literal at run time can be very difficult to
debug, because what you see in the listings is misleading.
To be a functional "call by value" there needs to be a temporary
fullword copy of the =F'3' constant made just before the call and that,
or its address, passed on the call. That temporary fullword can't be
used in any other context in the calling program unless it's value is
also set-before-use in that context as well.
That's not to say technique in Example 1 or 2 can't be used when you are
certain that called subroutine does not return a value to that
parameter, just don't be fooled by the =F'3' notation into thinking this
represents a constant that can't be altered by the CALLed program and
that this somehow becomes a call-by-value that prevents the called
routine from overwriting the value. Literals are created and
initialized once at assembly time, not dynamically at execution time.
Example 3 would be a true "call by value", since the value "3" is
rebuilt in storage for each call, and if that fullword is modified by
the called routine it can have no side effects back in the calling
routine. That the CALL is passing an integer in a context where
standard linkage conventions would expect a pointer to the integer is
not an issue as long as the called routine expects that usage.
Joel C Ewing
On 3/30/23 11:09, Frank Swarbrick wrote:
Perhaps the "weird way" could be documented as an appropriate way to pass
arguments by value instead of the standard by reference. Then it would no longer be
weird!
________________________________
From: IBM Mainframe Discussion List <[email protected]> on behalf of Steve
Smith <[email protected]>
Sent: Wednesday, March 29, 2023 9:16 PM
To: [email protected] <[email protected]>
Subject: Re: ASM call by value
Good job. You could have a future as an assembler programmer, because you
pay attention to the details.
Your weird way is interesting because it is correct, but... it is not
idiomatic. So it will freak out most assembler programmers. That's often
not a good thing, but often is not always.
sas
On Wed, Mar 29, 2023 at 7:53 PM Frank Swarbrick <[email protected]>
wrote:
OK, the following three examples all seem to work. I dare say you are
correct about example 1 being unexpected usage of the execute mode. I only
came up with it my looking at an example that wasn’t working and seeing
that putting my value there directly made it work. But it wasn’t meant to
be an example of good coding.
*
CALL1 CALL ,(,),MF=L
*
ISCICS# CEEENTRY MAIN=NO
*
* SEE IF WE'RE RUNNING UNDER CICS BY CALLING @@GETCb
* WITH “VALUE” OF FULLWORD 3.
*
* EXAMPLE 1 (MY WEIRD WAY):
CALL @@GETCB,MF=(E,=F'3')
*
* EXAMPLE 2 (LOAD R1 DIRECTLY WITH ADDRESS OF AREA
* CONTAINING 3, THEN JUST CALL):
LA 1,=F'3'
CALL @@GETCB
*
* EXAMPLE 3 (LOAD REGISTER (2) WITH VALUE,
* THEN CALL WITH THAT REGISTER AS THE ARGUMENT:
LHI 2,3
CALL @@GETCB,((2)),MF=(E,CALL1)
*
CEETERM RC=(15)
*
PPA CEEPPA
CEEDSA ,
CEECAA ,
END ISCICS#
I should note that I am not a systems programmer, or even an “assembler
programmer”. I am a COBOL programmer who dabbles in assembler
occasionally. So I am bound to get a lot of things wrong.
I think I’ll do with #2, since that generates the least amount of code and
is still fairly simple to read.
As for why I used X'0000000010000000200000003’ instead of F'1,2,3' in
another example, it’s because I didn’t know of the availability of using
“comma separated fullword” literals.
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN
--
Joel C. Ewing
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN