        TITLE  ISING3_ASM
; mods for c: disk 9-94
; written Chris Michael - see Phys. Rev. B33,7861(1986) -
; Should run on IBMPC , IBMPC AT , or clone.
; as is reads in A:L243IS0.DAT,does ITCOUNT*MEASVAL*NUMBL updates
; with seed from ASCII character read in from keyboard and
; writes lattice to A:L243IS.DAT and results to screen. Takes 60 hrs on AT!
; size is 24**3 and beta = 0.22165 - to change it is tricky since
; several ratios have to be integers - see comments later on.
;(use ISINGSH.EXE for a short display on the screen (40*8*8 with diff rand no)
;---USED 16 DIFF RANDOM NO SEQUENCES         ==>.EXE FILE
SHOWSTACK       SEGMENT PARA    STACK 'STACK'
        DW      100     DUP(?)
STK_TOP LABEL   WORD
SHOWSTACK       ENDS
;
;
ESEG    SEGMENT PARA
;===PARAMETERS=====
LX      EQU     24            ;INNER COUNT IS LX
LY      EQU     24            ;LATTICE LX*LY*LZ (16 COPIES)
LZ      EQU     24
ITCOUNT EQU     20            ;SWEEPS BETWEEN MEASUREMENTS
MEASVAL EQU     100           ;TOTAL NUMBER OF MEASUREMENTS BETWEEN WRITES
NUMBL   EQU     60            ;NUMBER OF MEAS BLOCKS
MEASPR  EQU     MEASVAL*NUMBL ;  <6000 ?
;
; SPACE FOR SHIFT REG RANSH STORE ETC
DIF     EQU     30*2            ;127-97   WORDS AS BYTES
LEN     EQU     128             ;THIS IS FIXED IN THIS CODE
RREG    DW      LEN DUP(?)      ; NEEDS OFFSET 0 FROM DS:///
;
;  .**. / .**. .**. .**.     .**. .**. / .**.
;  :      :    :                  :  :   :
;  MLATL  MLAT :                  MLATN  MLATH
;              MLAT1                 MLAST
;
MLATL   DW      LX*LY DUP(0)   ; HELICAL BOUNDARY CONDITIONS,SHADOW PLANE
MLAT    DW      LX*LY*LZ DUP(0) ; MAIN LATTICE STORE-16 COPIES
MLATH   DW      LX*LY DUP(0)
;        NEIGHBOUR ADDRESS RELATIVE SITE CHOSEN
LSQ     EQU     2*LX*LY
L1P     EQU     +2
L1M     EQU     -2
L2P     EQU     +2*LX
L2M     EQU     -2*LX
L3P     EQU     +LSQ
L3M     EQU     -LSQ
LCUBE   EQU     2*LX*LY*LZ
LCUBEM  EQU     -LCUBE
; MEMORY OFFSETS
MLAT1   EQU     MLAT+LSQ
MLATN   EQU     MLATH-LSQ
MLAST   EQU     MLATH-2
;
; --RANFA SEEDS---
SEEDH   DW      0H              ;ANY SEED
SEEDL   DW      0F001H
POINT   DB      0               ;RUNS 0,2,4.. 254 /SHIFT REG POINT
COUNT   DW      ITCOUNT
;USED TO INITIALISE D0 ,D1  LISTS
COUNTST DW      8 DUP(0)
BITNO   DW      16
;
MEASCT  DW      MEASVAL         ;DEC TO 0
NUMDN   DW      0
;
; SPACE TO STORE M- SUMS ON 16 LATTICES
STORE   DW      16 DUP(0)       ;INITIALISE TO ZERO
STOREPL DW      ?
MODML   DW      16 DUP(0)       ;MOD M
MODMH   DW      16 DUP(0)
MSQL    DW      16 DUP(0)       ;M**2
MSQH    DW      16 DUP(0)       ;M**2
MSQP    DW      16 DUP(0)       ;M**2
MFTHL   DW      16 DUP(0)       ;M**4
MFTHH   DW      16 DUP(0)       ;M**4
MFTHP   DW      16 DUP(0)       ;M**4
;
;------------UP TO HERE GETS READ IN     --, WRITTEN TO DISK-------
LENVRAM         DW  ?
LMTT    EQU     OFFSET LENVRAM
;
TITL_W  DB    0DH,0AH,'100*60*20*24**3 XOR SHIFT SH=R,128,SHUFFLE D0/D2',0DH,0AH
        DB    ' READ L243IS0.DAT  48000      8MARCH 86              ',0DH,0AH
        DB    '    MMOD   /MSQ/2**16  /M**4/2**32   ',0DH,0AH,'$'
PRMOD   DB      10 DUP(0)
PRMSQ   DB      11 DUP(0)
PRMFTH  DB      11 DUP(0),0DH,0AH,'$'
AVMOD   DW      4 DUP(0)                ;SUM OF 16 LATTS
AVMSQ   DW      4 DUP(0)
AVMFTH  DW      4 DUP(0)
PT_BF   DB      'AVERAGES',0DH,0AH,7  DUP(0)
PT_MOD  DB      '.',13 DUP(0)
PT_MSQ  DB      '.',13 DUP(0)
PT_MFTH DB      '.',10 DUP(0),0DH,0AH,'$'
;       ---NEEDED FOR WRITE/READ-----
INITFLAG    DW      1   ;ZERO FOR RESET NUMDN TO 0,IF IT WAS AT MAX
FNAME       DB     'c:L243IS.DAT',0     ;  ASCIIZ
ERR1        DB     'Can''t access file',0Dh,0Ah,'$'
ERR2        DB     'WRITE error',0Dh,0Ah,'$'
ERR3        DB     'NOT ALL BYTES WRITTEN',0Dh,0Ah,'$'
ERR4        DB     'CAN''T CLOSE FILE',0Dh,0Ah,'$'
FRNAME      DB     'c:L243IS0.DAT',0
ERR6        DB     'READ  error',0Dh,0Ah,'$'
ERR7        DB     'NOT ALL BYTES READ',0Dh,0Ah,'$'
QUERY   DB      'TYPE ANY ONE ASCII CHARACTER AS SEED =','$'
;
ESEG    ENDS
;
D0_SEG SEGMENT PARA
        ORG     0
D0_ST  DW      32767 DUP(?)   ;CARE LINK SEES 32768 AS 0 LENGTH
D0_SEG ENDS
;
D1_SEG SEGMENT PARA
        ORG     0
D1_ST  DW      32767 DUP(?)
D1_SEG ENDS
;
D2_SEG SEGMENT PARA
        ORG     0
D2_ST  DW      32767 DUP(?)
D2_SEG ENDS
;
;ASM 3D ISING WITH 16 LATTICES IN 1 WORD
;
ISCODE  SEGMENT PARA 'CODE'
        ASSUME  CS:ISCODE,DS:ESEG,SS:SHOWSTACK
ENTPT:
;
        MOV     CX,SEG RREG
        MOV     DS,CX
;INITIALISE RANSH    WITH RANFA
        MOV     BX,254  ;TOP OF RREG (128 WORDS)
INITSH:
        CALL    RANFA
        MOV     RREG[BX],AX
        SUB     BX,2            ;SETS CF IF BX WAS 0
        JNC     INITSH
;
; INITIALISE 16 LATTICES: HOT RANDOM VALUES
        MOV     BX,LCUBE-2      ;2 L**3 BYTES    0,..
INITLAT:
        CALL    RANFA
        MOV     MLATL[BX],AX    ;DO -L**2 TO L**3-L**2 WORDS
        SUB     BX,2
        JNC     INITLAT         ;BX NOW =0 JUMPS ALSO
; ADD IN SHADOW COPIES         BOTH DONE TOGETHER
        MOV     BX,LSQ*2-2      ;2* 2 L**2 BYTES    0,..
INITCOPY:
        MOV     AX,MLATL[BX]
        MOV     MLATN[BX],AX
        SUB     BX,2
        JNC     INITCOPY
;----READ--------
        MOV     DI,OFFSET RREG
        MOV     CX,LMTT         ;OVERWRITE RAND STUFF,LATT,AVERAGES,ETC
        CALL READ                                          ;====OPTION
KEEP_ON:
        MOV     MEASCT,MEASVAL
        MOV     AX,NUMDN
        CMP     AX,0
        JA      DO_SOME
;---HERE SET SEED,CHOOSE DIFF ON EACH OCCASION---------/1/ PASS---
        MOV     DX,OFFSET QUERY
        MOV     AH,9
        INT     21H
        MOV     AH,0CH
        MOV     AL,01H
        INT     21H
        CMP     AL,37   ;ASCII %
        JE      AS_IS
        MOV     SEEDH,AX        ;SEEDH IS ASCII CHAR READ FROM KEYBOARD
AS_IS:
;WANT D0_,ETC LISTS DIFF TOO SO REINITIALISE RANSH WITH NEW SEEDH
        MOV     BX,254  ;TOP OF RREG (128 WORDS)
INITXX:
        CALL    RANFA
        MOV     RREG[BX],AX
        SUB     BX,2            ;SETS CF IF BX WAS 0
        JNC     INITXX
;  SET MODML,...MFTHP TO ZERO,ALSO STORE FOR SAFETY
        MOV     DI,OFFSET STORE
ZERO_NEXT:
        MOV     WORD PTR[DI],0
        ADD     DI,2
        CMP     DI,OFFSET LENVRAM
        JB      ZERO_NEXT
;
        JMP     DO_SOME1
DO_SOME:
        CMP     AX,NUMBL
        JNE     DO_SOME1
;--NUMDN=MAX HERE
        CMP     INITFLAG,0
        JNE     NOSWAP
        MOV     INITFLAG,1      ;IF ZERO RESET NUMDN
        MOV     NUMDN,0
NOSWAP:
        JMP     END_ALL
DO_SOME1:                                       ;--/ALL PASSES/--
;
;---------------SET UP D0_,D1_ D2_ LISTS-----------------------------------

; CONVENTIONS FOR HEAT BATH ISING:BIT 1 UP, BIT 0 DOWN
; M=SUM 6 NEAREST NEIGHBOURS OF SITE:0 TO 6 IN VALUE
; PROB OF SITE UP IS F(M)=1/(EXP(4*BETA*(3-M))+1)
; DEFINE D SUCH THAT SITE IS UP IF D+M>=7
;   D:  0       1         2         3         4         5         6         7
;WEIGHT1-F(6) F(6)-F(5) F(5)-F(4) F(4)-F(3) F(3)-F(2) F(2)-F(1) F(1)-F(0) F(0)
;PARTITION 16-BIT RANDOM NUMBER WITH THESE RELATIVE WEIGHTS
; USE MSBIT TO CHOOSE 0-3 VERSUS 4-7 :50-50 CHOICE    ,F(3)=0.5
; THEN USE 15 REMAINING BITS TO SELECT /SHIFT LEFT TO USE AS FOLLOWS:-
; 0 <=  3  < R23 <= 2 < R12 <= 1 < R01 <= 0 <  65536
;  OR   4           5          6          7      FOR BETA=0.22165
R23     EQU     13644   ;2**32*(F(4)-F(3))        13643.81  R3
R12     EQU     23256   ;2**32*(F(5)-F(3))        23255.79  R3+R2
R01     EQU     28483   ;2**32*(F(6)-F(3))        28482.76  R3+R2+R1
DRN0    EQU     2142    ;  4285
DRN1    EQU     2614    ;  5227
DRN2    EQU     4806    ;  9612
DRN3    EQU     6822    ; 13644
TOTAL   EQU     65534           ;NO BYTES
;
        MOV     AX,SEG   D1_ST ;OFFSET 0
        MOV     ES,AX
ASSUME            ES:D1_SEG
        MOV     BITNO,16
;
NEXT_BIT:
        MOV     COUNTST,DRN0    ;COUNT D0 VALUES USED,ETC
        MOV     COUNTST+14,DRN0 ;COUNT D7 VALUES USED,ETC
        MOV     COUNTST+2,DRN1
        MOV     COUNTST+12,DRN1
        MOV     COUNTST+4,DRN2
        MOV     COUNTST+10,DRN2
        MOV     COUNTST+6,DRN3
        MOV     COUNTST+8,DRN3
        MOV     SI,TOTAL
NEW_R:
;128 16 BIT SHIFT REGISTER ALGORITHM  //MUST BE INITIALISED//POINT IN SP
;RETURNS RANDOM 16-BIT WORD IN AX,R(I)=XOR(R(I-127),R(I-97))//RREG AT OFFSET 0
        XOR     AH,AH           ; POINT    AX     BX     BP
        MOV     AL,POINT        ;    I     ?      ?      ?
        MOV     BX,AX           ;         I      I       ?
        ADD     AL,62           ;         I+31
        XCHG    AX,BX           ;         I      I+31
        MOV     BP,[BX]         ;                       R[I+31]
        SUB     BL,60           ;                I+1
        XOR     BP,[BX]         ;                     X(R[I+1],R[I+31])
        XCHG    AX,BX           ;         I+1    I
        MOV     [BX],BP         ;                STORE NEW R[I]
        MOV     POINT,AL        ;   I+1
        MOV     AX,BP           ;   16 BIT RANDOM NO IN BP
        JMP     RRINT
;
;HERE IS BRANCH OF D1,D0 SELECTION CODE    //INIT D01,ETC
X01_T:
        RCL     BX,1            ;HERE 29%, SETS D1=0 (CF VALUE)
        CMP     AX,R01          ;CF=1 IF AX<R01
        JMP     BACK_INT        ;TO SET D0=1 FROM CF ON ARRIVING
RRINT:
; CONVERT 16 BIT RANDOM NO TO VALUE OF D OF 0 TO 7
        AND     AX,7FFFH          ;           B15=0
        XOR     BX,BX           ;BX=0
        CMP     AX,R12          ;CF=1 IF AX<R12
        JAE     X01_T           ;AX>=R12 (29% CASE) JUMP
        RCL     BX,1            ;CF=>B0 OF BX :D1
        CMP     AX,R23          ;CF=1 IF AX<R23
BACK_INT:
        RCL     BX,1            ;CF=>B0 OF BX :D0  //BX IS D1,D0 NOW
        RCL     BP,1            ;GET MSB FROM BP
        SBB     BP,BP           ;00000 OR 11111
        XOR     BX,BP           ; NOT BX IF MSB=1
        AND     BX,7            ; MAKE 0-7 //THIS IS D2,D1,D0
        SAL     BX,1            ;*2     FOR WORD TABLE
        CMP     COUNTST[BX],0   ;TEST COUNTS,1 AT LAST CALC
        JE      NEW_R
        DEC     COUNTST[BX]
;----DIST APPROX OK,FINE TUNE BY GETTING ALL COUNTS TO 0
        SHR     BX,1            ;RESTORE   D2,D1,D0
        MOV     AX,SEG D0_ST
        MOV     DS,AX
        SHR     BX,1            ;CF IS D0
        RCL     DS:WORD PTR[SI],1      ;D0 TO D0_ST   BIT 0
        SHR     BX,1
        RCL     ES:WORD PTR[SI],1      ;D1 TO D1_ST   BIT 1
        MOV     AX,SEG D2_ST
        MOV     DS,AX
        SHR     BX,1
        RCL     DS:WORD PTR[SI],1      ;D2 TO D2_ST BIT 2
        MOV     AX,SEG RREG     ;CARE IF USING V-RAM///////OR ESEG
        MOV     DS,AX           ;ADDRESS ESEG AGAIN
        SUB     SI,2            ; SI=0 IS LAST CALC
        JNC     NEW_R           ;DO NEXT D1,D0 ENTRIES IN LIST
;
        SUB     BITNO,1
        JZ      MEAS_HOP        ;DO ALL 16 BITS
        JMP     NEXT_BIT
;  -------------------------------------------------------------------
MEAS_HOP:
        MOV     COUNT,ITCOUNT
;
HOP:
;SET UP COUNT OVER LATTICE     IN DI
        MOV     DI,OFFSET MLAT  ;ADDRESS LOADED
        SUB     DI,2
        MOV     DX,[DI]         ;FOR FIRST PASS OF LATTICE
;////////////////START INNER LOOP////////////////////////////
TOP_LOOP:
        ADD     DI,2
;                                             ------100 T CYCLES----
;128 16 BIT SHIFT REGISTER ALGORITHM  //MUST BE INITIALISED//POINT IN SP
;RETURNS RANDOM 16-BIT WORD IN BP,R(I)=XOR(R(I-127),R(I-97))//RREG AT OFFSET 0
        XOR     AH,AH           ; POINT    AX     BX     BP
        MOV     AL,POINT        ;   I     ?       ?      ?P
        MOV     BX,AX           ;         I      I       ?
        ADD     AL,62           ;         I+31
        XCHG    AX,BX           ;         I      I+31
        MOV     BP,[BX]         ;                       R[I+31]
        SUB     BL,60           ;                I+1
        XOR     BP,[BX]         ;                     X(R[I+1],R[I+31])
        XCHG    AX,BX           ;         I+1    I
        MOV     [BX],BP         ;                STORE NEW R[I]
        MOV     POINT,AL        ;   I+1
                                ;   16 BIT RANDOM NO IN BP
;
;
; CALCULATE SUM M OF 6 SITES (NN) IN BX,CX,DX FOR BITS 0,1,2 ---------
;                           244 T CYCLES UP TO RELOAD SITE
        MOV     AX,L1P[DI]
        MOV     BX,DX           ;SITE UPDATED LAST TIME (L1M)
        MOV     CX,BX
        AND     CX,AX           ;AND DEST,SOURCE   CARRY TO B1
        XOR     BX,AX           ;B0
;
        MOV     AX,L2P[DI]
        MOV     SI,AX
        AND     AX,BX           ;CARRY TO B1
        XOR     BX,SI           ;B0
        XOR     CX,AX           ;B1 (NO CARRY TO B2-SUM 3 BITS)
;
        MOV     AX,L2M[DI]
        MOV     SI,AX
        AND     AX,BX           ;CARRY TO B1
        XOR     BX,SI           ;B0
        MOV     DX,AX
        AND     DX,CX           ;CARRY TO B2
        XOR     CX,AX           ;B1
;
        MOV     AX,L3P[DI]
        MOV     SI,AX
        AND     AX,BX           ;CARRY TO B1
        XOR     BX,SI           ;B0
        MOV     SI,AX
        AND     AX,CX           ;CARRY TO B2
        XOR     CX,SI           ;B1
        XOR     DX,AX           ;B2 (NO CARRY TO B3-5 BITS SUMMED)
;
        MOV     AX,L3M[DI]
        MOV     SI,AX
        AND     AX,BX           ;CARRY TO B1
        XOR     BX,SI           ;B0
        MOV     SI,AX
        AND     AX,CX           ;CARRY TO B2
        XOR     CX,SI           ;B1
        XOR     DX,AX           ;B2 (NO CARRY TO B3-6 BITS SUMMED)
;
; ADD 1 TO (DX,CX,BX) ALL 16 BITS
        MOV     AX,BX           ;CARRY TO B1=AND BX,111111..11
        NOT     BX              ;B0         =XOR BX,111111..11
        MOV     SI,AX
        AND     AX,CX
        XOR     CX,SI
        XOR     DX,AX
;
; ADD 3-BIT VECTORS M  (DX,CX,BX) TO D2,D1,D0 -LOOK FOR CARRY TO B3
;                           1-7            0-7       SUM>=8
; USE BP TO LOOK UP LIST OF D0,D1,D2 WORDS
;                             ///CHECK [BP] IS PERIODIC MOD 2**16 /// YES
        XCHG    BP,SI
        AND     SI,0FFFEH               ;MAKE EVEN
        MOV     AX,SEG D0_ST
        MOV     DS,AX
        AND     BX,[SI]         ; ASSUMES DS: D0_ST   CARRY TO B1
;
        MOV     AX, ES:[SI]     ;        D1_ST
        MOV     BP,AX
        AND     AX,CX           ;CARRY TO B2
        XOR     CX,BP           ;B1
        AND     CX,BX           ;B1+CARRY TO B1==>CARRY TO B2
        XOR     CX,AX           ;TOTAL CARRY TO B2
;
        MOV     AX,SEG D2_ST
        MOV     DS,AX
        MOV     AX,[SI]         ;    D2_ST
        MOV     BP,AX
        AND     AX,DX           ;CARRY TO B3
        XOR     DX,BP           ;B2
        AND     DX,CX           ;B2+CARRY TO B2 =>CARRY TO B3
        XOR     DX,AX           ;TOTAL CARRY TO B3
        MOV     AX,SEG RREG     ; /////CARE IF USING V-RAM    OR ESEG
        MOV     DS,AX
;
LOAD_SITE:
        MOV     [DI],DX         ;HEAT BATH UPDATED SITES TO LATTICE ----
;       MOV     [DI+8192],DX    ;COPY TO INTERLACED SCREEN DISPLAY
;
        CMP     DI,OFFSET MLAT1 ;DI<LAT1 COPY SHADOW UP
        JB      COPY_UP         ;BELOW
        CMP     DI,OFFSET MLATN ;DI>=LATN COPY SHADOW DOWN
        JAE     COPY_DOWN       ;ABOVE OR EQUAL
        JMP     TOP_LOOP        ;END/JUMP 35 T CYCLES--------------------
;///////////END INNER LOOP//////////////////////////////////////////
COPY_DOWN:
        MOV     LCUBEM[DI],DX
        CMP     DI,OFFSET MLAST ;DI=LAST RESET COUNT
        JE      RESET
        JMP     TOP_LOOP
RESET:
        SUB     DI,LCUBE        ;RESET TO MLAT-2
        JMP     QUIT_LOOP
COPY_UP:
        MOV     LCUBE[DI],DX
        JMP     TOP_LOOP
;
QUIT_LOOP:
        DEC     COUNT
        JZ      MEASURE
        JMP     HOP             ;TOP OF LOOP
MEASURE:
;
;.....MEASURE 16 LATTICES AT PRESENT IN MLAT,SUMS OF BITS SET (M) IN STORE
        MOV     DI,OFFSET MLAT
        SUB     DX,DX
MEAS_NEXT:
        MOV     BX,OFFSET STORE
        MOV     AX,[DI]
MEAS_SHFT:
        SAL     AX,1            ;MS BIT TO CF
        ADC     [BX],DX         ;DX=0, SO ADD CF TO STORE NO BX
        ADD     BX,2            ;NEXT WORD IN STORE
        CMP     BX,OFFSET STOREPL      ;ONE PAST END
        JB      MEAS_SHFT       ; J BELOW
        ADD     DI,2
        CMP     DI,OFFSET MLATH ;ONE PAST END
        JB      MEAS_NEXT
;RESULT IN STORE     SUM M NUMBER OF BITS SET 0-L**3
;------------------ACCUMULATE AVERAGES---------------------
        SUB     BX,BX           ;COUNT 16 WORDS/16 LATTICES
NEXT_L:
        MOV     AX,STORE[BX]
        MOV     STORE[BX],0     ;RE INITIALISE STORE
        SAL     AX,1
        SUB     AX,LX*LY*LZ     ;M NOW SUM +/-1 PER SITE
        JNC     POS_V
        NEG     AX
POS_V:                          ; MOD M NOW
        ADD     MODML[BX],AX
        ADC     MODMH[BX],0
;
        MUL     AX              ;AX*AX=>DX,AX
        ADD     MSQL[BX],AX
        ADC     MSQH[BX],DX
        ADC     MSQP[BX],0
;                              DX,AX RANGE 0 - L**6 DIVIDE BY 256
        MOV     AL,AH
        MOV     AH,DL
        MUL     AX
        ADD     MFTHL[BX],AX
        ADC     MFTHH[BX],DX
        ADC     MFTHP[BX],0
;
        ADD     BX,2
        CMP     BX,30
        JBE     NEXT_L
        DEC     MEASCT
        JZ      FINISHBL
        JMP     MEAS_HOP        ;REDO ANOTHER COUNT OF LATTS
FINISHBL:   ;------------WRITE--INFO-------------
;---WRITE LATTICE--RANDOM NUMBER INFO      /INFO NOW IN ESEG/
        INC     NUMDN
        MOV     DI,OFFSET RREG
        MOV     CX,LMTT         ;RREG+LATT+COUNT+SEEDS+COPYW+POINT-BYTES
        CALL    WRITE
        JMP     KEEP_ON
; -------------------------------------------------------------------
END_ALL:
        MOV     DX,OFFSET TITL_W
        MOV     AH,09H
        INT     21H
        SUB     BX,BX
NEXT_OUT:
        MOV     DX,MODMH[BX]
        MOV     AX,MODML[BX]
        MOV     DI,OFFSET PRMOD
        CALL    PRDWORD
        MOV     DX,MSQP[BX]
        MOV     AX,MSQH[BX]
        MOV     DI,OFFSET PRMSQ
        CALL    PRDWORD
        MOV     DX,MFTHP[BX]
        MOV     AX,MFTHH[BX]
        MOV     DI,OFFSET PRMFTH
        CALL    PRDWORD
        MOV     DX,OFFSET PRMOD
        MOV     AH,09H
        INT     21H
        ADD     BX,2
        CMP     BX,30
        JBE     NEXT_OUT
;
; FORM RATIOS AND AVERAGE 16 LATTICES
        SUB     BX,BX
NEXT_AV:
        MOV     AX,MODML[BX]
        ADD     AVMOD+4,AX
        MOV     AX,MODMH[BX]
        ADC     AVMOD+2,AX
        XOR     AX,AX
        ADC     AVMOD,AX
        MOV     AX,MSQL[BX]
        ADD     AVMSQ+4,AX
        MOV     AX,MSQH[BX]
        ADC     AVMSQ+2,AX
        MOV     AX,MSQP[BX]
        ADC     AVMSQ,AX
        MOV     AX,MFTHL[BX]
        ADD     AVMFTH+4,AX
        MOV     AX,MFTHH[BX]
        ADC     AVMFTH+2,AX
        MOV     AX,MFTHP[BX]
        ADC     AVMFTH,AX
        ADD     BX,2
        CMP     BX,30
        JBE     NEXT_AV
;                     ----------NORMALISE /(L**3 * 16 *MEASPR)
        MOV     DI,OFFSET  AVMOD
        MOV     BX,8*MEASPR   ;ASSUME FITS 1 WORD
        CALL    DIVBX
        MOV     BX,LCUBE   ;ASSUME FITS ONE WORD     2  LX*LY*LZ
        CALL    DIVBX
        MOV     DI,OFFSET PT_MOD
        MOV     DX,AVMOD+4
        MOV     AX,AVMOD+6
        CALL    PRDEC           ;DX.AX
        MOV     DI,OFFSET AVMSQ
        MOV     BX,8*MEASPR   ;ASSUME FITS 1 WORD
        CALL    DIVBX
        MOV     BX,LCUBE
        CALL    DIVBX
        MOV     DI,OFFSET PT_MSQ
        MOV     DX,AVMSQ+4
        MOV     AX,AVMSQ+6
        CALL    PRDEC           ;DX.AX
        MOV     DI,OFFSET AVMFTH
        MOV     BX,8*MEASPR   ;ASSUME FITS 1 WORD
        CALL    DIVBX
        MOV     BX,LCUBE
        CALL    DIVBX
        MOV     DI,OFFSET PT_MFTH
        MOV     DX,AVMFTH+4
        MOV     AX,AVMFTH+6
        CALL    PRDEC           ;DX.AX
        MOV     DX,OFFSET PT_BF
        MOV     AH,09H
        INT     21H
;---WRITE LATTICE--RANDOM NUMBER INFO      /INFO NOW IN ESEG/
        MOV     DI,OFFSET RREG
        MOV     CX,LMTT         ;RREG+LATT+COUNT+SEEDS+COPYW+POINT-BYTES
        CALL    WRITE
        MOV     AH,4CH
        INT     21H             ;RETURN TO DOS
;---------------------------------------------------------------
DIVBX   PROC    NEAR
;---ASSUMES OFFSET DBF IN DI,DIVISOR IN BX
;--- DI BX RETAIN VALUES ,OTHER REGISTERS RESTORED
;   BEFORE  DBF: **************** **************** ****************  ***..*
;   AFTER /BX  : **************** **************** ****************  ***..*
        PUSH    AX
        PUSH    DX
        MOV     AX,[DI]
        XOR     DX,DX
        DIV     BX              ;(0,AX)/BX:UNSIGNED AX,REM DX
        MOV     [DI],AX
        MOV     AX,[DI+2]
        DIV     BX              ; (DX,AX)/BX NO OVERFLOW SINCE DX IS REM.
        MOV     [DI+2],AX
        MOV     AX,[DI+4]
        DIV     BX              ;(DX,AX)/BX
        MOV     [DI+4],AX
        MOV     AX,[DI+6]
        DIV     BX              ;(DX,AX)/BX
        RCL     DX,1
        ADC     AX,0            ;ROUND UP IF MSB OF REMAINDER IS 1
        MOV     [DI+6],AX
        POP     DX
        POP     AX
        RET
DIVBX   ENDP
;------------------------------------------------------------------
PRDWORD PROC    NEAR
;-------ASSUMES DI CONTAINS ADDRESS OF LEFT-HAND END OF STORE (10 BYTES)
;-------ASSUMES DX,AX CONTAIN DOUBLE WORD,NO OTHER REGISTER AFFECTED
;-------ASSUMES POSITIVE RESULT ;DI,AX,DX CHANGED
        PUSH    BP
        PUSH    BX
        MOV     BX,0AH          ;SET SPACES IN BUFFER
SPACE_IN:
        MOV     BYTE PTR [DI],' '
        INC     DI
        DEC     BX              ;COUNT 10
        JNZ     SPACE_IN
        DEC     DI
;
        XCHG    BP,DX
        MOV     BX,0AH          ;/10
RPT1:
        CMP     BP,0
        JZ      RPT2
        XCHG    AX,BP
        XOR     DX,DX
        DIV     BX              ;(DX,AX)/BX=AX,REM DX
        XCHG    BP,AX
        DIV     BX
        OR      DL,30H          ;ASCII +48
        MOV     [DI],DL
        DEC     DI
        JMP     RPT1
RPT2:
        XOR     DX,DX
        DIV     BX
        OR      DL,30H
        MOV     [DI],DL
        DEC     DI
        CMP     AX,0
        JNZ     RPT2
;
        POP     BX
        POP     BP
        RET
PRDWORD ENDP
;----------------------------------------------------------------------
PRDEC   PROC    NEAR
;----ASSUMES DI CONTAINS ADDRESS OF DECIMAL POINT,(6 DUP(0),'.',6 DUP(0))
;----ASSUMES DX,AX CONTAIN INTEGER,HEXIMAL PARTS     SIGN + OR -
        PUSH    CX
        PUSH    BX
        PUSH    AX
        PUSH    DI
;
        PUSH    DX
        OR      DX,DX           ;SETS SF
        JNS     POS_HW
        NEG     AX
        XOR     CX,CX
        SBB     CX,DX           ;0,0 - DX,AX
POS_HW:
        MOV     BX,0AH          ;10
        MOV     AX,DX
NEXT_HW:
        CMP     AX,0
        JZ      DONE_HW
        XOR     DX,DX
        DIV     BX              ; (0,AX)/10 = AX ,REM DX
        OR      DL,30H
        DEC     DI
        MOV     [DI],DL
        JMP     NEXT_HW
DONE_HW:
        POP     DX              ;ORIGINAL HW  ,TEST SIGN
        OR      DX,DX
        JNS     DEC_PT
        DEC     DI
        MOV     BYTE PTR[DI],'-'
DEC_PT:
        POP     DI              ;RESTORE ADDRESS OF DEC PT
        POP     AX
        MOV     CX,6
NEXT_DIG:
        INC     DI
        MUL     BX              ;AX*BX=DX,AX  DX IS DEC DIGIT,AX REMAINDER
        OR      DL,30H
        MOV     [DI],DL
        DEC     CX
        JNZ     NEXT_DIG
;
        POP     BX
        POP     CX
        RET
PRDEC   ENDP
;--------------------------------------------------------
RANFA   PROC    NEAR
; 32 BIT UNSIGNED CONGRUENCE RANDOM NO GENERATOR   :FAST VERSION
; MULTIPLIER 69069  MOD 2**32  RETURNS MS 16 BITS IN AX
; NO OTHER REGISTERS AFFECTED EXCEPT FLAGS
;  SEEDH,SEEDL DW STORED IN CALLING PROGRAM
;MULTIPLIER  IS 69069=3533+65536      BIN 1 0000 1101 1100 1101
                      ;-------------CODE HERE TO LINE 227 T-CYCLES 8088
                      ;   81 USED BY PUSH/POP ,56 BY MOVING 2 SEED WORDS
        PUSH    BX
        PUSH    CX
        PUSH    DX
        MOV     AX,SEEDL
        MOV     DX,SEEDH
        MOV     BX,AX
        MOV     CX,DX
        SAL     AX,1
        RCL     DX,1            ;32 BIT L SHIFT      *2
        ADD     AX,BX
        ADC     DX,CX           ;32 BIT ADD          *3
        SAL     AX,1
        RCL     DX,1
        SAL     AX,1
        RCL     DX,1            ;      DX,AX         *12
        ADD     BX,AX
        ADC     CX,DX           ;      CX,BX         *13
        SAL     AX,1
        RCL     DX,1
        SAL     AX,1
        RCL     DX,1
        SAL     AX,1
        RCL     DX,1
        SAL     AX,1
        RCL     DX,1            ;      DX,AX         *192
        ADD     AX,BX
        ADC     DX,CX           ;  DX,AX             *205
        MOV     CH,CL
        MOV     CL,BH
        MOV     BH,BL
        SUB     BL,BL           ;  CX,BX BYTE SHIFT  *256*13
        ADD     AX,BX
        ADC     DX,CX           ;                    *3533
        ADD     DX,SEEDL        ;  WORD SHIFT *65536 +*3533
        MOV     SEEDL,AX
; RESULT IN DX,AX
        MOV     AX,DX           ;SINCE MS 16 BITS MOD 2**32 NEEDED BY CM
        MOV     SEEDH,AX
        POP     DX
        POP     CX
        POP     BX
                       ;----------------------------------------------
        RET
RANFA   ENDP
;--------------------------------------------------------------------
DOSINT      MACRO  function            ;; Call the DOS interrupt
            mov    ah,function         ;; Put function number in AH
            int    21h
            ENDM

ERROR       MACRO  errnum              ;; Display error and exit
            mov    dx,OFFSET ERR&errnum;; Load address of error message
            DOSINT 09h                 ;; Display string function
            mov    al,errnum           ;; Exit with return code of errnum
            dosint 4Ch                 ;; Quit
            ENDM

WRITE   PROC    NEAR
;----ASSUMES BUFFER OFFSET IN DI,LENGTH IN CX----
;FNAME       DB     'c:L83IS.DAT',0     ;  ASCIIZ      //STORED IN ESEG
;ERR1        DB     'Can''t access file',0Dh,0Ah,'$'
;ERR2        DB     'WRITE error',0Dh,0Ah,'$'
;ERR3        DB     'NOT ALL BYTES WRITTEN',0Dh,0Ah,'$'
;ERR4        DB     'CAN''T CLOSE FILE',0Dh,0Ah,'$'
        MOV     DX,OFFSET FNAME
        PUSH    CX
        SUB     CX,CX           ;ATTRIBUTE SET 0
        DOSINT  3CH             ;OPEN  R/W NEW FILE
        JNC     NERR1
        ERROR   1
NERR1:
        MOV     DX,DI
        MOV     BX,AX           ;FILE HANDLE
        POP     CX
        DOSINT  40H             ;WRITE CX BYTES FROM [DI],..
        JNC     NERR2
        ERROR   2
NERR2:
        CMP     AX,CX           ;TEST IF AX BYTES WRITTEN = CX
        JE      NERR3
        ERROR   3
NERR3:
        DOSINT  3EH             ;CLOSE
        JNC     NERR4
        ERROR   4
NERR4:
        RET
WRITE   ENDP
;-----------------------------------------------------------------
READ    PROC    NEAR
;----ASSUMES BUFFER OFFSET IN DI,LENGTH IN CX----
;FRNAME      DB     'c:L83IS0.DAT',0     ;  ASCIIZ      //STORED IN ESEG
;ERR6        DB     'READ  error',0Dh,0Ah,'$'
;ERR7        DB     'NOT ALL BYTES READ',0Dh,0Ah,'$'
        MOV     DX,OFFSET FRNAME
        SUB     AL,AL           ;MODE READ
        DOSINT  3DH             ;OPEN          FILE
        JNC     NRERR1
        ERROR   1
NRERR1:
        MOV     DX,DI
        MOV     BX,AX           ;FILE HANDLE
        DOSINT  3FH             ;READ CX BYTES FROM [DI],..
        JNC     NRERR2
        ERROR   6
NRERR2:
        CMP     AX,CX           ;TEST IF AX BYTES WRITTEN = CX
        JE      NRERR3
        ERROR   7
NRERR3:
        DOSINT  3EH             ;CLOSE
        JNC     NRERR4
        ERROR   4
NRERR4:
; DELAY RETURN SO TIMER INTERRUPT CAN STOP DISKETTE MOTOR BEFORE CLI
        MOV     CX,0FFFFH
LOOP_TIME:
        MOV     BX,8            ;N=8
GEE:    SUB     BX,1
        JNZ     GEE
        LOOP    LOOP_TIME ;DELAY ABOUT 33*N+1*66000/5000000 > 2 SEC
        RET
READ    ENDP
;-----------------------------------------------------------------
ISCODE  ENDS
        END     ENTPT   ;START ADDRESS
