QBasic / QB64 Discussion Forum      Other Subforums, Links and Downloads
 Return to Index  

EMS routines using CALL ABSOLUTE routines

March 9 2002 at 1:13 PM
  (no login)

FAQ007 = How do you write/access ASM code in QBasic?

This program (copy and save as BAS file) contain a set of routines used for EMS support which you can add to your RPG game or other QB program.

The routines are briefly explained in the source code, but I'll give you some more explaination here.

Most important functions:

SUB AsmPrepare
- This function reads and prepares all assembly routines in the data statements
- Data statements begin with a number which must be unique for every routine. All Functions that use CALL ABSOLUTE use this number to identify their own assembly routine. A number of '-1' tells AsmPrepare there are no more routines.

FUNCTION EmsInstalled
>>> Checks if EMS is supported.
- Returns zero if EMS is supported and ready to use
- Returns nonzero if there is a problem

FUNCTION EmsPageFrameSegment (PageFrameSeg)
- Fills PageFrameSeg with the current 'EMS Page Frame Segment'
>>> This Segment must be read once. The Segment is used to copy data to or from the EMS.
- Returns nonzero if there is a problem

FUNCTION EmsAllocate (NumPages, Handle)
- Creates a EMS handle. The handle is returned in Handle
- It Allocates NumPages EMS pages and assignes it to the handle (A page is 16384 bytes)
>>> This Handle must be kept for use with other EMS function. A program can use multiple pieces of EMS by using multiple handles. A program can, by example, store graphics in one EMS handle and an array of variables in another.
- Returns nonzero if there is a problem

FUNCTION EmsRelease (Handle)
- Releases EMS memory assighed to the Handle and destroys the Handle
>>> This function must be called for every handle you have created with FUNCTION EmsAllocate.
- Returns nonzero if there is a problem

FUNCTION EmsMap (Handle, Page, NumPages)
>>> This function assignes up to 4 EMS pages to physical pages in the base memory at the EMS Page Frame Segment. (see FUNCTION EmsPageFrameSegment)
- Handle identifies which EMS handle is used to map memory to.
- Page must contain the first page of the handle which is mapped to the base memory.
>>> After the call, the bytes in this page are accessible from EmsPageFrameSegment:0000 to EmsPageFrameSegment:3FFF
- NumPages must contain the number of pages that are sequentionally assigned to the base memory.
>>> Data in the pages after the selected page are accessible from from EmsPageFrameSegment:4000 to EmsPageFrameSegment:7FFF, EmsPageFrameSegment:8000 to EmsPageFrameSegment:BFFF and EmsPageFrameSegment:C000 to EmsPageFrameSegment:FFFF. Assigning multiple pages creates a continuous range consisting of the seperate ranges.
- Returns nonzero if there is a problem

Less important functions:

FUNCTION EmsPages (TotalPages, AvailablePages)
- Fills TotalPages with the number of free EMS pages
- Fills AvailablePages with the number of available EMS pages
>>> AvailablePages will often clip at 1024. If in this case if AvailablePages is 1024 it means there are more free pages.
- Returns nonzero if there is a problem

FUNCTION EmsNumHandles (NumHandles)
- Fills NumHandles with the current number of EMS handles in use by QB and your program (or the peogram only if it's compiled).
- Returns nonzero if there is a problem

FUNCTION EmsNumPages (Handle, NumPages)
- Fills NumPages with the number of pages that are assigned to the Handle using EmsAllocate
- Returns nonzero if there is a problem

DEFINT A-Z

DIM SHARED AsmString(9) AS STRING * 50, AsmPointer(9), AsmSegment(9)

AsmPrepare

'
'Your code here
'

END

MemCopyAsmData:
DATA 0,1E8B760C8B460A8EC08B7E088B4E068B460E8ED8F3A41F
EmsInstalledAsmData:
DATA 1,B440CD67B0008B7E068905
EmsPageFrameSegmentAsmData:
DATA 2,B441CD67B0008B7E0689058B7E08891D
EmsPagesAsmData:
DATA 3,B442CD67B0008B7E0689058B7E0A89158B7E08891D
EmsAllocateAsmData:
DATA 4,8B5E0AB443CD67B0008B7E0689058B7E088915
EmsReleaseAsmData:
DATA 5,B4458B5606CD67
EmsNumPagesAsmData:
DATA 6,8B560AB44CCD67B0008B7E0689058B7E08891D
EmsMapAsmData:
DATA 7,8B560C8B5E0A8B4E0830C0B444CD6780FC007507FEC043E2F2B00030C08B7E068905
EmsNumHandlesAsmData:
DATA 8,B44BCD6730C08B7E0689058B7E08891D
DATA -1

SUB AsmPrepare STATIC
  DO
    READ Number
    IF Number = -1 THEN EXIT SUB

    AsmSegment(Number) = VARSEG(AsmString(Number))
    AsmPointer(Number) = VARPTR(AsmString(Number))

    '55   PUSH    BP
    '89E5 MOV     BP,SP
    '...user routine
    '5D   POP     BP
    'CB   RETF

    READ AsmHex$
    AsmHex$ = "5589E5" + AsmHex$ + "5DCB"

    asmbytes = LEN(AsmHex$) \ 2

    DEF SEG = AsmSegment(Number)

    FOR a = 0 TO asmbytes - 1
      POKE AsmPointer(Number) + a, VAL("&h" + MID$(AsmHex$, a * 2 + 1, 2))
    NEXT
  LOOP
END SUB

'Create a handle and allocate EMS pages to the handle
'
'MOV     BX,[BP+0A] ;NumPages
'MOV     AH,43
'INT     67
'MOV     AL,00
'MOV     DI,[BP+06] ;Status
'MOV     [DI],AX
'MOV     DI,[BP+08] ;Handle
'MOV     [DI],DX
'
'IN:  WORD number of logical pages to allocate
'OUT: WORD handle if successfull
'
FUNCTION EmsAllocate (NumPages, Handle) STATIC
  RESTORE EmsAllocateAsmData
  READ Number

  DEF SEG = AsmSegment(Number)
  CALL Absolute(BYVAL NumPages, Handle, Status, AsmPointer(Number))

  EmsAllocate = Status
END FUNCTION

'Get EMS manager status
'
'MOV     AH,40
'INT     67
'MOV     AL,00
'MOV     BX,[BP+06] ;Status
'MOV     [BX],AX
'
FUNCTION EmsInstalled STATIC
  RESTORE EmsInstalledAsmData
  READ Number

  DEF SEG = AsmSegment(Number)
  CALL Absolute(Status, AsmPointer(Number))

  EmsInstalled = Status
END FUNCTION

'Assign up to 4 EMS pages to the EMS page frame segment.
'
'MOV     DX,[BP+0C] ;Handle
'MOV     BX,[BP+0A] ;Page
'MOV     CX,[BP+08] ;NumPages
'XOR     AL,AL
';000B
'MOV     AH,44
'INT     67
'CMP     AH,00
'JNZ     001B
'INC     AL
'INC     BX
'LOOP    000B
'MOV     AL,00
';001B
'MOV     DI,[BP+06] ;Status
'MOV     [DI],AX
'
'IN:  WORD handle
'     WORD logical page number or FFFFh to unmap (QEMM)
'     WORD number of physical pages (1-4)
'
FUNCTION EmsMap (Handle, Page, NumPages) STATIC
  RESTORE EmsMapAsmData
  READ Number

  a = NumPages
  IF a > 4 THEN a = 4
  IF a < 1 THEN a = 1

  DEF SEG = AsmSegment(Number)
  CALL Absolute(BYVAL Handle, BYVAL Page, BYVAL a, Status, AsmPointer(Number))
  EmsMap = Status
END FUNCTION

'Get number of handles in use of the program
'
'MOV     AH,4B
'INT     67
'MOV     DI,[BP+06] ;Status
'MOV     [DI],AX
'MOV     DI,[BP+08] ;NumHandles
'MOV     [DI],BX
'
'OUT: WORD number of handles
'
FUNCTION EmsNumHandles (NumHandles) STATIC
  RESTORE EmsNumHandlesAsmData
  READ Number

  DEF SEG = AsmSegment(Number)
  CALL Absolute(NumHandles, Status, AsmPointer(Number))

  EmsNumHandles = Status
END FUNCTION

'Get pages owned by a handle
'
'MOV     DX,[BP+0A]
'MOV     AH,4C
'INT     67
'MOV     AL,00
'MOV     DI,[BP+06]
'MOV     [DI],AX
'MOV     DI,[BP+08]
'MOV     [DI],BX
'
'IN:  WORD handle
'OUT: WORD number of logical pages
'
FUNCTION EmsNumPages (Handle, NumPages) STATIC
  RESTORE EmsNumPagesAsmData
  READ Number

  DEF SEG = AsmSegment(Number)
  CALL Absolute(BYVAL Handle, NumPages, Status, AsmPointer(Number))

  EmsNumPages = Status
END FUNCTION

'Get the page frame segment
'
'MOV     AH,41
'INT     67
'MOV     AL,00
'MOV     DI,[BP+06] ;Status
'MOV     [DI],AX
'MOV     DI,[BP+08] ;PageFrameSeg
'MOV     [DI],BX
'
'OUT: WORD segment of page frame
'
FUNCTION EmsPageFrameSegment (PageFrameSeg) STATIC
  RESTORE EmsPageFrameSegmentAsmData
  READ Number

  DEF SEG = AsmSegment(Number)
  CALL Absolute(PageFrameSeg, Status, AsmPointer(Number))

  EmsPageFrameSegment = Status
END FUNCTION

'Get the total and free number of EMS pages
'
'MOV     AH,42
'INT     67
'MOV     AL,00
'MOV     DI,[BP+06] ;Status
'MOV     [DI],AX
'MOV     DI,[BP+08] ;AvailablePages
'MOV     [DI],BX
'MOV     DI,[BP+0A] ;TotalPages
'MOV     [DI],DX
'
'OUT: WORD number of unallocated pages
'     WORD total number of pages
'
FUNCTION EmsPages (TotalPages, AvailablePages) STATIC
  RESTORE EmsPagesAsmData
  READ Number

  DEF SEG = AsmSegment(Number)
  CALL Absolute(TotalPages, AvailablePages, Status, AsmPointer(Number))

  EmsPages = Status
END FUNCTION

'Discard a handle and Release memory
'
'MOV     AH,45
'MOV     DX,[BP+06] ;Handle
'INT     67
'
'IN:  WORD handle
'
SUB EmsRelease (Handle) STATIC
  RESTORE EmsReleaseAsmData
  READ Number

  DEF SEG = AsmSegment(Number)
  CALL Absolute(BYVAL Handle, AsmPointer(Number))
END SUB

'Copy in memory
'
'PUSH    DS
'MOV     SI,[BP+0C] ;SrcPtr
'MOV     AX,[BP+0A] ;DstSeg
'MOV     ES,AX
'MOV     DI,[BP+08] ;DstPtr
'MOV     CX,[BP+06] ;NumBytes
'MOV     AX,[BP+0E] ;SrcSeg
'MOV     DS,AX
'REPZ
'MOVSB
'POP     DS
'
'IN:  WORD Source segment
'     WORD Source pointer
'     WORD Destination segment
'     WORD Destination pointer
'     WORD Number of bytes to copy
'
SUB MemCopy (SrcSeg, SrcPtr, DstSeg, DstPtr, NumBytes&) STATIC
  RESTORE MemCopyAsmData
  READ Number

  IF NumBytes& > 32767 THEN
    a = NumBytes& - 65536
  ELSE
    a = NumBytes&
  END IF

  DEF SEG = AsmSegment(Number)
  CALL Absolute(BYVAL SrcSeg, BYVAL SrcPtr, BYVAL DstSeg, BYVAL DstPtr, BYVAL a, AsmPointer(Number))
END SUB




    
This message has been edited by iorr5t on Oct 30, 2003 12:40 PM


 
 Respond to this message   
Responses