'=========================================================================== ' Subject: RAM IN QBASIC 1: MEMINFO Date: 01-04-97 (00:00) ' Author: Rick Elbers Code: QB, QBasic, PDS ' Origin: t030611@tip.nl Packet: MEMORY.ABC '=========================================================================== DECLARE SUB xms.version (ES%, BX%) DECLARE FUNCTION EMS.FREE$ () DECLARE FUNCTION EMS.DETECT% () DECLARE FUNCTION COPYVID13$ () DECLARE FUNCTION BIOSXMS.DETECT% () DECLARE SUB XMS.ENTRIE (ES%, BX%) DECLARE FUNCTION INT2STR$ (SWORD%) DECLARE FUNCTION XMM.DETECT% () DECLARE FUNCTION XMS.FREE$ (ES%, BX%) DECLARE SUB DEMO () DECLARE FUNCTION LOW.FREE% () DECLARE FUNCTION EMS.VERSION% () 'Rick Elbers, januari 1997 'This program will give an introduction on memory issues as viewed from 'inside QBASIC intrepreter. The demo is nothing more then informing 'you about what we have available for low memory, expanded and 'extended memory management. 'Some other contribution will move on to the use of this dataspaces in 'some meaningful manner. 'NOTE: 'The XMS/EMS version numbers are not trivial here, like in a lot of other 'cases, since both the xms and ems specifications have been changing 'a lot ! DEMO FUNCTION BIOSXMS.DETECT% '------------------------------------------------------ 'THIS FUNCTION RETURNS XMS MEMORY BLOCKS OF 1KB 'FOR 286 AND 386 WITHOUT XMS MANAGER INSTALLED 'STACKPASSING :AX% 'IN: 'OUT :AX%--NR OF 1 KB EXTENDED MEMBLOCKS 'ERRORRETURN :AX%= 0 THEN FUNCTION NOT SUPPORTED OR XMS ' HANDLER INSTALLED '------------------------------------------------------- asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&H50) 'PUSH AX asm$ = asm$ + CHR$(&HB4) + CHR$(&H88) 'MOV AH,88 asm$ = asm$ + CHR$(&HCD) + CHR$(&H15) 'INT 15 asm$ = asm$ + CHR$(&H72) + CHR$(&H5) 'JC 5 asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'MOV [BX],AX asm$ = asm$ + CHR$(&H58) 'POP AX asm$ = asm$ + CHR$(&H5D) 'POP BP asm$ = asm$ + CHR$(&HCA) + CHR$(&H2) + CHR$(&H0) 'RETF 2 '________________________________________ Codeoff% = SADD(asm$) DEF SEG = VARSEG(asm$) CALL ABSOLUTE(ax%, Codeoff%) '________________________________________ DEF SEG BIOSXMS.DETECT% = ax% END FUNCTION FUNCTION COPYVID13$ '--------------------------------------------- 'THIS FUNCTION EMULATES PCOPY FOR LONG STRINGS 'THAT YOU WANT TO COPY IN THE TEXTSCREEN 'AND GUESS WHAT: ITS A LOT FASTER. '--------------------------------------------- 'STACKPASSING: ES%,DI% ' 'MOV BX,[BP+06] 'MOV ES,BX 'ES POINTS TO EMSVIDEOBUFFER 'MOV AX,A000 'MOV DS,AX 'DS POINTS TO VIDEOSEGMENT 'XOR DI,DI 'DI POINTS TO BEGIN OF EMSVIDEOBUFFER 'XOR SI,SI 'SI POINTS TO BEGIN OF VIDEOSEGMENT FOR GRAPHICS SCREEN 'MOV CX,&H7D1 'CX=32001(32000 WORDS TO COPIE) 'CLD 'LETS GO FORWARD! 'REPNZ MOVSW 'COPIE WORDS FROM DS:SI TO ES:DI UNTIL CX=0 '----------------------------------- 'PUSHA asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&H1E) 'PUSH DS asm$ = asm$ + CHR$(&H6) 'PUSH ES asm$ = asm$ + CHR$(&H56) 'PUSH SI asm$ = asm$ + CHR$(&H57) 'PUSH DI asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6)'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&H3F) 'MOV DI,[BX] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8)'MOV BX,[BP+08] asm$ = asm$ + CHR$(&H8E) + CHR$(&H7) 'MOV ES,[BX] asm$ = asm$ + CHR$(&HB8) + CHR$(&H0) + CHR$(&HA0)'MOV AX,&HA000 asm$ = asm$ + CHR$(&H8E) + CHR$(&HD8) 'MOV DS,AX asm$ = asm$ + CHR$(&H31) + CHR$(&HF6) 'XOR SI,SI asm$ = asm$ + CHR$(&HB9) + CHR$(&H1) + CHR$(&H7D)'MOV CX,32001 asm$ = asm$ + CHR$(&HFC) 'CLD asm$ = asm$ + CHR$(&HF2) + CHR$(&HA5) 'REPNZ MOVSW 'POPA asm$ = asm$ + CHR$(&H5F) 'POP DI asm$ = asm$ + CHR$(&H5E) 'POP SI asm$ = asm$ + CHR$(&H7) 'POP ES asm$ = asm$ + CHR$(&H1F) 'POP DS asm$ = asm$ + CHR$(&H5D) 'POP BP 'RETF asm$ = asm$ + CHR$(&HCA) + CHR$(&H4) + CHR$(&H0) 'RETF 4 COPYVID13$ = asm$ END FUNCTION SUB DEMO CLS PRINT SPACE$(17) + "MEMORY INFO IN QBASIC" PRINT STRING$(60, "_"): COLOR 0, 7: PRINT "LOW (CONVENTIONAL) MEMORY INFORMATION": COLOR 7, 0: PRINT A% = LOW.FREE% IF A% THEN PRINT "LOW MEMORY FREE IN PARA'S( BYTES) :"; : COLOR 0, 7: PRINT " "; HEX$(A%); " ("; 16& * A%; ")": COLOR 7, 0 PRINT STRING$(60, "_"): COLOR 0, 7: PRINT "EXTENDED MEMORY INFORMATION": COLOR 7, 0: PRINT 'XMS ? IF XMM.DETECT THEN PRINT "XMM "; : COLOR 0, 7: PRINT "DETECTED" ELSE PRINT "TOTAL XMS AVAILABLE FOR BIOS :"; : COLOR 0, 7: PRINT HEX$(BIOSXMS.DETECT%) COLOR 7, 0 XMS.ENTRIE ES%, BX% PRINT "DRIVER ENTRIE SEG" + SPACE$(21) + ":"; : COLOR 0, 7: PRINT " "; HEX$(ES%): COLOR 7, 0 PRINT "DRIVER ENTRIE OFF" + SPACE$(21) + ":"; : COLOR 0, 7: PRINT " "; HEX$(BX%): COLOR 7, 0 SEGDR% = ES%: OFFDR% = BX% xms.version ES%, BX% PRINT "XMS VERSION" + SPACE$(27); ":"; COLOR 0, 7: PRINT " "; HEX$((ES% AND &HFF00) \ 256); "."; HEX$(ES% AND &HFF) COLOR 7, 0 IF BX% THEN PRINT "HMA "; : COLOR 0, 7: PRINT "EXISTS": COLOR 7, 0 ELSE PRINT "HMA"; : COLOR .7: PRINT "NOT available "; "" 'LET US INITIALIZE A FEW: '------------------------ STRINGSEG% = VARSEG(ALLOC$): DEF SEG = STRINGSEG%: FREE$ = XMS.FREE$(SEGDR%, OFFDR%) '-------------------------------------------------------------------------- 'FREE MEMORY ? '-------------- Codeoff% = SADD(FREE$): CALL ABSOLUTE(ax%, dx%, Codeoff%) PRINT "TOTAL XMS IN KB/ BYTES" + SPACE$(16) + ":"; : COLOR 0, 7: PRINT dx%; "("; dx% * &H400&; ")" COLOR 7, 0 PRINT "FREE XMS IN KB/ BYTES" + SPACE$(16) + ":"; : COLOR 0, 7: PRINT ax%; "("; ax% * &H400&; ")" COLOR 7, 0 'EMS ? PRINT STRING$(60, "_"): COLOR 0, 7: PRINT "EXPANDED MEMORY INFORMATION": COLOR 7, 0: PRINT 'LETS DO SOME INITIALIZING FREE$ = EMS.FREE$: '---------------------------------------------------------------------- '1ST LETS DETERMINE IF EMS IS AVAILABLE: DEF SEG = STRINGSEG% PRINT "EMS "; : COLOR 0, 7: A% = EMS.DETECT% IF A% THEN PRINT "NOT INSTALLED, ERROR "; A%; " DETECTED": EXIT SUB: ELSE PRINT "INSTALLED" COLOR 7, 0 B% = EMS.VERSION% IF B% AND &HFF00 THEN PRINT "ERROR GETTING VERSION :"; B% ELSE PRINT "EMS VERSION" + SPACE$(27) + ":"; : COLOR 0, 7: PRINT " "; HEX$((B% AND &HF0) \ &HF); "."; HEX$(B% AND &HF) COLOR 7, 0 'SECOND LET US DETERMINE THE AMOUNT OF AVAILABLE EMS OFFCODE% = SADD(FREE$): CALL ABSOLUTE(BX%, dx%, OFFCODE%) IF dx% THEN PRINT "AVAILABLE EMS PAGES(16 KB)/BYTES :"; : COLOR 0, 7: PRINT dx%; "("; dx% * 16 * 1024&; ")": COLOR 7, 0: PRINT "FREE EMS PAGES(16 KB)/BYTES :"; : COLOR 0, 7: PRINT BX%; "("; BX% * 16 * 1024&; ")": ELSE PRINT "ERROR IN EMS SOFTWARE "; BX%: EXIT SUB COLOR 7, 0: PRINT STRING$(60, "_"): PRINT : PRINT "good bye" END SUB '**************** EMSSTATUS%() ****************** '*** RETURNS WHETHER EMS IS AVAILABLE. -1 IS *** '*** RETURNED IF IT IS AVAILABLE, 0 OTHERWISE *** 'ORIGINAL:J. LEGER 'IN: 'OUT: AX 0 SUCSES ' AX ELSE ERROR IN AH '************************************************ FUNCTION EMS.DETECT% asm$ = "" asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&HB4) + CHR$(&H40) 'MOV AH,40 asm$ = asm$ + CHR$(&HCD) + CHR$(&H67) 'INT 67 asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6)'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H88) + CHR$(&H27) 'MOV [BX],AH asm$ = asm$ + CHR$(&H5D) 'POP BP asm$ = asm$ + CHR$(&HCB) 'RETF DEF SEG = VARSEG(asm$) CALL ABSOLUTE(EMS%, SADD(asm$)) DEF SEG EMS.DETECT% = EMS% END FUNCTION FUNCTION EMS.FREE$ '---------------------------------------- 'THIS FUNCTION RETURNS TOTAL EMS MEMORY 'AND FREE EMS MEMORY 'STACKPASSING: BX%,DX% 'IN : 'OUT : DX% 0 ERROR ' : ELSE TOTAL EMS ' : BX% ERRORCODE/ FREE EMS '---------------------------------------- asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&H50) 'PUSH AX asm$ = asm$ + CHR$(&H52) 'PUSH DX asm$ = asm$ + CHR$(&HB4) + CHR$(&H42) 'MOV AH,42 asm$ = asm$ + CHR$(&HCD) + CHR$(&H67) 'INT 67 GET PAGE COUNT asm$ = asm$ + CHR$(&H8) + CHR$(&HE4) 'OR AH,AH asm$ = asm$ + CHR$(&H74) + CHR$(&H4) 'JZ+4 NO ERROR asm$ = asm$ + CHR$(&H31) + CHR$(&HD2) 'IF ERROR XOR DX,DX DX=0 asm$ = asm$ + CHR$(&H89) + CHR$(&HC3) 'IF ERROR MOV BX,AX BX=ERRORCODE asm$ = asm$ + CHR$(&H89) + CHR$(&HD8) 'MOV AX,BX TEMP NEED BX asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H89) + CHR$(&H17) 'MOV [BX],DX IN DX% 0 OR TOTAL EMS asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'MOV BX,[BP+08] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'MOV [BX],AX IN BX% ERRORCODE OR EMS FREE asm$ = asm$ + CHR$(&H5A) 'POP DX asm$ = asm$ + CHR$(&H58) 'POP AX asm$ = asm$ + CHR$(&H5D) 'POP BP asm$ = asm$ + CHR$(&HCA) + CHR$(&H4) + CHR$(&H0) 'RETF 4 '________________________________________ EMS.FREE$ = asm$ END FUNCTION FUNCTION EMS.VERSION% '--------------------------------------- 'THIS FUNCTION RETURNS THE EMS VERSION 'STACKPASSING: AX% 'IN : 'OUT : AH 0 SUCSES ' ELSE ERRORCODE ' AL VERSION 'THE VERSION IS IMPORTANT TO CHECK SINCE 'ALL ELABORATE EMS FUNCTIONS ARE MOSTLY '---------------------------------------- asm$ = "" asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&HB4) + CHR$(&H46) 'MOV AH,46 asm$ = asm$ + CHR$(&HCD) + CHR$(&H67) 'INT 67 asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'MOV [BX],AX asm$ = asm$ + CHR$(&H5D) 'POP BP asm$ = asm$ + CHR$(&HCA) + CHR$(&H2) + CHR$(&H0) 'RETF 2 '________________________________________ Codeoff% = SADD(asm$) DEF SEG = VARSEG(asm$) CALL ABSOLUTE(ax%, Codeoff%) '________________________________________ DEF SEG EMS.VERSION% = ax% END FUNCTION FUNCTION INT2STR$ (SWORD%) 'THIS FUNCTION IS TRANSLATING SWORD INTEGERS INTO A STRING. ITS ONLY USE 'IS WHEN YOU STILL USE ASM$ FOR ASSEMBLER FUNCTIONS( LIKE I DO). IN THAT 'CASE YOU CAN MAKE YOUR INTEGER VALUES USABLE .. 'THIS FUNCTION SIMPLY TRANSLATES THE HEXA BYTES 'INTO STRINGBYTES AS IS. '---------------------------------------------------- DEF SEG = VARSEG(SWORD%) PTR% = VARPTR(SWORD%) INT2STR$ = CHR$(PEEK(PTR%)) + CHR$(PEEK(PTR% + 1)) DEF SEG END FUNCTION FUNCTION LOW.FREE% '------------------------------------------------------------------- 'THIS FUNCTION ALLOCATES LOWER MEMORY 'STACK PASSING :BX% ' 'IN :BX%= FFFF WHOLE MB REQUESTED ' 'OUT :BX%= 0 OR AVAILABLE MEMORY '--------------------------------------------------------------------- asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&H50) 'PUSH AX asm$ = asm$ + CHR$(&H53) 'PUSH BX asm$ = asm$ + CHR$(&HBB) + CHR$(&HFF) + CHR$(&HFF) 'MOV BX,FFFF THE WHOLE MB asm$ = asm$ + CHR$(&HB4) + CHR$(&H48) 'MOV AH,48 asm$ = asm$ + CHR$(&HCD) + CHR$(&H21) 'INT 21 asm$ = asm$ + CHR$(&H72) + CHR$(&H2) 'JC +2 asm$ = asm$ + CHR$(&H31) + CHR$(&HDB) 'XOR BX,BX IF NO ERROR asm$ = asm$ + CHR$(&H89) + CHR$(&HD8) 'MOV AX,BX asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'MOV [BX],AX 0=NO ERROR asm$ = asm$ + CHR$(&H5B) 'POP BX asm$ = asm$ + CHR$(&H58) 'POP AX asm$ = asm$ + CHR$(&H5D) 'POP BP asm$ = asm$ + CHR$(&HCA) + CHR$(&H2) + CHR$(&H0) 'RETF 2 '________________________________________ Codeoff% = SADD(asm$) DEF SEG = VARSEG(asm$) CALL ABSOLUTE(BX%, Codeoff%) '________________________________________ DEF SEG LOW.FREE% = BX% END FUNCTION FUNCTION XMM.DETECT% '------------------------------------------------------------ 'THIS FUNCTION RETURNS IF XMS MEMORY MANAGER INSTALLED 'STACKPASSING :AX% 'IN: 'OUT :AX% = &H0080 XMM INSTALLED 'ERRORRETURN :AX% <> &H0080 XMM NOT INSTALLED( QBASIC:AX%=0) '------------------------------------------------------------ asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&H50) 'PUSH AX asm$ = asm$ + CHR$(&HB8) + CHR$(&H0) + CHR$(&H43) 'MOV AX,4300 asm$ = asm$ + CHR$(&HCD) + CHR$(&H2F) 'INT 2F asm$ = asm$ + CHR$(&H3C) + CHR$(&H80) 'CMP AL,80 asm$ = asm$ + CHR$(&H74) + CHR$(&H2) 'JZ 2 asm$ = asm$ + CHR$(&H31) + CHR$(&HC0) 'XOR AX,AX asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'MOV [BX],AX asm$ = asm$ + CHR$(&H58) 'POP AX asm$ = asm$ + CHR$(&H5D) 'POP BP asm$ = asm$ + CHR$(&HCA) + CHR$(&H2) + CHR$(&H0) 'RETF 2 '________________________________________ Codeoff% = SADD(asm$) DEF SEG = VARSEG(asm$) CALL ABSOLUTE(ax%, Codeoff%) '________________________________________ DEF SEG XMM.DETECT% = ax% END FUNCTION SUB XMS.ENTRIE (ES%, BX%) '-------------------------------------------------- 'THIS FUNCTION DETECTS DRIVER ENTRIE, 'THE FREE XMS SIZE AND TOTAL XMS SIZE 'STACK PASSING : ES%,BX% 'IN : 'OUT : ES%= DRIVER ENTRIE SEGMENT ' BX%= DRIVER ENTRIE OFFSET '-------------------------------------------------- asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&H50) 'PUSH AX asm$ = asm$ + CHR$(&H53) 'PUSH BX asm$ = asm$ + CHR$(&H6) 'PUSH ES asm$ = asm$ + CHR$(&HB8) + CHR$(&H10) + CHR$(&H43) 'MOV AX,4310 asm$ = asm$ + CHR$(&HCD) + CHR$(&H2F) 'INT 2F GET DRIVER ENTRIE asm$ = asm$ + CHR$(&H89) + CHR$(&HD8) 'MOV AX,BX (NEED TO STORE BX) asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'MOV BX,[BP+08] asm$ = asm$ + CHR$(&H8C) + CHR$(&H7) 'MOV [BX],ES SEG DRIVER asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'MOV [BX],AX OFF DRIVER asm$ = asm$ + CHR$(&H7) 'POP ES asm$ = asm$ + CHR$(&H5B) 'POP BX asm$ = asm$ + CHR$(&H58) 'POP AX asm$ = asm$ + CHR$(&H5D) 'POP BP asm$ = asm$ + CHR$(&HCA) + CHR$(&H4) + CHR$(&H0) 'RETF 4 '________________________________________ Codeoff% = SADD(asm$) DEF SEG = VARSEG(asm$) CALL ABSOLUTE(ES%, BX%, Codeoff%) '________________________________________ DEF SEG END SUB FUNCTION XMS.FREE$ (ES%, BX%) '---------------------------------------------------------------- 'THIS FUNCTION RETURNS IF FREE AND TOTAL XMS MEMORY 'STACKPASSING :AX%,DX% 'IN: :ES[BX] DRIVER ENTRIE 'OUT :AX% = FREE XMS ' DX% = TOTAL XMS '---------------------------------------------------------------- 'INIT '----- ES$ = INT2STR$(ES%): BX$ = INT2STR$(BX%) '---------------------------------------------------------------- asm$ = "" asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&H50) 'PUSH AX asm$ = asm$ + CHR$(&H53) 'PUSH BX asm$ = asm$ + CHR$(&H52) 'PUSH DX asm$ = asm$ + CHR$(&HB4) + CHR$(&H8) 'MOV AH,0800 QUERY FREE XMS asm$ = asm$ + CHR$(&H9A) + BX$ + ES$ 'CALL DRIVER asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H89) + CHR$(&H17) 'MOV [BX],DX asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'MOV BX,[BP+08] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'MOV [BX],AX asm$ = asm$ + CHR$(&H5A) 'POP DX asm$ = asm$ + CHR$(&H5B) 'POP BX asm$ = asm$ + CHR$(&H58) 'POP AX asm$ = asm$ + CHR$(&H5D) 'POP BP asm$ = asm$ + CHR$(&HCA) + CHR$(&H4) + CHR$(&H0) 'RETF 4 XMS.FREE$ = asm$ END FUNCTION SUB xms.version (ES%, BX%) '---------------------------------------------------------------- 'THIS FUNCTION RETURNS THE XMSVERSION and HMA AVAILABILITY 'STACKPASSING :AX%,DX% 'IN: :ES[BX] DRIVER ENTRIE 'OUT :AX% = XMS VERSION ' DX% = 0 HMA unavailable ' HMA exists 'QBASIC :ES% = XMS version ' BX% = HMA exists '---------------------------------------------------------------- 'INIT '----- ES$ = INT2STR$(ES%): BX$ = INT2STR$(BX%) '---------------------------------------------------------------- asm$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp asm$ = asm$ + CHR$(&HB4) + CHR$(&H0) 'mov ah,0 asm$ = asm$ + CHR$(&H9A) + BX$ + ES$ 'CALL DRIVER asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+06] asm$ = asm$ + CHR$(&H89) + CHR$(&H17) 'mov [bx],dx asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H4) + CHR$(&H0) 'retf 4 '________________________________________ Codeoff% = SADD(asm$) DEF SEG = VARSEG(asm$) CALL ABSOLUTE(ax%, dx%, Codeoff%) '________________________________________ DEF SEG ES% = ax%: BX% = dx% END SUB