Oppolzer - Informatik / Blog


Blog-Hauptseite      Neuester Artikel      Älterer Artikel      Neuerer Artikel      Älterer gleiche Kategorie      Neuerer gleiche Kategorie

Hercules - Aufruf eines externen Unterprogramms in PL/1

Subject:

Re: [H390-VM] Re: PL/I Main Program calling an External Subroutine

From:

Bernd Oppolzer <bernd.oppolzer@T-ONLINE.DE>

Reply-To:

Date:

2013.03.28 17:39:00


Hello once again,

further examination of the compile listing of COMMON showed:

the address passed to SQUARE ASSEMBLE as external ENTRY is in fact not the
starting address of the structure AREA1, but the address of a structure or table
descriptor.

The first address of the descriptor normally contains the address of the passed
parameter, but not in this case.

I tried to access the area by adding another L instruction:

L     6,=V(AREA1) REG6 POINTS TO EXTERNAL
L     6,0(6)

but then I got:

EXECUTION BEGINS...


P1 =         132624
P2 =      -16777216
P1 =         132624
P2 =         132620
             1                       1
             2                       4
             3                       9
             4                      16
             5                      25
             6                      36
             7                      49
             8                      64
             9                      81
       1310721                      77
Ready; T=0.17/0.48 18:35:47

that is: now only 9 elements are computed, the 10th is missing.

The reason is, as you can see by looking at P2:

I didn't get the true starting address of the vector this way, but the so called
RVO (relative virtual origin) of the table, that is: the location of the element
with index zero, and that's why the loop doesn't reach the 10th element.

So you see:

as long as you don't know about the structure of the internal descriptions of
PL/1, it's best to compute the pointers at the PL/1 side and simply pass
pointers.

Works for me ...

Kind regards

Bernd




Am 28.03.2013 17:15, schrieb Bernd Oppolzer:
>
>
> Hello again,
>
> START
> EXECUTION BEGINS...
>
>
> P1 =         132624
> P2 =      -16777216
> P1 =         132624
> P2 =      -16777216
>              1                       1
>              2                       4
>              3                       9
>              4                      16
>              5                      25
>              6                      36
>              7                      49
>              8                      64
>              9                      81
>             10                     100
> Ready; T=0.17/0.49 18:11:22
>
>
> SQUARE2 looks like this:
>
>          PRINT NOGEN
> SQUARE   CSECT
>          STM   14,12,12(13)
>          BALR  11,0
>          USING *,11
>          L     2,0(1)
>          L     6,0(2)
> *                                                            10 NUMBERS
>          USING AREA2,6     REG6 ALSO MADE THE BASE REGISTE
>
> no other changes, only the computation of reg 6 from the address list
> instead of the V constant
>
>
> and COMMON PLI was changed like this:
>
> P1 = ADDR (NUMBERS(1));
> P2 = NULL;
> CALL PUTADDR ('P1', P1); CALL PUTADDR ('P2', P2);
> CALL SQUARE (P1);
> CALL PUTADDR ('P1', P1); CALL PUTADDR ('P2', P2);
>
> the parameter P1 is passed to SQUARE (the starting address of
> the NUMBERS vector).
>
>
> Kind regards
>
> Bernd
>
>
>
>
>
> Am 28.03.2013 16:58, schrieb Bernd Oppolzer:
>>
>>
>> Hello,
>>
>> the problem is, that the ASSEMBLER subroutine does not get the starting address of
>> AREA1 by using the V constant, but some kind of structure or area description which
>> the PL/1 compiler puts in front of the actual area. I don't know the details; to examine this
>> further it might be necessary to look at the machine code generated by the PL/1 compiler.
>>
>> But what I did is:
>>
>> I passed the value that the ASSEMBLER subroutine got through the V constant back to
>> the PL/1 main program (through the reg 1 address list) and compared it to the actual
>> start of the vector NUMBERS in AREA1, and they are different (by 24 bytes) - which
>> fits well with the observed behaviour.
>>
>> Look at this:
>>
>> type square assemble
>>
>> ***********************************************************************
>> * SQUARE4 - ASSEMBLER SUBROUTINE CALLED FROM LIST FORTRAN TO SQUARE *
>> * A LIST OF 10 NUMBERS GENERATED BY LIST FORTRAN                      *
>> ***********************************************************************
>> *
>>          PRINT NOGEN
>> SQUARE   CSECT
>>          STM   14,12,12(13)
>>          BALR  11,0
>>          USING *,11
>>          L     2,0(1)
>>          L     6,=V(AREA1) REG6 POINTS TO EXTERNAL
>>          ST    6,0(2)
>> *                          10 NUMBERS
>>          USING AREA2,6     REG6 ALSO MADE THE BASE REGISTE
>> *                          REFERENCING NA
>> *                          REG6 IS THE WO
>> *
>>          LA    9,10
>> BACK     SR    4,4
>>          L     5,NUM
>>          MR    4,5
>>          ST    5,PROD
>>          LA    6,4(6)
>>          BCT   9,BACK
>> *
>>          LM    14,12,12(13)
>>          BR    14
>>          LTORG
>> AREA2    DSECT
>> NUM      DS    10F
>> PROD     DS    10F
>>          END   SQUARE
>>
>>
>> Ready; T=0.01/0.03 17:52:03
>>
>> type common pli
>>
>>   COMMON: PROCEDURE OPTIONS(MAIN);
>>   DCL 1 AREA1 STATIC EXT,
>>        2 NUMBERS(10) FIXED BIN(31),
>>        2 PRODUCT(10) FIXED BIN(31);
>>   DCL  I FIXED BIN(31);
>>   DCL P1 PTR;
>>   DCL P2 PTR;
>>   DCL NULL BUILTIN;
>>   DO I = 1 TO 10;
>>      NUMBERS(I) = I;
>>      PRODUCT(I) = 77;
>>   END;
>>   P1 = ADDR (NUMBERS(1));
>>   P2 = NULL;
>>   CALL PUTADDR ('P1', P1); CALL PUTADDR ('P2', P2);
>>   CALL SQUARE (P2);
>>   CALL PUTADDR ('P1', P1); CALL PUTADDR ('P2', P2);
>>   DO I = 1 TO 10;
>>   PUT SKIP LIST (NUMBERS(I), PRODUCT(I));
>>   END;
>>
>>   PUTADDR: PROC (CH, P);
>>   DCL CH CHAR (*);
>>   DCL P PTR;
>>   DCL BP BIN FIXED (31) BASED (PP);
>>   DCL PP PTR;
>>   PP = ADDR (P);
>>   PUT SKIP LIST (CH || ' = ' || BP);
>>   END PUTADDR;
>>
>>   END COMMON;
>>
>> Ready; T=0.01/0.02 17:53:28
>>
>> tt
>> GLOBAL TXTLIB PLILIB
>> EXEC PLICOMP COMMON
>> FILEDEF * CLEAR
>> PLI COMMON ( LIST XREF
>>     COMPILER DIAGNOSTICS.
>>
>>  WARNINGS.
>>     IEM0227I          NO FILE/STRING OPTION SPECIFIED IN ONE OR MORE GET/PUT STA
>> TEMENTS. SYSIN/SYSPRINT HAS BEEN
>>                       ASSUMED IN EACH CASE.
>>
>>  END OF DIAGNOSTICS.
>> +++ R(00004) +++
>> FILEDEF * CLEAR
>> ASSEMBLE SQUARE
>>
>> ASSEMBLER (XF) DONE
>> NO STATEMENTS FLAGGED IN THIS ASSEMBLY
>> LOAD COMMON SQUARE ( CLEAR
>> FILEDEF SYSPRINT TERM
>> START
>> EXECUTION BEGINS...
>>
>>
>> P1 =         132624
>> P2 =      -16777216
>> P1 =         132624
>> P2 =         132600
>>              1                       1
>>              2                       4
>>              3                       9
>>              4                      16
>>      408195216                      77
>>             16                      77
>>        1310721                      77
>>      418806416                      77
>>             16                      77
>>        1310721                      77
>> Ready; T=0.17/0.48 17:54:49
>>
>>
>> Please remember: PL/1 is different from FORTRAN, it does many crazy things
>> when passing parameters, and you have always to take this into account,
>> when accessing PL/1 areas from ASSEMBLER language.
>>
>> Next step: I will change SQUARE and the PL/1 programm to work on the
>> true starting address passed by reg1, and I think, it will work this way.
>>
>> Kind regards
>>
>> Bernd
>>
>>
>>
>> Am 28.03.2013 05:31, schrieb G.M.:
>>>
>>>
>>> This is nice.  A FORTRAN program  generates a list of 10 numbers
>>> and then calls an Assembler subroutine which will square each of the 10 numbers.
>>> A DSECT is used as a template for the common area,
>>> so no dealing with Reg 1, or using registers for indirect addressing;
>>> just simple variables  NUM, and PROD.
>>> Ready; T=0.01/0.01 22:10:35
>>>
>>> type list fortran
>>>
>>>          INTEGER NUM(10), PROD(10)
>>>          COMMON /AREA1/NUM,PROD
>>>          DO 10 I = 1,10
>>>                      NUM(I) = I
>>> 10       CONTINUE
>>>            CALL SQUARE
>>>            DO 20 I=1,10
>>>                      WRITE(6,100) NUM(I),PROD(I)
>>> 20    CONTINUE
>>> 100  FORMAT(2X,I2,3X,I3)
>>>          END
>>>
>>> Ready; T=0.01/0.02 22:11:01
>>>
>>> type square4 assemble
>>>
>>> ***********************************************************************
>>> * SQUARE4 - ASSEMBLER SUBROUTINE CALLED FROM LIST FORTRAN TO SQUARE   *
>>> * A LIST OF 10 NUMBERS GENERATED BY LIST FORTRAN                      *
>>> ***********************************************************************
>>> *
>>>          PRINT NOGEN
>>> SQUARE   CSECT
>>>          STM   14,12,12(13)
>>>          BALR  11,0
>>>          USING *,11
>>>          L     6,=V(AREA1)  REG6 POINTS TO EXTERNAL AREA HOLDING THE
>>> *                           10 NUMBERS.
>>>          USING AREA2,6      REG6 ALSO MADE THE BASE REGISTER WHEN
>>> *                           REFERENCING NAMES IN THE DUMMY SECTION
>>> *                           REG6 IS THE WORKHORSE BEHIND THE SCENE
>>> *
>>>          L     9,=F'10'
>>> BACK     SR    4,4
>>>          L     5,NUM
>>>          MR    4,5
>>>          ST    5,PROD
>>>          A     6,=F'4'
>>>          BCT   9,BACK
>>> *
>>>          LM    14,12,12(13)
>>>          BR    14
>>>          LTORG
>>> AREA2    DSECT
>>> NUM      DS    10F
>>> PROD     DS    10F
>>>          END   SQUARE
>>>
>>> Ready; T=0.02/0.08 22:12:11
>>>
>>> fortran list
>>> COMPILING: LIST
>>>
>>> Ready; T=0.03/0.08 22:12:32
>>>
>>> assemble square4
>>>
>>> ASSEMBLER (XF) DONE
>>> NO STATEMENTS FLAGGED IN THIS ASSEMBLY
>>> Ready; T=0.20/0.30 22:12:58
>>>
>>> load list square4
>>> Ready; T=0.16/0.19 22:13:33
>>>
>>> filedef 6 term
>>> Ready; T=0.01/0.01 22:13:48
>>>
>>>  start
>>> DMSLIO740I Execution begins...
>>>   1     1
>>>   2     4
>>>   3     9
>>>   4    16
>>>   5    25
>>>   6    36
>>>   7    49
>>>   8    64
>>>   9    81
>>>  10   100
>>> Ready; T=0.01/0.02 22:13:54
>>>
>>> COOL!  Program worked.
>>>
>>> Now look what happens when a PL/I program generates the same numbers and calls
>>> the same Assembler subroutine:
>>>
>>> type common pli
>>>  COMMON: PROCEDURE OPTIONS(MAIN);
>>>  DCL 1 AREA1 STATIC EXT,
>>>              2 NUMBERS(10) FIXED BIN(31),
>>>              2 PRODUCT(10) FIXED BIN(31);
>>>  DCL  I FIXED BIN(31);
>>>  DO I = 1 TO 10;
>>>         NUMBERS(I) = I;
>>>   END;
>>>  CALL SQUARE;
>>>  DO I = 1 TO 10;
>>>         PUT SKIP EDIT(NUMBERS(I), PRODUCT(I)) (COL(2), F(3), X(2), F(3));
>>>  END;
>>>  END COMMON;
>>>
>>> Ready; T=0.01/0.02 22:14:54
>>>
>>> pli common
>>>     COMPILER DIAGNOSTICS.
>>>
>>>  WARNINGS.
>>>     IEM0227I          NO FILE/STRING OPTION SPECIFIED IN ONE OR MORE GET/PUT ST
>>>                       ASSUMED IN EACH CASE.
>>>
>>>  END OF DIAGNOSTICS.
>>> Ready(00004); T=0.31/0.37 22:15:07
>>>
>>> filedef * clear
>>> Ready; T=0.01/0.01 22:15:18
>>>
>>> load common square4
>>> Ready; T=0.08/0.09 22:15:34
>>>
>>> filedef sysprint term
>>> Ready; T=0.01/0.01 22:15:45
>>> start
>>> DMSLIO740I Execution begins...
>>>
>>>
>>>    1    1
>>>    2    4
>>>    3    9
>>>    4   16
>>>  592    0
>>>   16    0
>>>  721    0
>>>  992    0
>>>   16    0
>>>  721    0
>>> Ready; T=0.23/0.30 22:15:52
>>>
>>> Everything was going fine until it got to the fifth number where it blew up.  What screwed up the list?
>>>
>>
>

Blog-Hauptseite      Neuester Artikel      Älterer Artikel      Neuerer Artikel      Älterer gleiche Kategorie      Neuerer gleiche Kategorie