The following is a list of examples demonstrating various features of Systems/C.
Also - you can try out your own code. We've provided a web-based compilation mechanism to submit source and see the output from the Systems/C compiler (dcc), along with the generated assembly source.
Each example contains the example C source code, the dcc command which compiled it (and any output from that step) and the generated ASM source.
This page is automatically generated. You may want to refer to it again to see any new examples, or improvements in previous ones.
The interesting things to notice in this are not C language features, but rather the generated ASM source. You'll notice the generated source is commented to show exactly what the intent of the source is. Also, notice that the source lines, where meaningful, are included as well.
These comments - as well as all the comments in the generated ASM source, are produced by the compiler. The generated ASM source found here has not been altered in any manner from that produced by the compiler.
You may also notice an aspect of Systems/C code generation; the constant 10 is not loaded from a separate section, but is placed at an appropriate place in the instruction stream.
__register
keyword on variable declarations (which
place the declared variable in the named register) and the __asm
keyword which places the given ASM source directly in the generated output.
The code in this example demonstrates rather straightforward malloc(), free() and realloc() functions which simply call the system services GETMAIN and FREEMAIN
The offsets are hard-coded, but using some of the more advanced features, these values could be taken directly from the MVS control block DSECTs. Some of the other examples demonstrate how one might do that.
__far
pointer support.
Notice in the source
how __alet
variables are used to specify which
ALET is associated with
which __far
pointer. Also, notice that both
far_foo_pointer
and far_ip
share the same ALET.
0C1
error
to occur, with a particular value in register #2 (in this
case, errno
.)
Thus, when the dump is taken, the register information
will display the value in register #2, letting the user
know what errno
contained.
DSECT
s without
any conversion utility.
That is, you can directly reference DSECT
s and
their fields without converting the DSECT
to
C source.
In this particular example, we access the current PSA
and then the current ASCB
to get the current ASCBASID
.
This example is rather high-level; subsequent examples demonstrate more of the "inner workings" of the various macros used.
EQU
values) directly from C source, with
__asmval
constants.
In the source, you'll see two EQUs for foo
and bar
which are referenced several ways.
DSECT
from C code, using __asmval
to compute the field offsets.
Using this technique; you can allocate storage for DSECT
s,
alter fields, etc... without having to convert the DSECT
into a C structure representation.
The Systems/C provided __asmref
macro is a much more
legible mechanism to reference DSECT
fields. But, this
example is provided to demonstrate some of the power of __asmval
.
/*
* A small example to demonstrate the generated ASM source
*
* Simply declares some variables, does some assignments.
*/
struct my_struct {
int field1;
int field2;
} ;
main()
{
struct my_struct s;
int f1, f2;
f1 = s.field2;
f2 = f1;
s.field1 = f2;
s.field2 = s.field2 + 10;
}
../dcc -flicense=dignus.freebsd.inf -oasm0001.390 src0001.c
DCC Systems/C 390 compiler - version 1.31.00
(c) Copyright 1999-2000 Dignus, LLC All rights reserved.
DCC is licensed to Dignus, LLC.
DCC Return code 0, elapsed time 0.05 seconds.
*
* Compiled by DCC Version 1.31.00
* on Fri Oct 27 16:43:34 2000
*
@CRT0 ALIAS C'@crt0'
EXTRN @CRT0
*
*
*
* Code Section
*
@CODE ALIAS C'@SRC0001'
@CODE CSECT
@CODE AMODE ANY
@CODE RMODE ANY
@DATA ALIAS C'@src0001'
*
*
*
main ALIAS C'main'
main DCCPRLG CINDEX=6,BASER=12,FRAME=112,ENTRY=YES
* ******* End of Prologue
* *
* *** struct my_struct s;
* *** int f1, f2;
* ***
* *** f1 = s.field2;
LA 4,96(0,13) ; &s
LA 4,4(0,4) ; offset of field2 in my_struct
L 5,0(0,4)
LR 3,5 ; f1
* ***
* *** f2 = f1;
LR 2,3 ; f2
* ***
* *** s.field1 = f2;
LA 4,96(0,13) ; &s
ST 2,0(0,4)
* ***
* *** s.field2 = s.field2 + 10;
LA 4,96(0,13) ; &s
LA 4,4(0,4) ; offset of field2 in my_struct
LA 5,96(0,13) ; &s
LA 5,4(0,5) ; offset of field2 in my_struct
L 6,0(0,5)
A 6,@lit_6_1
ST 6,0(0,4) ; offset of field2 in my_struct
* *** }
@ret_lab_6 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
DS 0D
@lit_6_1 DC F'10' 0x0000000a
@FRAMESIZE_6 DC F'112'
*
* DSECT for automatic variables in "main"
* (FUNCTION #6)
*
@AUTO#main DSECT
DS XL96
main#s#0 DS 8XL1 ; s
main#f1#0 DS 1F ; f1
main#f2#0 DS 1F ; f2
*
@CODE CSECT
*
* Non-Re-Entrant Data Section
*
@DATA CSECT
@DATA RMODE ANY
@DATA AMODE ANY
*
END
/*
* long-long example
*
* This is a very trivial for() loop, printing
* 100 long-longs.
**/
#include <sys/types.h>
#include <limits.h>
main()
{
long long index;
/* We'll loop for the last 100 long-long values. */
/* QUAD_MAX (from limits.h) defines the largest */
/* signed long long value. */
for( index = QUAD_MAX - 100; index < QUAD_MAX; index ++) {
/* Print the value of 'index'. Note the 'q' */
/* in the printf format specifier, indicating */
/* a 'quad' (long long) decimal type. */
printf("%qd\n", index);
}
}
../dcc -flicense=dignus.freebsd.inf -oasm0002.390 src0002.c
DCC Systems/C 390 compiler - version 1.31.00
(c) Copyright 1999-2000 Dignus, LLC All rights reserved.
DCC is licensed to Dignus, LLC.
cc: src0002.c line 24:Warning #2136: implicit declaration of function `printf'
printf("%qd\n", index);
DCC Return code 0, 1 Warning, elapsed time 0.07 seconds.
*
* Compiled by DCC Version 1.31.00
* on Fri Oct 27 16:43:34 2000
*
@CRT0 ALIAS C'@crt0'
EXTRN @CRT0
*
*
*
* Code Section
*
@CODE ALIAS C'@SRC0002'
@CODE CSECT
@CODE AMODE ANY
@CODE RMODE ANY
@DATA ALIAS C'@src0002'
printf ALIAS C'printf'
EXTRN printf
*
*
*
main ALIAS C'main'
main DCCPRLG CINDEX=10,BASER=12,FRAME=120,ENTRY=YES
* ******* End of Prologue
* *
* *** long long index;
* ***
* ***
* ***
* ***
* *** for( index = ((quad_t)(((u_quad_t)0-1) >> 1)) - 100; index < (\
* (quad_t)(((u_quad_t)0-1) >> 1)); index ++) {
LA 2,@lit_10_1
MVC 96(8,13),0(2) ; index
B @L1
DS 0D
@lit_10_1 DC XL8'7FFFFFFFFFFFFF9B'
@FRAMESIZE_10 DC F'120'
@lit_10_2 DC XL5'6C98841500' .qd..
DC X'00'
@lit_10_4 DC XL8'0000000000000001'
@lit_10_3 DC A(printf)
@lit_10_5 DC H'1' 0x0001
@lit_10_6 DC XL8'7FFFFFFFFFFFFFFF'
@L0 DS 0H
* ***
* ***
* ***
* ***
* *** printf("%qd\n", index);
LA 2,@lit_10_2
ST 2,104(0,13)
MVC 108(8,13),96(13)
LA 1,104(0,13)
L 15,@lit_10_3 ; printf
BALR 14,15
* *** }
L 10,96(0,13)
L 11,100(0,13)
LA 2,@lit_10_4
A 10,0(0,2)
AL 11,4(0,2)
BC 12,@@gen_label0
AH 10,@lit_10_5
@@gen_label0 DS 0H
STM 10,11,96(13) ; index
@L1 DS 0H
L 10,96(0,13)
L 11,100(0,13)
LA 2,@lit_10_6
C 10,0(0,2)
BNE @@gen_label1
CL 11,4(0,2)
@@gen_label1 DS 0H
BL @L0
* *** }
@ret_lab_10 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
*
* DSECT for automatic variables in "main"
* (FUNCTION #10)
*
@AUTO#main DSECT
DS XL96
main#index#0 DS 8XL1 ; index
*
@CODE CSECT
*
* Non-Re-Entrant Data Section
*
@DATA CSECT
@DATA RMODE ANY
@DATA AMODE ANY
*
END
/*
*
* Example of using __asm and __register.
*
* This provides a rather simplistic malloc()/free() support by
* simply calling the OS to acquire and release memory.
*
* A more sophisticated memory manager (as is used in the Systems/C library)
* would be preferred for any substantial program.
*
*
**/
/* To get builtin definitions of memcpy, you can include */
/* <string.h> */
#include <string.h>
/*
*
*
* *Very* simply malloc - just call GETMAIN
*
*
**/
void *
malloc(size)
unsigned long size;
{
void *retval;
/* We're going to save the size of the allocation */
/* for the subsequent call to FREEMAIN. So we */
/* add 8 bytes to the requested size. Why 8 and */
/* not 4? To keep things double-word aligned. */
size = size + 8;
if(size >= 16777216) {
/* Size is greater than 16 meg - this won't work */
/* because the GETMAIN we're using won't gives us that... */
retval = 0;
} else {
{
__register(1) unsigned long r1;
__register(2) unsigned long r2;
/* Need to declare R0 because GETMAIN uses it */
__register(0) unsigned long r0;
r1 = 0xf0000000;
r2 = size;
/* Note the '12' on the __asm statement */
/* the GETMAIN macro, when expanded, produces */
/* 12 bytes of instructions. This is not required */
/* but helps the compiler properly allocate the space */
/* for the inlined assembly language source. */
__asm 12 {
GETMAIN RU,LV=(2),LOC=BELOW
} ;
retval = (void *)r1;
}
if(retval != 0) {
/* Put in our size for later */
memcpy(retval, &(size), 4);
/* Add 8 to the returned result, we hand */
/* the user a pointer to the space, not */
/* a pointer to our hidden information. */
retval = ((char *)retval + 8);
}
}
/* Return the result */
return retval;
}
/*
*
*
* *Very* simple free - just give the memory back to the OS
* with FREEMAIN
*
*
**/
void
free(ptr)
void *ptr;
{
char *p;
unsigned long size;
p = (char *)ptr;
/* Back the pointer up to point at our hidden */
/* information. */
p = p - 8;
/* Get the original allocation size out of the */
/* hidden information. */
memcpy(&size, p, 4);
{
/* Need to declare R0/R1 because FREEMAIN uses it */
__register(0) unsigned long r0;
__register(1) unsigned long r1;
__register(2) unsigned long r2;
__register(3) unsigned long r3;
r3 = (unsigned long)p;
r2 = size;
__asm 8 {
FREEMAIN RU,LV=(2),A=(3)
} ;
}
}
/*
*
*
* *Very* simple realloc() - we simply always reallocate and
* copy
*
*
**/
void *
realloc(ptr, new_size)
void *ptr;
unsigned long new_size;
{
void *retval;
if(ptr == 0) {
/* If the previous pointer is 0, this is */
/* "just like" malloc() */
return malloc(new_size);
}
/* Get some new space. */
retval = malloc(new_size);
if(retval != 0) {
char *p;
unsigned long old_size;
unsigned long to_copy;
p = ptr;
/* Point to our hidden information so */
/* we can copy the old bytes to the */
/* location. For that copy, we need */
/* to get the size information. */
p = p-8;
memcpy(&old_size, p, 4);
/* Copy the old stuff back */
to_copy = old_size;
if(to_copy > new_size) {
to_copy = new_size;
}
memcpy(retval, ptr, to_copy);
/* Free the old stuff */
free(ptr);
}
/* Return the result */
return retval;
}
../dcc -flicense=dignus.freebsd.inf -oasm0003.390 src0003.c
DCC Systems/C 390 compiler - version 1.31.00
(c) Copyright 1999-2000 Dignus, LLC All rights reserved.
DCC is licensed to Dignus, LLC.
DCC Return code 0, elapsed time 0.07 seconds.
*
* Compiled by DCC Version 1.31.00
* on Fri Oct 27 16:43:34 2000
*
*
*
*
* Code Section
*
@CODE ALIAS C'@SRC0003'
@CODE CSECT
@CODE AMODE ANY
@CODE RMODE ANY
@DATA ALIAS C'@src0003'
*
*
*
malloc ALIAS C'malloc'
malloc DCCPRLG CINDEX=51,BASER=12,FRAME=128,ENTRY=YES
ST 1,80(0,13) ; Save ptr to incoming parm block
* ******* End of Prologue
* *
* *** void *retval;
* *** # 35
* *** size = size + 8;
L 2,0(0,1) ; size
AL 2,@lit_51_1
ST 2,0(0,1) ; size
* *** if(size >= 16777216) {
CL 2,@lit_51_2
BL @L0
* ***
* ***
* *** retval = 0;
LA 3,0(0,0) ; retval
* *** } else {
B @L1
DS 0D
@lit_51_2 DC F'16777216' 0x01000000
@lit_51_1 DC F'8' 0x00000008
@FRAMESIZE_51 DC F'128'
@lit_51_3 DC F'-268435456' 0xf0000000
@L0 DS 0H
* *** {
* *** __register(1) unsigned long r1;
* *** __register(2) unsigned long r2;
* ***
* *** __register(0) unsigned long r0;
* ***
* *** r1 = 0xf0000000;
L 4,@lit_51_3
LR 1,4 ; r1
* *** r2 = size;
L 4,80(0,13)
L 5,0(0,4) ; size
LR 2,5 ; r2
* *** # 55
* *** __asm 12 {
* *** GETMAIN RU,LV=(2),LOC=BELOW
* *** } ;
* inline ASM source (12 bytes)
GETMAIN RU,LV=(2),LOC=BELOW
*
@CODE CSECT
* *** retval = (void *)r1;
LR 3,1 ; retval
* *** }
* ***
* ***
* *** if(retval != 0) {
LR 2,3 ; #0
LA 6,0(0,0)
CR 2,6
BE @L1
* ***
* ***
* *** __memcpy(retval,&(size),4);
LR 2,3
MVC 0(4,2),0(4)
* ***
* ***
* ***
* ***
* *** retval = ((char *)retval + 8);
LA 3,8(0,3)
* *** }
* *** }
B @L1
@L2 DS 0H
* ***
* ***
* *** return retval;
@L1 DS 0H
LR 2,3
LR 15,2
B @ret_lab_51
* *** }
@ret_lab_51 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
*
* DSECT for automatic variables in "malloc"
* (FUNCTION #51)
*
@AUTO#malloc DSECT
DS XL104
malloc#retval#0 DS 1A ; retval
*
@CODE CSECT
*
*
*
free ALIAS C'free'
free DCCPRLG CINDEX=52,BASER=12,FRAME=128,ENTRY=YES
ST 1,80(0,13) ; Save ptr to incoming parm block
* ******* End of Prologue
* *
* *** char *p;
* *** unsigned long size;
* ***
* *** p = (char *)ptr;
L 2,0(0,1) ; ptr
ST 2,104(0,13) ; p
* ***
* ***
* ***
* *** p = p - 8;
SL 2,@lit_52_5
ST 2,104(0,13) ; p
* ***
* ***
* ***
* *** __memcpy(&size,p,4);
LA 3,108(0,13) ; &size
MVC 0(4,3),0(2)
* ***
* *** {
* ***
* *** __register(0) unsigned long r0;
* *** __register(1) unsigned long r1;
* *** __register(2) unsigned long r2;
* *** __register(3) unsigned long r3;
* *** r3 = (unsigned long)p;
L 4,104(0,13) ; p
LR 3,4 ; r3
* *** r2 = size;
L 5,108(0,13) ; size
LR 2,5 ; r2
* *** __asm 8 {
* *** FREEMAIN RU,LV=(2),A=(3)
* *** } ;
* inline ASM source (8 bytes)
FREEMAIN RU,LV=(2),A=(3)
*
@CODE CSECT
* *** }
* *** }
@ret_lab_52 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
DS 0D
@lit_52_5 DC F'8' 0x00000008
@FRAMESIZE_52 DC F'128'
*
* DSECT for automatic variables in "free"
* (FUNCTION #52)
*
@AUTO#free DSECT
DS XL104
free#p#0 DS 1A ; p
free#size#0 DS 1F ; size
*
@CODE CSECT
*
*
*
realloc ALIAS C'realloc'
realloc DCCPRLG CINDEX=53,BASER=12,FRAME=136,ENTRY=YES
ST 1,80(0,13) ; Save ptr to incoming parm block
* ******* End of Prologue
* *
L 2,4(0,1)
LR 5,2
* *** void *retval;
* ***
* *** if(ptr == 0) {
L 6,0(0,1) ; ptr
LA 7,0(0,0)
CR 6,7
BNE @L3
* ***
* ***
* *** return malloc(new_size);
LR 7,5
ST 7,120(0,13)
LA 1,120(0,13)
L 15,@lit_53_7 ; malloc
BALR 14,15
B @ret_lab_53
DS 0D
@FRAMESIZE_53 DC F'136'
@lit_53_7 DC A(malloc)
@lit_53_9 DC F'8' 0x00000008
@lit_53_10 DC F'256' 0x00000100
@lit_53_12 DC XL6'D20060008000'
@lit_53_13 DC A(free)
* *** }
* ***
* ***
* *** retval = malloc(new_size);
@L3 DS 0H
LR 6,5
ST 6,120(0,13)
LA 1,120(0,13)
L 15,@lit_53_7 ; malloc
BALR 14,15
LR 4,15 ; retval
* ***
* *** if(retval != 0) {
LR 6,4 ; #0
LA 7,0(0,0)
CR 6,7
BE @L4
* *** char *p;
* *** unsigned long old_size;
* *** unsigned long to_copy;
* ***
* *** p = ptr;
L 6,80(0,13)
L 7,0(0,6) ; ptr
LR 3,7 ; p
* ***
* ***
* ***
* ***
* *** p = p-8;
LR 8,3
SL 8,@lit_53_9
LR 3,8 ; p
* *** __memcpy(&old_size,p,4);
LA 8,112(0,13) ; &old_size
LR 9,3
MVC 0(4,8),0(9)
* ***
* ***
* ***
* *** to_copy = old_size;
L 7,112(0,13) ; old_size
LR 2,7 ; to_copy
* *** if(to_copy > new_size) {
LR 8,2 ; new_size
LR 9,5
CLR 8,9
BNH @L5
* *** to_copy = new_size;
LR 8,5 ; to_copy
LR 2,8 ; to_copy
* *** }
* *** __memcpy(retval,ptr,to_copy);
@L5 DS 0H
LR 6,4
L 7,80(0,13)
L 8,0(0,7) ; ptr
LR 9,2
LR 10,6
@@gen_label5 DS 0H
LTR 9,9
BZ @@gen_label6
CL 9,@lit_53_10
BH @@gen_label7
LR 11,9
B @@gen_label8
@@gen_label7 DS 0H
L 11,@lit_53_10
@@gen_label8 DS 0H
SLR 9,11
BCTR 11,0
EX 11,@lit_53_12
LA 6,1(11,6)
LA 8,1(11,8)
B @@gen_label5
@@gen_label6 DS 0H
* ***
* ***
* *** free(ptr);
L 6,80(0,13)
L 7,0(0,6) ; ptr
ST 7,120(0,13)
LA 1,120(0,13)
L 15,@lit_53_13 ; free
BALR 14,15
* *** }
* ***
* ***
* *** return retval;
@L4 DS 0H
LR 6,4
LR 15,6
B @ret_lab_53
* *** }
@ret_lab_53 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
*
* DSECT for automatic variables in "realloc"
* (FUNCTION #53)
*
@AUTO#realloc DSECT
DS XL104
realloc#retval#0 DS 1A ; retval
realloc#p#2 DS 1A ; p
realloc#old_size#2 DS 1F ; old_size
realloc#to_copy#2 DS 1F ; to_copy
*
@CODE CSECT
*
* Non-Re-Entrant Data Section
*
@DATA CSECT
@DATA RMODE ANY
@DATA AMODE ANY
*
END
/*
*
* A simple program to retrieve the user name
* on MVS.
*
**/
#include <stdio.h>
#include <string.h>
int main()
{
int flccvt, ascb, asxb, acee, i;
int *ip;
char aceeusri[9];
ip = (int *)0x224; /* PSAAOLD */
ascb = *ip;
ip = (int *)(ascb + 0x6c); /* ASCBASXB */
asxb = *ip;
ip = (int *)(asxb + 0xc8); /* ASXBSENV */
acee = *ip;
ip = (int *)(acee + 0x15); /* ACEEUSRI */
memcpy(aceeusri, ip, 8); /* Get USER ID */
aceeusri[8] = '\0'; /* NULL terminate */
printf("User name is `%s'\n", aceeusri);
}
../dcc -flicense=dignus.freebsd.inf -oasm0004.390 src0004.c
DCC Systems/C 390 compiler - version 1.31.00
(c) Copyright 1999-2000 Dignus, LLC All rights reserved.
DCC is licensed to Dignus, LLC.
DCC Return code 0, elapsed time 0.11 seconds.
*
* Compiled by DCC Version 1.31.00
* on Fri Oct 27 16:43:34 2000
*
@CRT0 ALIAS C'@crt0'
EXTRN @CRT0
*
*
*
* Code Section
*
@CODE ALIAS C'@SRC0004'
@CODE CSECT
@CODE AMODE ANY
@CODE RMODE ANY
@DATA ALIAS C'@src0004'
printf ALIAS C'printf'
EXTRN printf
*
*
*
main ALIAS C'main'
main DCCPRLG CINDEX=118,BASER=12,FRAME=152,ENTRY=YES
* ******* End of Prologue
* *
* *** int flccvt, ascb, asxb, acee, i;
* *** int *ip;
* ***
* *** char aceeusri[9];
* ***
* *** ip = (int *)0x224;
LA 2,548(0,0) ; ip
* *** ascb = *ip;
L 6,0(0,2)
LR 5,6 ; ascb
* ***
* *** ip = (int *)(ascb + 0x6c);
LR 6,5
A 6,@lit_118_1
LR 2,6 ; ip
* *** asxb = *ip;
L 6,0(0,2)
LR 4,6 ; asxb
* ***
* *** ip = (int *)(asxb + 0xc8);
LR 6,4
A 6,@lit_118_2
LR 2,6 ; ip
* *** acee = *ip;
L 6,0(0,2)
LR 3,6 ; acee
* ***
* *** ip = (int *)(acee + 0x15);
LR 6,3
A 6,@lit_118_3
LR 2,6 ; ip
* ***
* *** __memcpy(aceeusri,ip,8);
LA 6,120(0,13) ; &aceeusri
LR 7,2
MVC 0(8,6),0(7)
* *** aceeusri[8] = '\0';
LA 6,120(0,13) ; &aceeusri
LA 6,8(0,6)
LA 7,0(0,0)
STC 7,0(0,6)
* ***
* *** printf("User name is `%s'\n", aceeusri);
LA 6,@lit_118_4
LA 7,120(0,13) ; &aceeusri
STM 6,7,136(13)
LA 1,136(0,13)
L 15,@lit_118_5 ; printf
BALR 14,15
* *** }
@ret_lab_118 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
DS 0D
@lit_118_4 DC XL8'E4A2859940958194' User.nam
DC XL8'854089A240796CA2' e.is...s
DC XL3'7D1500' ...
DC X'00'
@lit_118_3 DC F'21' 0x00000015
@lit_118_2 DC F'200' 0x000000c8
@lit_118_1 DC F'108' 0x0000006c
@FRAMESIZE_118 DC F'152'
@lit_118_5 DC A(printf)
*
* DSECT for automatic variables in "main"
* (FUNCTION #118)
*
@AUTO#main DSECT
DS XL96
main#flccvt#0 DS 1F ; flccvt
main#ascb#0 DS 1F ; ascb
main#asxb#0 DS 1F ; asxb
main#acee#0 DS 1F ; acee
main#i#0 DS 1F ; i
main#ip#0 DS 1A ; ip
main#aceeusri#0 DS 9CL1 ; aceeusri
*
@CODE CSECT
*
* Non-Re-Entrant Data Section
*
@DATA CSECT
@DATA RMODE ANY
@DATA AMODE ANY
*
END
/*
* __far pointer example.
*
* __far pointers pointer into Hiperspace (via AR registers)
*
* __far pointers may take advantage of the __based() attribute
* to indicate they are based on a particular __alet. Thus,
* several __far pointers may share __alet values. In this case
* the __far pointer only uses 4 bytes of memory.
*
* __far pointers which are not based use 8 bytes of memory and
* have the form:
* +----------+
* | ALET |
* +----------+
* | OFFSET |
* +----------+
*
* The following example declares a few __far __based() pointers and
* demonstrates movements to/from Hiperspace via dereferences of
* these pointers.
*
**/
main()
{
struct foo {
int field1;
int field2;
} ;
__alet base, base2;
__far struct foo __based(base) *far_foo_pointer;
__far struct foo __based(base2) *far_foo_pointer_2;
__far __based(base) *far_ip;
int i;
struct foo f;
/* Move from a __far structure to a local structure. */
f = *far_foo_pointer;
/* Move from a local structure to a __far structure. */
*far_foo_pointer = f;
/* Move one __far structure to another (note the two */
/* different based __alets */
*far_foo_pointer_2 = *far_foo_pointer;
/* Assign from a field in a __far structure */
i = far_foo_pointer -> field2;
/* Assign to a field in a __far structure */
far_foo_pointer -> field2 = 10;
/* Assign an integer to an __alet */
base = 0x0;
/* Simple dereference of a __far integer pointer */
i = *far_ip;
*far_ip = i;
}
../dcc -flicense=dignus.freebsd.inf -oasm0050.390 src0050.c
DCC Systems/C 390 compiler - version 1.31.00
(c) Copyright 1999-2000 Dignus, LLC All rights reserved.
DCC is licensed to Dignus, LLC.
DCC Return code 0, elapsed time 0.04 seconds.
*
* Compiled by DCC Version 1.31.00
* on Fri Oct 27 16:43:34 2000
*
@CRT0 ALIAS C'@crt0'
EXTRN @CRT0
*
*
*
* Code Section
*
@CODE ALIAS C'@SRC0050'
@CODE CSECT
@CODE AMODE ANY
@CODE RMODE ANY
@DATA ALIAS C'@src0050'
*
*
*
main ALIAS C'main'
main DCCPRLG CINDEX=6,BASER=12,FRAME=128,ENTRY=YES
* ******* End of Prologue
* *
* *** struct foo {
* *** int field1;
* *** int field2;
* *** } ;
* ***
* *** __alet base, base2;
* *** __far struct foo __based(base) *far_foo_pointer;
* *** __far struct foo __based(base2) *far_foo_pointer_2;
* *** __far __based(base) *far_ip;
* *** int i;
* ***
* *** struct foo f;
* ***
* ***
* *** f = *far_foo_pointer;
LA 6,120(0,13) ; &f
LR 7,2 ; far_foo_pointer
LR 8,3
SAR 8,7
CPYA 6,12 ; AR 12 is always 0
SAC 512(0) ; AR mode
MVC 0(8,6),0(8)
SAC 0(0) ; Primary mode
* ***
* ***
* *** *far_foo_pointer = f;
LR 6,2 ; far_foo_pointer
LR 7,3
SAR 7,6
LA 6,120(0,13) ; &f
CPYA 6,12 ; AR 12 is always 0
SAC 512(0) ; AR mode
MVC 0(8,7),0(6)
SAC 0(0) ; Primary mode
* ***
* ***
* ***
* *** *far_foo_pointer_2 = *far_foo_pointer;
L 6,100(0,13) ; base2
L 7,108(0,13) ; far_foo_pointer_2
SAR 7,6
LR 8,2 ; far_foo_pointer
LR 9,3
SAR 9,8
SAC 512(0) ; AR mode
MVC 0(8,7),0(9)
SAC 0(0) ; Primary mode
* ***
* ***
* *** i = far_foo_pointer -> field2;
LR 8,2 ; far_foo_pointer
LR 9,3
SAR 9,8
LA 9,4(0,9) ; offset of field2 in foo
SAC 512(0) ; AR mode
L 8,0(0,9)
SAC 0(0) ; Primary mode
LR 4,8 ; i
* ***
* ***
* *** far_foo_pointer -> field2 = 10;
LR 8,2 ; far_foo_pointer
LR 9,3
SAR 9,8
LA 9,4(0,9) ; offset of field2 in foo
LA 8,10(0,0)
SAC 512(0) ; AR mode
ST 8,0(0,9) ; offset of field2 in foo
SAC 0(0) ; Primary mode
* ***
* ***
* *** base = 0x0;
LA 6,0(0,0)
ST 6,96(0,13) ; base
* ***
* ***
* *** i = *far_ip;
LR 8,2 ; far_ip
LR 9,5
SAR 9,8
SAC 512(0) ; AR mode
L 8,0(0,9)
SAC 0(0) ; Primary mode
LR 4,8 ; i
* ***
* *** *far_ip = i;
LR 8,2 ; far_ip
LR 9,5
SAR 9,8
LR 8,4
SAC 512(0) ; AR mode
ST 8,0(0,9)
SAC 0(0) ; Primary mode
* ***
* *** }
@ret_lab_6 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
DS 0D
@FRAMESIZE_6 DC F'128'
*
* DSECT for automatic variables in "main"
* (FUNCTION #6)
*
@AUTO#main DSECT
DS XL96
main#base#0 DS 1F ; base
main#base2#0 DS 1F ; base2
main#far_foo_pointer#0 DS 4XL1 ; far_foo_pointer
main#far_foo_pointer_2#0 DS 4XL1 ; far_foo_pointer_2
main#far_ip#0 DS 4XL1 ; far_ip
main#i#0 DS 1F ; i
main#f#0 DS 8XL1 ; f
*
@CODE CSECT
*
* Non-Re-Entrant Data Section
*
@DATA CSECT
@DATA RMODE ANY
@DATA AMODE ANY
*
END
/*
* An example of using the system's register
* information in a dump to debug a program.
**/
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#define OhC1(label,ax) __asm 2 {label dc x'00',ax }
main()
{
if(open("mydd", O_RDONLY, 0) < 0) {
/* Put errno in register #2 */
/* so it will appear in the */
/* register information. */
__register(2) int r2;
r2 = errno;
/* Generate the 0C1 error here. */
OhC1(labeli,x'00');
}
}
../dcc -flicense=dignus.freebsd.inf -oasm0081.390 src0081.c
DCC Systems/C 390 compiler - version 1.31.00
(c) Copyright 1999-2000 Dignus, LLC All rights reserved.
DCC is licensed to Dignus, LLC.
DCC Return code 0, elapsed time 0.11 seconds.
*
* Compiled by DCC Version 1.31.00
* on Fri Oct 27 16:43:35 2000
*
@CRT0 ALIAS C'@crt0'
EXTRN @CRT0
*
*
*
* Code Section
*
@CODE ALIAS C'@SRC0081'
@CODE CSECT
@CODE AMODE ANY
@CODE RMODE ANY
@DATA ALIAS C'@src0081'
errno ALIAS C'errno'
EXTRN errno
open ALIAS C'open'
EXTRN open
*
*
*
main ALIAS C'main'
main DCCPRLG CINDEX=78,BASER=12,FRAME=112,ENTRY=YES
* ******* End of Prologue
* *
* *** if(open("mydd", 0x0000, 0) < 0) {
LA 2,@lit_78_1
LA 3,0(0,0)
LA 4,0(0,0)
STM 2,4,96(13)
LA 1,96(0,13)
L 15,@lit_78_2 ; open
BALR 14,15
LTR 15,15
BNL @ret_lab_78
* ***
* ***
* ***
* *** __register(2) int r2;
* ***
* *** r2 = errno;
L 3,@lit_78_3
L 2,0(0,3) ; r2
* ***
* ***
* *** __asm 2 {labeli dc x'00',x'00' };
* inline ASM source (2 bytes)
labeli dc x'00',x'00'
*
@CODE CSECT
* *** }
* ***
* *** }
@ret_lab_78 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
DS 0D
@lit_78_1 DC XL5'94A8848400' mydd.
DC X'00'
@FRAMESIZE_78 DC F'112'
@lit_78_2 DC A(open)
@lit_78_3 DC A(errno)
*
* DSECT for automatic variables in "main"
* (FUNCTION #78)
*
@AUTO#main DSECT
DS XL96
*
@CODE CSECT
*
* Non-Re-Entrant Data Section
*
@DATA CSECT
@DATA RMODE ANY
@DATA AMODE ANY
*
END
/*
* Demonstrates referencing some MVS asm fields
* directly from C.
**/
#include <stdio.h>
/*
* <machine/asmref.h> defines the __asmref macro
* which takes three arguments:
* 1: The base pointer to use for the DSECT
* you'd like to reference.
* 2: The ASM expression that produces the
* absolute field offset in the DSECT you'd
* like to access. Usually this is something like
* "FIELD_NAME-DSECT_NAME".
* 3: The C type to use for the reference.
**/
#include <machine/asmref.h>
main()
{
short current_ascbasid;
void *current_ascb;
/*
* For demonstration, we place the __asmref for PSAAOLD
* in a separate #define.
*/
#define PSAAOLD __asmref(0,"PSAAOLD-PSA",void *)
#define ASCBASID __asmref( current_ascb, "ASCBASID-ASCB", unsigned short)
/*
* Get the current ASCB from the PSA. Note that
* the PSA is located at offset 0; so we use 0 as
* our base.
*/
current_ascb = PSAAOLD;
/* Now, get the ASCBASID from the ASCB. */
current_ascbasid = ASCBASID;
/*
* Here's an equivalent way of getting the current
* ASCBASID without the intermediate step of loading
* loading the current_ascb into a variable.
*/
current_ascbasid = __asmref(
__asmref(0,"PSAAOLD-PSA",void *),
"ASCBASID-ASCB", unsigned short);
}
/*
* Include the appropriate system macros to get
* the DSECTs we need.
*/
__asm {
IHAPSA
IHAASCB
}
../dcc -flicense=dignus.freebsd.inf -oasm0086.390 src0086.c
DCC Systems/C 390 compiler - version 1.31.00
(c) Copyright 1999-2000 Dignus, LLC All rights reserved.
DCC is licensed to Dignus, LLC.
DCC Return code 0, elapsed time 0.10 seconds.
*
* Compiled by DCC Version 1.31.00
* on Fri Oct 27 16:43:35 2000
*
@CRT0 ALIAS C'@crt0'
EXTRN @CRT0
*
*
*
* Code Section
*
@CODE ALIAS C'@SRC0086'
@CODE CSECT
@CODE AMODE ANY
@CODE RMODE ANY
@DATA ALIAS C'@src0086'
*
*
*
main ALIAS C'main'
main DCCPRLG CINDEX=73,BASER=12,FRAME=96,ENTRY=YES
* ******* End of Prologue
* *
* *** short current_ascbasid;
* *** void *current_ascb;
* *** # 33
* ***
* *** # 43
* *** current_ascb = (*(void * *)(((char *)(0)) + __asmval(4,"PSAAOL\
* D-PSA")));
LA 3,0(0,0)
L 4,@lit_73_4 ; =AL4(PSAAOLD-PSA)
LA 3,0(3,4)
L 4,0(0,3)
LR 2,4 ; current_ascb
* ***
* ***
* ***
* ***
* *** current_ascbasid = (*(unsigned short *)(((char *)(current_ascb\
* )) + __asmval(4,"ASCBASID-ASCB")));
LR 3,2
L 4,@lit_73_5 ; =AL4(ASCBASID-ASCB)
LA 3,0(3,4)
LH 4,0(0,3)
ICM 4,B'1100',@lit_73_6
STH 4,88(0,13) ; current_ascbasid
* *** # 56
* *** current_ascbasid = (*(unsigned short *)(((char *)((*(void * *)\
* (((char *)(0)) + __asmval(4,"PSAAOLD-PSA"))))) + __asmval(4,"ASCBASI\
* D-ASCB")));
LA 3,0(0,0)
L 5,@lit_73_4 ; =AL4(PSAAOLD-PSA)
LA 3,0(3,5)
L 5,0(0,3)
L 3,@lit_73_5 ; =AL4(ASCBASID-ASCB)
LA 5,0(5,3)
LH 3,0(0,5)
ICM 3,B'1100',@lit_73_6
STH 3,88(0,13) ; current_ascbasid
* *** # 60
* *** }
@ret_lab_73 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
DS 0D
@lit_73_6 DC F'0' 0x00000000
@lit_73_5 DC AL4(ASCBASID-ASCB)
@lit_73_4 DC AL4(PSAAOLD-PSA)
@FRAMESIZE_73 DC F'96'
*
* DSECT for automatic variables in "main"
* (FUNCTION #73)
*
@AUTO#main DSECT
DS XL88
main#current_ascbasid#0 DS 2XL1 ; current_ascbasid
ORG @AUTO#main+92
main#current_ascb#0 DS 1A ; current_ascb
*
@CODE CSECT
* inline ASM source (12 bytes)
IHAPSA
IHAASCB
*
*
* Non-Re-Entrant Data Section
*
@DATA CSECT
@DATA RMODE ANY
@DATA AMODE ANY
*
END
/*
* Example of using __asmval to reference assembly-language
* constants (usually EQUs)
*
* Each of these constants is treated as an unsigned "int" type;
* When a reference to the __asmval() constant is made,
* the code generator will create a A-CON literal that contains the
* named value (much as =A(name) would do.)
*
* The specification of an __asmval includes the size of the
* the literal to create. If the size is just one byte, the code
* generator can do a better job and perhaps not actually need
* to allocate literal space for it.
*
**/
/*
*
* Provide some nice EQUs in the generate ASM source
* so we can reference them from C code.
*
* Typically these values would come from some COPY deck
* or other defining source...
*/
__asm {
foo EQU 10
bar EQU 20
}
main()
{
int i;
int j;
char c;
/* Just load the value */
i = __asmval(2,"foo");
/* Load the other one */
i = __asmval(3, "bar");
/* Load the first one again, and convert */
/* it to an unsigned char. */
c = __asmval(2,"foo");
/* Do some arithmetic on these values. Since */
/* the compiler doesn't know the value of */
/* either `bar' or `foo', the arithmetic will */
/* happen at run-time. */
i = __asmval(2,"foo") + __asmval(3,"bar");
}
../dcc -flicense=dignus.freebsd.inf -oasm0088.390 src0088.c
DCC Systems/C 390 compiler - version 1.31.00
(c) Copyright 1999-2000 Dignus, LLC All rights reserved.
DCC is licensed to Dignus, LLC.
DCC Return code 0, elapsed time 0.03 seconds.
*
* Compiled by DCC Version 1.31.00
* on Fri Oct 27 16:43:35 2000
*
@CRT0 ALIAS C'@crt0'
EXTRN @CRT0
*
*
* inline ASM source (12 bytes)
foo EQU 10
bar EQU 20
*
*
* Code Section
*
@CODE ALIAS C'@SRC0088'
@CODE CSECT
@CODE AMODE ANY
@CODE RMODE ANY
@DATA ALIAS C'@src0088'
*
*
*
main ALIAS C'main'
main DCCPRLG CINDEX=6,BASER=12,FRAME=104,ENTRY=YES
* ******* End of Prologue
* *
* *** int i;
* *** int j;
* *** char c;
* *** # 43
* *** i = __asmval(2,"foo");
LA 3,0(0,0)
ICM 3,B'0011',@lit_6_4 ; =AL2(foo)
LR 2,3 ; i
* ***
* ***
* *** i = __asmval(3, "bar");
LA 3,0(0,0)
ICM 3,B'0111',@lit_6_5 ; =AL3(bar)
LR 2,3 ; i
* ***
* ***
* ***
* *** c = __asmval(2,"foo");
LA 3,0(0,0)
ICM 3,B'0011',@lit_6_4 ; =AL2(foo)
STC 3,96(0,13) ; c
* *** # 56
* *** i = __asmval(2,"foo") + __asmval(3,"bar");
LA 4,0(0,0)
ICM 4,B'0011',@lit_6_4 ; =AL2(foo)
LA 5,0(0,0)
ICM 5,B'0111',@lit_6_5 ; =AL3(bar)
ALR 4,5
LR 2,4 ; i
* ***
* *** }
@ret_lab_6 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
DS 0D
@lit_6_5 DC AL3(bar)
DC AL1(0)
@lit_6_4 DC AL2(foo)
DC AL2(0)
@FRAMESIZE_6 DC F'104'
*
* DSECT for automatic variables in "main"
* (FUNCTION #6)
*
@AUTO#main DSECT
DS XL88
main#i#0 DS 1F ; i
main#j#0 DS 1F ; j
main#c#0 DS 1CL1 ; c
*
@CODE CSECT
*
* Non-Re-Entrant Data Section
*
@DATA CSECT
@DATA RMODE ANY
@DATA AMODE ANY
*
END
/*
*
* An example of using __asmval to access
* various members of a DSECT.
*
* In order to demonstrate how this technique may
* be employed, the various aspects have been made
* explicit. Presumably, employing the macro preprocessor
* to define appropriate macros for field references would
* make the code much more legible.
*
**/
/*
*
* Just a nice DSECT we can reference. (This could have easily been
* an assembly macro to generate any DSECT, etc...)
*
**/
__asm {
MYDSECT DSECT
FIELD1 DS 1F
FIELD2 DS 2F
MYDSECT_SIZE DS 0F
}
main()
{
/*
* Note that we calculate the various field
* offsets by subtracting the DSECT start.
* This causes the assembler to create an
* absolute value which can be used in a DC.
*
* Also, notice that should the specifics of
* the DSECT change (say, a field is added),
* this code would work unchanged after being
* re-assembled, there would be no need to recompile
* the C source.
*/
/*
* These two variables will become the pointers
* to the fields we're interested int.
*/
int *field1;
int *field2;
/*
* mydsect is the base of the DSECT, which
* will be dynamically allocated. This is
* declared as a (char *) so the eventual
* pointer arithmetic for computing field
* addresses works correctly.
*/
char *mydsect;
/*
* Got get some memory (of the appropriate size)
* for the DSECT. The size of the DSECT is unknown by
* the compiler, but we can use an __asmval() construct to
* determine just what it should be.
*
* We use the C library function malloc() to allocate the space.
*/
mydsect = malloc(__asmval(4,"MYDSECT_SIZE-MYDSECT"));
/*
* Calculate field offsets & set up the
* field pointers.
*/
field1 = (int *)(mydsect + __asmval(4,"FIELD1-MYDSECT"));
field2 = (int *)(mydsect + __asmval(4,"FIELD2-MYDSECT"));
/*
* Put a F(10) in FIELD1
*/
*field1 = 10;
/*
* Put 100 + FIELD1 in FIELD2
*/
*field2 = (*field1 + 100);
}
../dcc -flicense=dignus.freebsd.inf -oasm0089.390 src0089.c
DCC Systems/C 390 compiler - version 1.31.00
(c) Copyright 1999-2000 Dignus, LLC All rights reserved.
DCC is licensed to Dignus, LLC.
cc: src0089.c line 71:Warning #2136: implicit declaration of function `malloc'
mydsect = malloc(__asmval(4,"MYDSECT_SIZE-MYDSECT"));
cc: src0089.c line 71:Warning #2237: assignment converts integral to pointer without a cast
mydsect = malloc(__asmval(4,"MYDSECT_SIZE-MYDSECT"));
DCC Return code 0, 2 Warnings, elapsed time 0.04 seconds.
*
* Compiled by DCC Version 1.31.00
* on Fri Oct 27 16:43:35 2000
*
@CRT0 ALIAS C'@crt0'
EXTRN @CRT0
*
*
* inline ASM source (20 bytes)
MYDSECT DSECT
FIELD1 DS 1F
FIELD2 DS 2F
MYDSECT_SIZE DS 0F
*
*
* Code Section
*
@CODE ALIAS C'@SRC0089'
@CODE CSECT
@CODE AMODE ANY
@CODE RMODE ANY
@DATA ALIAS C'@src0089'
malloc ALIAS C'malloc'
EXTRN malloc
*
*
*
main ALIAS C'main'
main DCCPRLG CINDEX=6,BASER=12,FRAME=120,ENTRY=YES
* ******* End of Prologue
* *
* *** # 50
* *** int *field1;
* *** int *field2;
* *** # 60
* *** char *mydsect;
* *** # 71
* *** mydsect = malloc(__asmval(4,"MYDSECT_SIZE-MYDSECT"));
L 5,@lit_6_1 ; =AL4(MYDSECT_SIZE-MYDSECT)
ST 5,112(0,13)
LA 1,112(0,13)
L 15,@lit_6_2 ; malloc
BALR 14,15
LR 3,15 ; mydsect
* *** # 77
* *** field1 = (int *)(mydsect + __asmval(4,"FIELD1-MYDSECT"));
LR 5,3
L 6,@lit_6_3 ; =AL4(FIELD1-MYDSECT)
LA 5,0(5,6)
LR 2,5 ; field1
* *** field2 = (int *)(mydsect + __asmval(4,"FIELD2-MYDSECT"));
LR 5,3
L 6,@lit_6_4 ; =AL4(FIELD2-MYDSECT)
LA 5,0(5,6)
LR 4,5 ; field2
* *** # 83
* *** *field1 = 10;
LR 5,2 ; #10
LA 6,10(0,0)
ST 6,0(0,5) ; field1
* *** # 88
* *** *field2 = (*field1 + 100);
LR 5,4 ; field1
L 6,0(0,2)
A 6,@lit_6_5
ST 6,0(0,5) ; field2
* ***
* ***
* *** }
@ret_lab_6 DS 0H
* * **** Start of Epilogue
DCCEPIL
* * **** End of Epilogue
DS 0D
@lit_6_5 DC F'100' 0x00000064
@lit_6_4 DC AL4(FIELD2-MYDSECT)
@lit_6_3 DC AL4(FIELD1-MYDSECT)
@lit_6_2 DC A(malloc)
@lit_6_1 DC AL4(MYDSECT_SIZE-MYDSECT)
@FRAMESIZE_6 DC F'120'
*
* DSECT for automatic variables in "main"
* (FUNCTION #6)
*
@AUTO#main DSECT
DS XL96
main#field1#0 DS 1A ; field1
main#field2#0 DS 1A ; field2
main#mydsect#0 DS 1A ; mydsect
*
@CODE CSECT
*
* Non-Re-Entrant Data Section
*
@DATA CSECT
@DATA RMODE ANY
@DATA AMODE ANY
*
END
Generated on Fri Oct 27 16:43:35 EDT 2000 Contact us |
Copyright © 2000 Dignus, LLC All rights reserved. |