Calling C functions from HLASM

164 views
Skip to first unread message

Dave Clark

unread,
Jun 6, 2023, 11:27:13 AM6/6/23
to ASSEMBL...@listserv.uga.edu
Would someone show me an example of calling a C function from
HLASM? I tried asking ChatGPT and got the following. I don't see how
this will link from HLASM to the C function.

PRINT NOGEN
TITLE 'HLASM Calling ldap_open'

USING *,12
LR 12,15
LA 15,SAVEAREA

ENTRY START

SAVEAREA DS 18F

LDAP_OPEN EQU *
DROP 0
LR 15,13
BALR 14,15
USING LDAP_OPEN,14
DROP 1
L 1,LDAP_HOSTNAME
L 2,LDAP_PORT
L 3,LDAP_RESULT
BALR 14,15
USING LDAP_OPEN,14
DROP 0
L 15,SAVEAREA
RETURN (14,12),RC=0

START DS 0H
...
... ; HLASM code
...
LA 1,LDAP_HOSTNAME
LA 2,LDAP_PORT
LA 3,LDAP_RESULT
BALR 14,15
USING LDAP_OPEN,14
...
... ; Continue with HLASM code
...
PRINT NOGEN
END START

Sincerely,

Dave Clark
--
int.ext: 91078
direct: (937) 531-6378
home: (937) 751-3300

Winsupply Group Services
3110 Kettering Boulevard
Dayton, Ohio 45439 USA
(937) 294-5331



*********************************************************************************************
This email message and any attachments is for use only by the named
addressee(s) and may contain confidential, privileged and/or proprietary
information. If you have received this message in error, please
immediately notify the sender and delete and destroy the message and all
copies. All unauthorized direct or indirect use or disclosure of this
message is strictly prohibited. No right to confidentiality or privilege
is waived or lost by any error in transmission.
*********************************************************************************************

Rick Troth

unread,
Jun 6, 2023, 11:55:35 AM6/6/23
to ASSEMBL...@listserv.uga.edu
Forgive me if you already know ...

C requires a stack (at least), sometimes more for sake of minimizing the
surprise factor (for developers who think it's always a Unix thing).
After that, there's not much difference (in my experience) to call a C
routine than to call an assembler routine.
There's nothing in the code you got from ChatGPT which would instantiate
the expected stack and supplemental environment.

Have you called COBOL from assembler? Similar game there, and similar
instantiation req (LE and whatever it has evolved into these days).

I hope this helps.

-- R; <><

John McKown

unread,
Jun 6, 2023, 12:10:27 PM6/6/23
to ASSEMBL...@listserv.uga.edu
I really hesitate to mention this, being as it it mine, not really very
good code, but https://github.com/JohnArchieMckown/utilities-1/find/master

And look at SKELETON.s file. Plesse be kind. The entire program is LE
enabled, with LE startup and termination macros, from IBM.

Farley, Peter

unread,
Jun 6, 2023, 12:14:19 PM6/6/23
to ASSEMBL...@listserv.uga.edu
From the XLC/C++ Programming guide (V2.3), chapter 20, "Combining C or C++ and Assembler programs", page 281 in the PDF, page number 245:

Use the Language Environment CEEENTRY prolog macro with MAIN=YES
specified so that z/OS Language Environment is initialized.
Once you are in the assembler program, you can call other C or C++ programs
from the assembler.

Peter

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.

Colin Paice

unread,
Jun 6, 2023, 12:17:02 PM6/6/23
to ASSEMBL...@listserv.uga.edu
It is documented Combining C or C++ and Assembler programs
<https://www.ibm.com/docs/en/zos/2.5.0?topic=cc-combining-c-c-assembler-programs>
which I have used in the past
Colin

Farley, Peter

unread,
Jun 6, 2023, 12:18:42 PM6/6/23
to ASSEMBL...@listserv.uga.edu
Don't be so modest John - that is decent, maintainable code from where I sit, and a fine example of what needs to be done.

Thanks for sharing.

Peter

-----Original Message-----
From: IBM Mainframe Assembler List <ASSEMBL...@LISTSERV.UGA.EDU> On Behalf Of John McKown
Sent: Tuesday, June 6, 2023 12:10 PM
To: ASSEMBL...@LISTSERV.UGA.EDU
Subject: Re: Calling C functions from HLASM

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.

Dave Clark

unread,
Jun 6, 2023, 12:22:39 PM6/6/23
to ASSEMBL...@listserv.uga.edu
"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/06/2023 11:55:30 AM:
> Forgive me if you already know ...
>
> C requires a stack (at least), sometimes more for sake of minimizing the

> surprise factor (for developers who think it's always a Unix thing).
> After that, there's not much difference (in my experience) to call a C
> routine than to call an assembler routine.
> There's nothing in the code you got from ChatGPT which would instantiate

> the expected stack and supplemental environment.

I'm not a C programmer. I know some things about calling C from
RPG/ILE (in terms of null-terminated strings, etc). So, no, I did not
know that... something to learn.


> Have you called COBOL from assembler? Similar game there, and similar
> instantiation req (LE and whatever it has evolved into these days).

Yes, I have called COBOL. However, calling COBOL means you have
an up to 8-character internal name that matches an external name I can
find in the system or user library. C function names can be longer than
that and, therefore, can't possibly match anything in my system libraries.

That is the part I don't see an example of -- how to connect a C
function name to the object that would be found in the system library. In
RPG/ILE you create a procedure prototype that connects an internal RPG
procedure name to the external C function name. How do I do something
equivalent to that in HLASM?


Sincerely,

Dave Clark
--
int.ext: 91078
direct: (937) 531-6378
home: (937) 751-3300

Winsupply Group Services
3110 Kettering Boulevard
Dayton, Ohio 45439 USA
(937) 294-5331



>

Dave Clark

unread,
Jun 6, 2023, 12:48:09 PM6/6/23
to ASSEMBL...@listserv.uga.edu
"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/06/2023 12:10:08 PM:
> I really hesitate to mention this, being as it it mine, not really very
> good code, but https://urldefense.com/v3/__https://github.com/
> JohnArchieMckown/utilities-1/find/master__;!!E0nbmg29qrX0lQ!
>
aj5Q4OBH5sqMRPmyCDBHnqp2WItdttjwGs4WQfKLwd4jwNLv470EZiQTuFl_8PzRd5TuAxPN9RAnigLctAz4cHfvpgDjYS4$
>
> And look at SKELETON.s file. Plesse be kind. The entire program is LE
> enabled, with LE startup and termination macros, from IBM.


I take it that LE takes care of connecting the long C function
names to the C runtime libraries?

Farley, Peter

unread,
Jun 6, 2023, 1:04:51 PM6/6/23
to ASSEMBL...@listserv.uga.edu
Many of the "long name" functions have 8-byte names as alias's. To call C functions directly with their mixed-case "long name" I believe you have to use DLL calling conventions and GOFF object output for the HLASM program, and that's another whole can of worms which I believe is also addressed in the Programmer's Guide (have not read those chapters myself though).

If you're curious, you will need to do some serious reading.

Note that in John's SKELETON.s assembler source, he is just calling C function sprintf() with a VCON for name SPRINTF, so no long-name mangling required there.

Peter

-----Original Message-----
From: IBM Mainframe Assembler List <ASSEMBL...@LISTSERV.UGA.EDU> On Behalf Of Dave Clark
Sent: Tuesday, June 6, 2023 12:48 PM
To: ASSEMBL...@LISTSERV.UGA.EDU
Subject: Re: Calling C functions from HLASM

"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/06/2023 12:10:08 PM:
> I really hesitate to mention this, being as it it mine, not really very
> good code, but https://github.com/JohnArchieMckown/utilities-1/find/master
>
> And look at SKELETON.s file. Plesse be kind. The entire program is LE
> enabled, with LE startup and termination macros, from IBM.


I take it that LE takes care of connecting the long C function
names to the C runtime libraries?


Sincerely,

Dave Clark
--
int.ext: 91078
direct: (937) 531-6378
home: (937) 751-3300

Winsupply Group Services
3110 Kettering Boulevard
Dayton, Ohio 45439 USA
(937) 294-5331




*********************************************************************************************
This email message and any attachments is for use only by the named
addressee(s) and may contain confidential, privileged and/or proprietary
information. If you have received this message in error, please
immediately notify the sender and delete and destroy the message and all
copies. All unauthorized direct or indirect use or disclosure of this
message is strictly prohibited. No right to confidentiality or privilege
is waived or lost by any error in transmission.
*********************************************************************************************

Charles Mills

unread,
Jun 6, 2023, 1:29:48 PM6/6/23
to ASSEMBL...@listserv.uga.edu
I have never done what you are asking about. (Done lots of the opposite: C++
calling HLASM.) I recall that there is decent doc in one of the manuals.

If you need long name support can't you do that in HLASM with GOFF? If not,
you need to use the C prelinker which mushes long names into short.

As others have alluded, this is not a quickie question. You are going to
need some serious study.

Charles


-----Original Message-----
From: IBM Mainframe Assembler List [mailto:ASSEMBL...@LISTSERV.UGA.EDU]
On Behalf Of Dave Clark
Sent: Tuesday, June 6, 2023 9:48 AM
To: ASSEMBL...@LISTSERV.UGA.EDU
Subject: Re: Calling C functions from HLASM

Rick Troth

unread,
Jun 6, 2023, 1:33:40 PM6/6/23
to ASSEMBL...@listserv.uga.edu
Ah!
I see. Yeah, that.


On 6/6/23 12:22, Dave Clark wrote:
> Yes, I have called COBOL. However, calling COBOL means you have
> an up to 8-character internal name that matches an external name I can
> find in the system or user library. C function names can be longer than
> that and, therefore, can't possibly match anything in my system libraries.


Start by using just 8-character function names in C.

Also see what Peter said.

I'm personally not keen on name mangling.
There will always be more names in "long name space" than in "short name
space", so the mangled names amount to a hash and hashes are, by
definition, prone to collisions.

-- R; <><

Dave Clark

unread,
Jun 6, 2023, 1:34:04 PM6/6/23
to ASSEMBL...@listserv.uga.edu
"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/06/2023 01:04:43 PM:
> Many of the "long name" functions have 8-byte names as alias's.

OK, so how would I find out the aliases for these C functions?

ldap_init
ldap_open
ldap_bind_s
ldap_simple_bind_s
ldap_unbind_s
ldap_search_s
etc.

Rick Troth

unread,
Jun 6, 2023, 1:42:19 PM6/6/23
to ASSEMBL...@listserv.uga.edu
Have you considered wrapping the LDAP routines with your own C code?
Might make it easier. Yeah, longer execution code path, but if it gets
you in control then it's worth it.

-- R; <><

Dave Clark

unread,
Jun 6, 2023, 1:50:48 PM6/6/23
to ASSEMBL...@listserv.uga.edu
"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/06/2023 01:42:10 PM:
> Have you considered wrapping the LDAP routines with your own C code?
> Might make it easier. Yeah, longer execution code path, but if it gets
> you in control then it's worth it.


We don't have the C compiler. We just have the provided C runtime
libraries.

Farley, Peter

unread,
Jun 6, 2023, 1:59:38 PM6/6/23
to ASSEMBL...@listserv.uga.edu
GIYF. Using "site:ibm.com ldap_init", the fourth hit leads to IBM documentation for the z/OS V2.3 "IBM Tivoli Directory Server for z/OS", and one of the pages there ("Compiling, linking, and running a program") addresses your questions:

https://www.ibm.com/docs/en/zos/2.3.0?topic=programming-compiling-linking-running-program#compiling

Looks like the C DLL is in the "/usr/lib" directory in the Unix file system (file name GLDCLDAP) and your binder step needs a "side deck" named GLDCLDAP.x to get the DLL stub into your executable. No PDS or PDSE library for the executable code, just the Unix copy.

Welcome to the future.

As I said previously, for how to actually USE that DLL from HLASM you need to do some serious reading. There may, in fact, be no such specific documentation, in which case you would have to open a support ticket with IBM to get help.

Peter

-----Original Message-----
From: IBM Mainframe Assembler List <ASSEMBL...@LISTSERV.UGA.EDU> On Behalf Of Dave Clark
Sent: Tuesday, June 6, 2023 1:34 PM
To: ASSEMBL...@LISTSERV.UGA.EDU
Subject: Re: Calling C functions from HLASM

Swarbrick, Frank

unread,
Jun 6, 2023, 2:09:33 PM6/6/23
to ASSEMBL...@listserv.uga.edu
It looks like CEEPCALL is used to call DLL functions.
However I've not gotten it to work yet. This is what I've tried for printf():

prntit2 ceeentry main=YES
ceepcall printf,(fmtstr,3,str),,mf=(E,PARMS3)
ceeterm
ppa ceeppa ,
fmtstr dc c'Test %d: %s.',x'0'
str dc c'one two three',x'0'
ceedsa ,
parms3 ceepcall ,(0,0,0),mf=L
ceecaa ,
end prntit2

It compiles and links (binds), but when I run it the output is "ECTEXT".

-----Original Message-----
From: IBM Mainframe Assembler List <ASSEMBL...@LISTSERV.UGA.EDU> On Behalf Of Farley, Peter
Sent: Tuesday, June 6, 2023 11:59 AM
To: ASSEMBL...@LISTSERV.UGA.EDU
Subject: [EXTERNAL] Re: Calling C functions from HLASM

GIYF. Using "site:ibm.com ldap_init", the fourth hit leads to IBM documentation for the z/OS V2.3 "IBM Tivoli Directory Server for z/OS", and one of the pages there ("Compiling, linking, and running a program") addresses your questions:

https://urldefense.com/v3/__https://www.ibm.com/docs/en/zos/2.3.0?topic=programming-compiling-linking-running-program*compiling__;Iw!!EP3Ar9QBfU06DzGV!B3gdk9L4qNt8hnODo9FAbhU7yVG9XzojXagK_L4Z_bLfQQjV477tMUQPZrCXoMdK2IQ9OaPxvH7E9BYXXAdLLT6741DOzIp8w1Nrxs_XFJc$
The information contained in this electronic communication and any document attached hereto or transmitted herewith is confidential and intended for the exclusive use of the individual or entity named above. If the reader of this message is not the intended recipient or the employee or agent responsible for delivering it to the intended recipient, you are hereby notified that any examination, use, dissemination, distribution or copying of this communication or any part thereof is strictly prohibited. If you have received this communication in error, please immediately notify the sender by reply e-mail and destroy this communication. Thank you.

Dave Clark

unread,
Jun 6, 2023, 2:16:45 PM6/6/23
to ASSEMBL...@listserv.uga.edu
"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/06/2023 02:09:21 PM:
> It looks like CEEPCALL is used to call DLL functions.
> However I've not gotten it to work yet. This is what I've tried for
printf():
>
> prntit2 ceeentry main=YES
> ceepcall printf,(fmtstr,3,str),,mf=(E,PARMS3)
> ceeterm
> ppa ceeppa ,
> fmtstr dc c'Test %d: %s.',x'0'
> str dc c'one two three',x'0'
> ceedsa ,
> parms3 ceepcall ,(0,0,0),mf=L
> ceecaa ,
> end prntit2
>
> It compiles and links (binds), but when I run it the output is "ECTEXT".


That is very helpful. Thank you.

Swarbrick, Frank

unread,
Jun 6, 2023, 2:20:46 PM6/6/23
to ASSEMBL...@listserv.uga.edu
I got it working. Didn't properly allocate automatic (stack) storage for the parameters in the earlier example.

prntit2 ceeentry main=YES,auto=AUTOSZ
ceepcall printf,(fmtstr,3,str),,mf=(E,PARMS3)
ceeterm
ppa ceeppa ,
fmtstr dc c'Test %d: %s.',x'0'
str dc c'one two three',x'0'
ceedsa ,
parms3 ceepcall ,(0,0,0),mf=L
autoend ds 0d
autosz equ autoend-ceedsa
ceecaa ,
end prntit2

I don't have connectivity to LDAP as far as I know, so I can't test that out.

-----Original Message-----
From: IBM Mainframe Assembler List <ASSEMBL...@LISTSERV.UGA.EDU> On Behalf Of Dave Clark
Sent: Tuesday, June 6, 2023 12:17 PM
To: ASSEMBL...@LISTSERV.UGA.EDU
Subject: [EXTERNAL] Re: Calling C functions from HLASM

Dave Clark

unread,
Jun 6, 2023, 2:43:09 PM6/6/23
to ASSEMBL...@listserv.uga.edu
"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/06/2023 02:20:37 PM:
> I got it working. Didn't properly allocate automatic (stack)
> storage for the parameters in the earlier example.
>
> prntit2 ceeentry main=YES,auto=AUTOSZ
> ceepcall printf,(fmtstr,3,str),,mf=(E,PARMS3)
> ceeterm
> ppa ceeppa ,
> fmtstr dc c'Test %d: %s.',x'0'
> str dc c'one two three',x'0'
> ceedsa ,
> parms3 ceepcall ,(0,0,0),mf=L
> autoend ds 0d
> autosz equ autoend-ceedsa
> ceecaa ,
> end prntit2
>
> I don't have connectivity to LDAP as far as I know, so I can't test that
out.


Excellent! Excellent! That is in-line with the statement earlier
that a stack is required for calling C functions. Now I just hope that I
actually have the runtime library for LDAP and it wasn't just compiled
into the LDAP client that IBM provided us.

By the way... This is a z/VSE shop we're talking about here. ;-)

Swarbrick, Frank

unread,
Jun 6, 2023, 2:50:09 PM6/6/23
to ASSEMBL...@listserv.uga.edu
I don't believe VSE supports DLLs, so this may be all for naught. Unless VSE has a non-DLL LDAP library.

-----Original Message-----
From: IBM Mainframe Assembler List <ASSEMBL...@LISTSERV.UGA.EDU> On Behalf Of Dave Clark
Sent: Tuesday, June 6, 2023 12:43 PM
To: ASSEMBL...@LISTSERV.UGA.EDU
Subject: [EXTERNAL] Re: Calling C functions from HLASM

Dave Clark

unread,
Jun 6, 2023, 3:04:44 PM6/6/23
to ASSEMBL...@listserv.uga.edu
"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/06/2023 02:49:57 PM:
> I don't believe VSE supports DLLs, so this may be all for naught.
> Unless VSE has a non-DLL LDAP library.


Oh, you're correct that z/VSE does not have a Linux file system
where traditional DLL link libraries would be found. I also just checked
my system and there is no CEEPCALL macro. I have all the other macros you
referenced. Hmmm...

Swarbrick, Frank

unread,
Jun 6, 2023, 3:07:19 PM6/6/23
to ASSEMBL...@listserv.uga.edu
DLLs on z/OS can be stored in PDSEs as well. But that does not help you for z/VSE...

-----Original Message-----
From: IBM Mainframe Assembler List <ASSEMBL...@LISTSERV.UGA.EDU> On Behalf Of Dave Clark
Sent: Tuesday, June 6, 2023 1:05 PM
To: ASSEMBL...@LISTSERV.UGA.EDU
Subject: [EXTERNAL] Re: Calling C functions from HLASM

Dave Clark

unread,
Jun 6, 2023, 3:38:00 PM6/6/23
to ASSEMBL...@listserv.uga.edu
"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/06/2023 03:07:14 PM:
> DLLs on z/OS can be stored in PDSEs as well. But that does not help
> you for z/VSE...


I have PDSes for 3rd-party products. But, you're correct that IBM
doesn't use them on z/VSE. For source and executables IBM supports only
the VSE Librarian (LIBR) libraries.

Dave Clark

unread,
Jun 7, 2023, 4:08:23 PM6/7/23
to ASSEMBL...@listserv.uga.edu
"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/06/2023 02:43:04 PM:
> By the way... This is a z/VSE shop we're talking about here. ;-)


I got the call to a C function working in my assembler program. I
have to build the parameter list myself and use a V-constant to call the
function, though, and that works with no extra effort as long as the
function is a standalone executable or object module.

What's used in z/VSE to simulate DLL's is an object deck with XSD
entries in it for the list of functions in the single object deck. Then
you have to use the LE prelinker (EDCPRLK) to resolve those XSD entries --
which allows the V-constant to pick up the address of the function
embedded in the single object deck.

Dave Clark

unread,
Jun 7, 2023, 4:18:01 PM6/7/23
to ASSEMBL...@listserv.uga.edu
"IBM Mainframe Assembler List" <ASSEMBL...@LISTSERV.UGA.EDU> wrote on
06/07/2023 04:08:17 PM:
> What's used in z/VSE to simulate DLL's is an object deck with
XSD
> entries in it for the list of functions in the single object deck. Then

> you have to use the LE prelinker (EDCPRLK) to resolve those XSD entries
--
> which allows the V-constant to pick up the address of the function
> embedded in the single object deck.


Oh, by the way... The above still only works with the short name
for a C function (using #pragma map). So even if there are XSD entries
for the long name, the VSE linkage editor won't resolve the external
addresses. As far as I know, at this point, the V-constant is the only
way in VSE for the linkage editor to resolve the external reference.
Reply all
Reply to author
Forward
0 new messages