      PROGRAM CALLM2
C Purpose: calls real mode program via address
C Copyright (C) MicroWay, Inc. 1989
C Usage: run386 -minreal ???? callm2.exp
C where ???? is the minimum number of paragraphs
C of conventional memory to be reserved for the
C real mode program. See appropriate section of
C Phar Lap manual.

      INTEGER BUFFSIZE, PARASIZE
      PARAMETER (BUFFSIZE=1, PARASIZE=16)

      INTEGER MSIZE,NSIZE
      PARAMETER (MSIZE=((BUFFSIZE*PARASIZE)/2), NSIZE=4)

      INTEGER INTNUM, BUFFSEG
      INTEGER PHYSADD
      INTEGER*2 M(MSIZE)
      INTEGER*2 N(NSIZE)
      CHARACTER*80 COMMANDLINE
      INCLUDE 'DOS.FH'

C INT 21 hexadecimal (33 decimal), service 25C0 hexadecimal
C (9664 decimal) is used to allocate BUFFSIZE paragraphs of
C MS-DOS memory. The segment address of the allocated buffer
C is stored in BUFFSEG.
C       winregs(3) = bx
C       winregs(1) = ax
      INTNUM = Z'21'
      WINREGS(3) = BUFFSIZE
      WINREGS(1) = Z'25C0'
      CALL INT386(INTNUM,INREGS(1),OUTREGS(1))
C Paragraph address of real mode buffer returned in AX
      BUFFSEG = WOUTREGS(1)

      WRITE(COMMANDLINE, 20) BUFFSEG
   20 FORMAT("RB.EXE ", I5)
      WRITE (*,*) COMMANDLINE
C system invokes the real mode program named in COMMANDLINE
      CALL SYSTEM (COMMANDLINE)
C Convert paragraph address in BUFFSEG to 32-bit address
      PHYSADD = BUFFSEG * 16

C In this example, BLK_MB() moves 16 bytes of information
C from offset PHYSADD in conventional memory to the array
C M() in the NDP program's data segment. Conventional memory
C is accessed by Phar Lap's segment selector 34 hexadecimal
C (52 decimal). Segment 34h maps to the first megabyte
C of memory (real memory), and the address is
C calculated by multiplying the real mode segment
C by 16 (done above) and adding the offset into
C the segment (in this case, 0).

      CALL BLK_MB(M(1), Z'34', PHYSADD, (BUFFSIZE*PARASIZE))

C The BASIC program has loaded M(4) with the
C segment and M(3) with the offset of a data
C transfer area.

      PHYSADD = M(4) * 16 + M(3)
      N(1) = 2
      N(2) = 3
      N(3) = 5
      N(4) = 7

C The call to BLK_BM() is syntactically similar
C to the one to BLK_MB(). In this case, it loads
C the BASIC array with the values found in N(1)
C through N(4).

      CALL BLK_BM(N(1), Z'34', PHYSADD, (2*NSIZE))
C winregs(3) = bx
C winregs(4) = high byte of ebx
C inregs(3) = ecx
C winregs(1) = ax

      INTNUM = Z'21'
      WINREGS(3) = M(1)
      WINREGS(4) = M(2)
      INREGS(3) = 0
      WINREGS(1) = Z'250E'

C This call to INT386 places a call to the entry
C point BASIC left in the M() array at segment
C M(2), offset M(1)

      CALL INT386(INTNUM,INREGS(1),OUTREGS(1))

C The array, as altered by BASIC, brought back
C to protected mode by a last call to BLK_MB().

      CALL BLK_MB(N(1), Z'34', PHYSADD, (2*NSIZE))
      WRITE(*,*) N(1), N(2), N(3), N(4)

C Free MS-DOS memory allocated above
C       winregs(5) = cx
C       winregs(1) = ax
      INTNUM = Z'21'
      WINREGS(5) = BUFFSEG
      WINREGS(1) = Z'25C1'
      CALL INT386(INTNUM,INREGS(1),OUTREGS(1))

      END

