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?
>
|