'=========================================================================== ' Subject: RAM IN QBASIC 2: LOWMEM Date: 01-16-97 (23:25) ' Author: Rick Elbers Code: QB, QBasic, PDS ' Origin: t030611@tip.nl Packet: MEMORY.ABC '=========================================================================== DECLARE FUNCTION USWORD% (SWORD&) : DECLARE FUNCTION getSWORD& (USWORD%) DECLARE FUNCTION low.dealloc$ () : DECLARE FUNCTION low.alloc$ () DECLARE SUB demo2 () : DECLARE SUB demo3 () : DECLARE SUB demo4 () : DECLARE FUNCTION low.getstring$ () : DECLARE FUNCTION low.movestring$ () DECLARE FUNCTION low.getsubarray$ () : DECLARE FUNCTION low.setelement$ () DECLARE FUNCTION low.getelement$ () : DECLARE FUNCTION COPYVID13$ () DECLARE FUNCTION low.movewords$ () : DECLARE SUB demo () DECLARE FUNCTION low.free$ () : DECLARE SUB demo1 (free%) CLS demo '-------------------------------- 'DOSMEMORY ACCESS ....AND......? '-------------------------------- 'Oke let us go for the real stuff now, oke. 'What you should in fact do is unlike the demos initialize the space you 'need and leave allocation/ deallocation until the end of the program 'SAY you need 100Kb ? 'Initialization '--------------- moveW$ = low.movewords$: dealloc$ = low.dealloc$: alloc$ = low.alloc$: stringseg% = VARSEG(alloc$): DEF SEG = stringseg%: offcode% = SADD(alloc$) bx% = 100 * (1024& \ 16): CALL absolute(ax%, bx%, offcode%): DEF SEG IF ax% = 0 THEN dosseg% = bx%: nrDOSbytes% = 100 * (1024& \ 16) ELSE END 'errorcondition 'So at this time we know we have 100KB access if dosseg%> 0 '---------------------------------------------------------------------------- 'USEFUL 1: PROGRAMS WITH 20 FILES OPEN LIKE SOME ACCOUNTING PROGRAMS ? 'Lets just copy them on and offscreen( providing that 5000 bytes is enough) 'Instead of having open so many files or opening/closing them each time '---------------------------------------------------------------------------- '-------------------------------------------------------------- 'Print 20 screens for BASIC and let us save 10 screens to DOS. '-------------------------------------------------------------- DEF SEG = &H40: help% = PEEK(&H10) AND &H30: IF help% = &H30 THEN videobase% = &HB000 ELSE videobase% = &HB800 DEF SEG = stringseg% FOR i% = 0 TO 9: LOCATE 1, 1: PRINT STRING$(3999, CHR$(48 + i%)) codeoff% = SADD(moveW$): es% = dosseg% CALL absolute(videobase%, 0, es%, USWORD%(4000& * i%), 4000, codeoff%) NEXT: DEF SEG = &H40: POKE &H1C, PEEK(&H1A): DEF SEG = stringseg% CLS : PRINT "Want some back ? Give a number that i will MOD 9 "; : INPUT ; i% '---------------------------------------------- 'Let us get one of them back '---------------------------------------------- codeoff% = SADD(moveW$): es% = dosseg%: i% = i% MOD 9 CALL absolute(es%, USWORD%(4000& * i%), videobase%, 0, 4000, codeoff%) VIEW PRINT 23 TO 25: CLS 2 PRINT "Impressive and fast ? Wait until you see what you can do with 7MB EMS/XMS !" PRINT "press a key for next ": SLEEP '--------------------------------------------------------------------------- 'USEFUL 2: PROGRAMS THAT NEED 100 KB EXTRA DATASPACE ? '--------------------------------------------------------------------------- 'Demo 2,3,4 should have given you the taste... 'Further uses: 'Read really big files( bigger then 10 KB) into DOSMEM and copy parts of 'them to BASIC. Faster then reading bit/bit from the file. Even more fast is 'to read the file directly to the segment, but for that possibility you need 'some assembly routine to read a file. '--------------------------------------------------------------------------- 'USEFUL 3: PROGRAMS THAT WANT MORE PAGES IN GRAPHICS MODE '--------------------------------------------------------------------------- VIEW PRINT: CLS : PRINT "Be sure that you are in PLAIN DOS before executing this one!" PRINT "If you are , press a key": SLEEP 'Lets draw some stuff onscreen SCREEN 13 FOR x% = 1 TO 99 CIRCLE (159, 99), x%, x% NEXT x% '--------------------------------------- 'And now let us save the screen to DOS. '--------------------------------------- codeoff% = SADD(moveW$): es% = dosseg% CALL absolute(&HA000, 0, es%, 0, 32000, codeoff%) CLS : PRINT "Want that nice picture back ?": PRINT "press a key" SLEEP '-------------------------------------- 'And getting the screen back '-------------------------------------- codeoff% = SADD(moveW$): es% = dosseg% CALL absolute(es%, 0, &HA000, 0, 32000, codeoff%) 'Deallocating '------------- offcode% = SADD(dealloc$): es% = dosseg%: segm% = es%: codeoff% = SADD(dealloc$): CALL absolute(es%, codeoff%) IF es% THEN PRINT "Error deallocating memory "; es% DEF SEG '---------------------------------------------------------------------------- 'NOTES: '------- '1)There is not a function modify memalloc available here, since i did not ' thought that would have been very useful. It can easily be developed from ' the function low.alloc( only change is: mov ah,4a and that is that) '2)You can only move blocks up to 128 KB around with movewords since i ' did not accounted for bigger moves. When you are going to move blocks ' bigger then 32 KB be sure that you translate to UNSIGNED INTEGERS! ' The reason that i did not accounted for bigger moves is that both the ' EMS and XMS move functions are perfectly suited for bigger moves already '3)For stringmovement the limit is 64 KB. Same reasons '4)I did not have timed any of these functions LOCATE 24, 1: PRINT "Press a key ..sleep.....": SLEEP SCREEN 0: WIDTH 80 LOCATE 19, 1 PRINT "This is the end of the DOS memory demo: if you want to move bigger " PRINT "strings or array's at once you have to use the EMS or XMS move" PRINT "functions in some later article i will adress those functions. " PRINT PRINT "Good bye" PRINT "Rick" END SUB demo CLS demo1 free% IF free% > 64000 \ 16 THEN demo2: demo3 IF free% > 10000 \ 16 THEN demo4 CLS END SUB SUB demo1 (free%) '------------ 'initiating: '------------ dosfree$ = low.free$: alloc$ = low.alloc$: dealloc$ = low.dealloc$ 'Lets first get the free dosmemory after BASIC is done '------------------------------------------------------ DEF SEG = VARSEG(dosfree$): codeoff% = SADD(dosfree$) CALL absolute(bx%, codeoff%) PRINT "DEMO 1 DOS FREE MEMORY AND ALLOCATING DEALLOCATING DOS MEM" PRINT STRING$(80, "_") IF bx% THEN PRINT "Low memory free in para's( bytes) :"; bx%; "("; 16& * bx%; ")" ELSE PRINT "No free DOS memory to demonstrate ..exiting..": END free% = bx% 'Second lets allocate 3 times '----------------------------------------- DIM dealloc%(3) 'save the segments in this array bx% = &HFFF: nralloc$ = HEX$(bx%): codeoff% = SADD(alloc$): CALL absolute(ax%, bx%, codeoff%): dealloc%(0) = bx% IF ax% THEN PRINT "Error allocating memory "; bx%; " Available memory (para's) "; HEX$(ax%) 'deallocate and quit ELSE PRINT "Allocated "; STRING$(4 - LEN(nralloc$), "0") + nralloc$; " para's at segment(hex) : "; HEX$(bx%) END IF bx% = 2: nralloc$ = HEX$(bx%): codeoff% = SADD(alloc$): CALL absolute(ax%, bx%, codeoff%): dealloc%(1) = bx% IF ax% THEN PRINT "Error allocating memory "; bx%; " Available memory (para's) "; HEX$(ax%) ELSE PRINT "Allocated "; STRING$(4 - LEN(nralloc$), "0") + nralloc$; " para's at segment(hex) : "; HEX$(bx%) END IF bx% = 1: nralloc$ = HEX$(bx%): codeoff% = SADD(alloc$): CALL absolute(ax%, bx%, codeoff%): dealloc%(2) = bx% IF ax% THEN PRINT "Error allocating memory "; bx%; " Available memory (para's) "; HEX$(ax%) ELSE PRINT "Allocated "; STRING$(4 - LEN(nralloc$), "0") + nralloc$; " para's at segment(hex) : "; HEX$(bx%) END IF FOR i% = 0 TO 2: es% = dealloc%(i%): segm% = es%: codeoff% = SADD(dealloc$) CALL absolute(es%, codeoff%) IF es% THEN PRINT "Error deallocating memory "; es% ELSE PRINT "Sucses deallocating memory from segment : "; HEX$(segm%) NEXT PRINT PRINT "Press a key for next demo": SLEEP: CLS END SUB SUB demo2 'Initiating: '----------- moveW$ = low.movewords$: alloc$ = low.alloc$: dealloc$ = low.dealloc$ 'DEMO 2 let us move an array '--------------------------- LOCATE 10, 1: PRINT STRING$(80, "_") LOCATE 11, 1: PRINT "DEMO 2: MOVING A 64 KB ARRAY TO DOS AND BACK AGAIN" COLOR 0, 7: LOCATE 12, 1: PRINT "Initializing array in BASIC" COLOR 7, 0: VIEW PRINT 15 TO 22 DIM datas%(32000): FOR i% = 0 TO 32000 - 1: datas%(i%) = i%: PRINT datas%(i%); : NEXT basseg% = VARSEG(datas%(0)): basoff% = VARPTR(datas%(0)) bx% = 64000 \ 16: nralloc$ = HEX$(bx%): codeoff% = SADD(alloc$): CALL absolute(ax%, bx%, codeoff%): dosseg% = bx% VIEW PRINT: LOCATE 1, 1 IF ax% THEN PRINT "Error allocating memory "; bx%; " Available memory (para's) "; HEX$(ax%) 'deallocate and quit ELSE PRINT "Allocated "; STRING$(4 - LEN(nralloc$), "0") + nralloc$; " para's at segment(hex) : "; HEX$(bx%) END IF LOCATE 12, 1: COLOR 0, 7: PRINT "Moved 64 KB array to DOS: BASIC array is free!" codeoff% = SADD(moveW$): es% = dosseg% CALL absolute(basseg%, basoff%, es%, 0, 32000, codeoff%) LOCATE 13, 1: PRINT "64 KB Array given other values in BASIC: " COLOR 7, 0: VIEW PRINT 15 TO 22 FOR i% = 0 TO 32000 - 1: datas%(i%) = -1: PRINT datas%(i%); : NEXT VIEW PRINT COLOR 0, 7: LOCATE 12, 1: PRINT "64 KB Array back from DOS with old values ": COLOR 7, 0 PRINT SPACE$(45) codeoff% = SADD(moveW$) CALL absolute(dosseg%, 0, basseg%, basoff%, 32000, codeoff%) DEF SEG COLOR 7, 0: VIEW PRINT 15 TO 22 FOR i% = 0 TO 32000 - 1: PRINT datas%(i%); : NEXT VIEW PRINT: LOCATE 2, 1 es% = dosseg%: segm% = es%: codeoff% = SADD(dealloc$) CALL absolute(es%, codeoff%) IF es% THEN PRINT "Error deallocating memory "; es% ELSE PRINT "Sucses deallocating memory from segment : "; HEX$(segm%) PRINT : PRINT "Press a key for next demo": SLEEP: CLS END SUB SUB demo3 'Initializing: '--------------- alloc$ = low.alloc$: dealloc$ = low.dealloc$ moveW$ = low.movewords$: setelement$ = low.setelement$: getelement$ = low.getelement$: subarray$ = low.getsubarray$: 'DEMO 3 Let us access array elements in DOS '------------------------------------------ LOCATE 10, 1: PRINT STRING$(80, "_") LOCATE 11, 1: PRINT "DEMO 3: MOVING A 64 KB ARRAY TO DOS AND GETTING ELEMENTS\ SETTING ELEMENTS" COLOR 0, 7: LOCATE 12, 1: PRINT "Initializing array in BASIC" COLOR 7, 0: VIEW PRINT 15 TO 22 DIM datas%(32000): FOR i% = 0 TO 32000 - 1: datas%(i%) = i%: PRINT datas%(i%); : NEXT '----------- 'allocating '----------- basseg% = VARSEG(datas%(0)): basoff% = VARPTR(datas%(0)) bx% = 64000 \ 16: VIEW PRINT: nralloc$ = HEX$(bx%): codeoff% = SADD(alloc$): CALL absolute(ax%, bx%, codeoff%): dosseg% = bx% VIEW PRINT: LOCATE 1, 1 IF ax% THEN PRINT "Error allocating memory "; bx%; " Available memory (para's) "; HEX$(ax%): EXIT SUB ELSE PRINT "Allocated "; STRING$(4 - LEN(nralloc$), "0") + nralloc$; " para's at segment(hex) : "; HEX$(bx%) END IF 'moving the array to DOS '------------------------- LOCATE 12, 1: COLOR 0, 7: PRINT "Moved 64 KB array to DOS: BASIC array is free!" COLOR 7, 0 DEF SEG = VARSEG(moveW$): codeoff% = SADD(moveW$): es% = dosseg% CALL absolute(basseg%, basoff%, es%, 0, 32000, codeoff%) 'Get an element: '-------------- offcode% = SADD(getelement$): es% = dosseg%: nr% = 456'lets get this number CALL absolute(es%, 0, bas%, nr%, offcode%) VIEW PRINT: LOCATE 2, 1: PRINT "The element "; : COLOR 0, 7: PRINT nr%; : COLOR 7, 0: PRINT " has the value of : "; : COLOR 0, 7: PRINT bas% COLOR 7, 0 'Let us change this element oke ? '-------------------------------- offcode% = SADD(setelement$): chgbas% = -1: bas% = chgbas%'let us give it -1 es% = dosseg%: CALL absolute(es%, 0, bas%, nr%, offcode%) PRINT "The element "; : COLOR 0, 7: PRINT nr%; : COLOR 7, 0: PRINT " changing to value : "; : COLOR 0, 7: PRINT chgbas% COLOR 7, 0 'And get it again from DOS '-------------------------- offcode% = SADD(getelement$): es% = dosseg%: nr% = 456'lets get this number CALL absolute(dosseg%, 0, bas%, nr%, offcode%) PRINT "The element "; : COLOR 0, 7: PRINT nr%; : COLOR 7, 0: PRINT " has now the value of : "; : COLOR 0, 7: PRINT bas% COLOR 7, 0 'Is looking good so far, not ? '--------------------------------------------------------------------- 'Let us move on with defining a subarray in BASIC with values from DOS '--------------------------------------------------------------------- PRINT "Getting BASIC subarray "; : COLOR 0, 7: PRINT "[0..9]"; : COLOR 7, 0: PRINT " from DOSarray "; : COLOR 0, 7: PRINT "[455.. 464]" codeoff% = SADD(subarray$): dosoff% = (456 * 2) - 2 'let us get 10 elements offset 456 es% = dosseg% CALL absolute(es%, dosoff%, basseg%, basoff%, 10, codeoff%) COLOR 7, 0: PRINT "The subarray "; : COLOR 0, 7: PRINT "0.. 10"; : COLOR 7, 0: PRINT " has now the values :": COLOR 0, 7: FOR i% = 0 TO 10: PRINT datas%(i%); : NEXT COLOR 7, 0: PRINT : es% = dosseg%: segm% = es%: codeoff% = SADD(dealloc$) CALL absolute(es%, codeoff%) IF es% THEN PRINT "Error deallocating memory "; es% ELSE PRINT "Sucses deallocating memory from segment : "; HEX$(segm%) LOCATE 24, 1: PRINT "Press a key for next demo": SLEEP: CLS END SUB SUB demo4 'Initializing: '-------------- alloc$ = low.alloc$: dealloc$ = low.dealloc$ movestring$ = low.movestring$: getstring$ = low.getstring$: '-------------------------------------------- 'DEMO 4 Let us access string elements in DOS '-------------------------------------------- LOCATE 10, 1: PRINT STRING$(80, "_") LOCATE 11, 1: PRINT "DEMO 4: MOVING AN 10 KB STRING TO DOS AND GETTING\ SETTING PARTS OF IT" COLOR 0, 7: LOCATE 12, 1: PRINT "Initializing string in BASIC" COLOR 7, 0: VIEW PRINT 15 TO 22 'Let us initialize the string STATIC a$: FOR i% = 0 TO 10: a$ = a$ + STRING$(1000, CHR$(65 + i%)): NEXT basseg% = VARSEG(a$): basoff% = SADD(a$) VIEW PRINT 15 TO 22: PRINT a$: '----------- 'allocating '----------- bx% = 10000 / 16: VIEW PRINT: VIEW PRINT: nralloc$ = HEX$(bx%): codeoff% = SADD(alloc$): CALL absolute(ax%, bx%, codeoff%): dosseg% = bx% VIEW PRINT: LOCATE 1, 1 IF ax% THEN PRINT "Error allocating memory "; bx%; " Available memory (para's) "; HEX$(ax%): EXIT SUB ELSE PRINT "Allocated "; STRING$(4 - LEN(nralloc$), "0") + nralloc$; " para's at segment(hex) : "; HEX$(bx%) END IF LOCATE 12, 1: COLOR 0, 7: PRINT "Moved 10 KB string to DOS: BASIC string is free!" COLOR 7, 0 'Let us move the string to DOS '----------------------------- DEF SEG = VARSEG(movestring$): codeoff% = SADD(movestring$): es% = dosseg% CALL absolute(basseg%, basoff%, es%, 0, 10000, codeoff%) 'Let us move a part back to BASIC LOCATE 12, 1: COLOR 0, 7: PRINT "Get the part of the string from 1995 to 2005:"; : COLOR 7, 0: PRINT SPACE$(10) b$ = SPACE$(10): codeoff% = SADD(getstring$) 'get chars 1995 to 2005 VIEW PRINT 15 TO 22: es% = dosseg% CALL absolute(es%, 1995, VARSEG(b$), SADD(b$), 10, codeoff%) CLS 2: LOCATE 15, 1: PRINT b$ VIEW PRINT: LOCATE 23, 1: PRINT "Press a key to change the last ten bytes of the DOSstring to "; COLOR 0, 7: PRINT b$: COLOR 7, 0 PRINT "and get the whole string back in BASIC": SLEEP 'Let us set some stringbytes codeoff% = SADD(movestring$): es% = dosseg% CALL absolute(VARSEG(b$), SADD(b$), es%, 9990, 10, codeoff%) VIEW PRINT: COLOR 0, 7: LOCATE 12, 1: PRINT "Get the whole string back to BASIC"; COLOR 7, 0: PRINT SPACE$(11): es% = dosseg% a$ = SPACE$(10000): codeoff% = SADD(getstring$) CALL absolute(es%, 0, VARSEG(a$), SADD(a$), 10000, codeoff%) VIEW PRINT 15 TO 22: CLS 2: LOCATE 15, 1: PRINT a$ PRINT "Last character at byte "; LEN(a$); " is a character : "; RIGHT$(a$, 1) DEF SEG 'Is looking good so far, not ? VIEW PRINT: LOCATE 2, 1 es% = dosseg%: segm% = es%: codeoff% = SADD(dealloc$) CALL absolute(es%, codeoff%) IF es% THEN PRINT "Error deallocating memory "; es% ELSE PRINT "Sucses deallocating memory from segment : "; HEX$(segm%) VIEW PRINT 23 TO 24: CLS 2 LOCATE 24, 1: PRINT "Press a key" + SPACE$(50): VIEW PRINT: SLEEP: CLS END SUB FUNCTION getSWORD& (USWORD%) '--------------------------------------------- 'This routine is translating an unsigned word in 'integer form to an signed integer in long format 'This might be useful when you have to read out 'some registers with unsigned words. 'IN: USWORD% (vb. &hEA60) 'OUT: SWORD& (vb. 60000 ) '--------------------------------------------- getSWORD& = USWORD% AND &HFFFF& END FUNCTION FUNCTION low.alloc$ '------------------------------------------------------------------- 'This function allocates lower memory 'STACK PASSING :AX%,BX% ' 'IN :BX%= number of para's to allocate ' 'OUT :AX%= startsegment or error ' :BX%= if error=8 then available memory ' :QBASIC: AX%=0 then success, else errorcode ' BX%=startsegment or number of segments available '--------------------------------------------------------------------- asm$ = "" asm$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&H1F) 'mov bx,[bx] 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$(&HD9) 'mov cx,bx need bx asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] asm$ = asm$ + CHR$(&H89) + CHR$(&HF) 'mov [bx],cx 0=no error asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+06] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax seg or error asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H4) + CHR$(&H0) 'retf 4 low.alloc$ = asm$ END FUNCTION FUNCTION low.dealloc$ '------------------------------------------------------------------- 'This function de allocates lower memory 'STACK PASSING :ES% ' 'IN :ES%= segment of block to de_allocate ' 'OUT :AX%= errorcode ' :QBASIC: ES%=0 or errorcode '--------------------------------------------------------------------- asm$ = "" asm$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp asm$ = asm$ + CHR$(&H6) 'push es asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+06] asm$ = asm$ + CHR$(&H8E) + CHR$(&H7) 'mov es,[bx] asm$ = asm$ + CHR$(&HB4) + CHR$(&H49) 'mov ah,49 asm$ = asm$ + CHR$(&HCD) + CHR$(&H21) 'int 21 asm$ = asm$ + CHR$(&H72) + CHR$(&H2) 'jc +2 asm$ = asm$ + CHR$(&H31) + CHR$(&HC0) 'XOR aX,aX if no error asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+08] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax 0=no error asm$ = asm$ + CHR$(&H7) 'pop es asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H2) + CHR$(&H0) 'retf 2 low.dealloc$ = asm$ 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$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp 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$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H2) + CHR$(&H0) 'retf 2 low.free$ = asm$ END FUNCTION FUNCTION low.getelement$ '------------------------------------------------------- 'This function gets an element of an DOSarray. 'STACKPASSING :DS%,SI%,BAS%,AX% 'IN :DS[SI] = source DOSarray ' BAS = destiny BASvar ' AX = elementnumber 'OUT : '------------------------------------------------------- 'PUSHA asm$ = "" asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&H1E) 'PUSH ds 'number of bytes asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6)'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&H7) 'MOV ax,[BX] asm$ = asm$ + CHR$(&HD1) + CHR$(&HE0) 'SHL AX,1 element relative adress 'source :DOS memory asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA)'MOV BX,[BP+0a] asm$ = asm$ + CHR$(&H8B) + CHR$(&H37) 'MOV si,[BX] asm$ = asm$ + CHR$(&H1) + CHR$(&HC6) 'ADD si,ax si=offset+nradress asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC)'MOV BX,[BP+0c] asm$ = asm$ + CHR$(&H8E) + CHR$(&H1F) 'MOV dS,[BX] 'alons y asm$ = asm$ + CHR$(&HFC) 'CLD asm$ = asm$ + CHR$(&HAD) 'LODSW asm$ = asm$ + CHR$(&H1F) 'pop ds 'destiny :BASIC variable asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8)'MOV BX,[BP+08] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'MOV [BX],ax 'POPA asm$ = asm$ + CHR$(&H5D) 'pop bp 'RETF asm$ = asm$ + CHR$(&HCA) + CHR$(&H8) + CHR$(&H0) 'retf 8 low.getelement$ = asm$ END FUNCTION FUNCTION low.getstring$ '------------------------------------------------------- 'This function returns a substring from DOS to BASIC. 'STACKPASSING :DS%,SI%,ES%,DI%,CX% 'IN :DS[SI] = source SI points to first byte to get( 0 based) ' ES[DI] = destiny BASIC ' CX = number of bytes to get (1 based) 'OUT : '------------------------------------------------------- 'PUSHA asm$ = "" 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 'number of bytes asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6)'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&HF) 'MOV cx,[BX] asm$ = asm$ + CHR$(&H89) + CHR$(&HCA) 'MOV dx,cx 'need a copy of cx asm$ = asm$ + CHR$(&HD1) + CHR$(&HE9) 'SHR cx,1 'divide by 2 'destiny: BASstring asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8)'MOV BX,[BP+08] asm$ = asm$ + CHR$(&H8B) + CHR$(&H3F) 'MOV di,[BX] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA)'MOV BX,[BP+0a] asm$ = asm$ + CHR$(&H8E) + CHR$(&H7) 'MOV ES,[BX] 'source : DOS memory asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC)'MOV BX,[BP+0c] asm$ = asm$ + CHR$(&H8B) + CHR$(&H37) 'MOV si,[BX] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HE)'MOV BX,[BP+0e] asm$ = asm$ + CHR$(&H8E) + CHR$(&H1F) 'MOV dS,[BX] 'alons y asm$ = asm$ + CHR$(&HFC) 'CLD asm$ = asm$ + CHR$(&HF2) + CHR$(&HA5) 'REPNZ MOVSW 'moves cx words from DS[SI] to ES[DI] asm$ = asm$ + CHR$(&HF6) + CHR$(&HC2) + CHR$(&H1)'TEST DL,1 is there a last byte ? asm$ = asm$ + CHR$(&H74) + CHR$(&H1) 'No ? Jmp over JZ 1 asm$ = asm$ + CHR$(&HA4) 'MOVSB 'last byte 'POPA asm$ = asm$ + CHR$(&H7) 'pop es asm$ = asm$ + CHR$(&H1F) 'pop ds asm$ = asm$ + CHR$(&H5D) 'pop bp 'RETF asm$ = asm$ + CHR$(&HCA) + CHR$(&HA) + CHR$(&H0) 'retf a low.getstring$ = asm$ END FUNCTION FUNCTION low.getsubarray$ '------------------------------------------------------- 'This function moves a subarray from DOS to BASIC. 'It will move an even number of bytes around. 'STACKPASSING :DS%,SI%,ES%,DI%,CX% 'IN :DS[SI] = source SI points to first element to get ' ES[DI] = destiny BASIC ' CX = number of elements to get 'OUT : '------------------------------------------------------- 'PUSHA asm$ = "" 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 'number of bytes asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6)'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&HF) 'MOV cx,[BX] asm$ = asm$ + CHR$(&HD1) + CHR$(&HE1) 'SHL CX,1 element relative adress 'destiny: BASIC array asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8)'MOV BX,[BP+08] asm$ = asm$ + CHR$(&H8B) + CHR$(&H3F) 'MOV di,[BX] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA)'MOV BX,[BP+0a] asm$ = asm$ + CHR$(&H8E) + CHR$(&H7) 'MOV ES,[BX] 'source : DOS memory asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC)'MOV BX,[BP+0c] asm$ = asm$ + CHR$(&H8B) + CHR$(&H37) 'MOV si,[BX] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HE)'MOV BX,[BP+0e] asm$ = asm$ + CHR$(&H8E) + CHR$(&H1F) 'MOV dS,[BX] 'alons y asm$ = asm$ + CHR$(&HFC) 'CLD asm$ = asm$ + CHR$(&HF2) + CHR$(&HA5) 'REPNZ MOVSW 'moves cx words from DS[SI] to ES[DI] 'POPA asm$ = asm$ + CHR$(&H7) 'pop es asm$ = asm$ + CHR$(&H1F) 'pop ds asm$ = asm$ + CHR$(&H5D) 'pop bp 'RETF asm$ = asm$ + CHR$(&HCA) + CHR$(&HA) + CHR$(&H0) 'retf a low.getsubarray$ = asm$ END FUNCTION FUNCTION low.movestring$ '------------------------------------------------------- 'This function moves stringblocks around in lowmemory. 'It can be used to move a block from BASIC to DOS and 'back. It moves bytes (for strings, string and byte types) 'STACKPASSING :DS%,SI%,ES%,DI%,CX% 'IN :DS[SI] = source ' ES[DI] = destiny ' CX = number of bytes to move 'OUT : '------------------------------------------------------- 'PUSHA asm$ = "" 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 'number of words asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6)'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&HF) 'MOV cx,[BX] asm$ = asm$ + CHR$(&H89) + CHR$(&HCA) 'MOV dx,cx 'need a copy of cx asm$ = asm$ + CHR$(&HD1) + CHR$(&HE9) 'SHR cx,1 'divide by 2 'destiny DOS memory asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8)'MOV BX,[BP+08] asm$ = asm$ + CHR$(&H8B) + CHR$(&H3F) 'MOV di,[BX] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA)'MOV BX,[BP+0a] asm$ = asm$ + CHR$(&H8E) + CHR$(&H7) 'MOV ES,[BX] 'source BASIC string asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC)'MOV BX,[BP+0c] asm$ = asm$ + CHR$(&H8B) + CHR$(&H37) 'MOV si,[BX] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HE)'MOV BX,[BP+0e] asm$ = asm$ + CHR$(&H8E) + CHR$(&H1F) 'MOV dS,[BX] 'alons y asm$ = asm$ + CHR$(&HFC) 'CLD asm$ = asm$ + CHR$(&HF2) + CHR$(&HA5) 'REPNZ MOVSW asm$ = asm$ + CHR$(&HF6) + CHR$(&HC2) + CHR$(&H1)'TEST DL,1 is there a last byte ? asm$ = asm$ + CHR$(&H74) + CHR$(&H1) 'No ? Jmp over JZ 1 asm$ = asm$ + CHR$(&HA4) 'MOVSB 'last byte 'POPA asm$ = asm$ + CHR$(&H7) 'pop es asm$ = asm$ + CHR$(&H1F) 'pop ds asm$ = asm$ + CHR$(&H5D) 'pop bp 'RETF asm$ = asm$ + CHR$(&HCA) + CHR$(&HA) + CHR$(&H0) 'retf a low.movestring$ = asm$ END FUNCTION FUNCTION low.movewords$ '------------------------------------------------------- 'This function moves memoryblocks around in lowmemory. 'It can be used to move a block from BASIC to DOS and 'back. It moves words( for integers and arrays,integer types) 'STACKPASSING :DS%,SI%,ES%,DI%,CX% 'IN :DS[SI] = source ' ES[DI] = destiny ' CX = number of words to move 'OUT : '------------------------------------------------------- 'PUSHA asm$ = "" 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 'number of words asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&HF) 'MOV cx,[BX] 'destiny DOS memory asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8)'MOV BX,[BP+08] asm$ = asm$ + CHR$(&H8B) + CHR$(&H3F) 'MOV di,[BX] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA)'MOV BX,[BP+0a] asm$ = asm$ + CHR$(&H8E) + CHR$(&H7) 'MOV ES,[BX] 'source BASIC array asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC)'MOV BX,[BP+0c] asm$ = asm$ + CHR$(&H8B) + CHR$(&H37) 'MOV si,[BX] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HE)'MOV BX,[BP+0e] asm$ = asm$ + CHR$(&H8E) + CHR$(&H1F) 'MOV dS,[BX] 'alons y asm$ = asm$ + CHR$(&HFC) 'CLD asm$ = asm$ + CHR$(&HF2) + CHR$(&HA5) 'REPNZ MOVSW 'POPA asm$ = asm$ + CHR$(&H7) 'pop es asm$ = asm$ + CHR$(&H1F) 'pop ds asm$ = asm$ + CHR$(&H5D) 'pop bp 'RETF asm$ = asm$ + CHR$(&HCA) + CHR$(&HA) + CHR$(&H0) 'retf a low.movewords$ = asm$ END FUNCTION FUNCTION low.setelement$ '------------------------------------------------------- 'This function sets an element of a DOSarray. 'STACKPASSING :ES%,DI%,BAS%,AX% 'IN :ES[DI] = destiny DOSarray ' BAS = source BASvar ' AX = elementnumber 'OUT : '------------------------------------------------------- 'PUSHA asm$ = "" asm$ = asm$ + CHR$(&H55) 'PUSH BP asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP asm$ = asm$ + CHR$(&H6) 'PUSH es asm$ = asm$ + CHR$(&H57) 'PUSH di 'Relative offset in array asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6)'MOV BX,[BP+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&H7) 'MOV ax,[BX] asm$ = asm$ + CHR$(&HD1) + CHR$(&HE0) 'SHL AX,1 element relative adress 'Destiny DOS memory asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA)'MOV BX,[BP+0a] asm$ = asm$ + CHR$(&H8B) + CHR$(&H3F) 'MOV di,[BX] asm$ = asm$ + CHR$(&H1) + CHR$(&HC7) 'ADD di,ax si=offset+nradress asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC)'MOV BX,[BP+0c] asm$ = asm$ + CHR$(&H8E) + CHR$(&H7) 'MOV eS,[BX] 'Source BASIC variable asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8)'MOV BX,[BP+08] asm$ = asm$ + CHR$(&H8B) + CHR$(&H7) 'MOV ax,[bx] 'Alons y asm$ = asm$ + CHR$(&HFC) 'CLD asm$ = asm$ + CHR$(&HAB) 'STOSW 'POPA asm$ = asm$ + CHR$(&H5F) 'POP di asm$ = asm$ + CHR$(&H7) 'pop es asm$ = asm$ + CHR$(&H5D) 'pop bp 'RETF asm$ = asm$ + CHR$(&HCA) + CHR$(&H8) + CHR$(&H0) 'retf 8 low.setelement$ = asm$ END FUNCTION FUNCTION USWORD% (SWORD&) '--------------------------------------------- 'This routine is translating a signed word in 'long form to an unsigned integer. This might 'be useful when you have to fill some registers 'with unsigned words. 'IN : SWORD& (vb. 60000 ) 'OUT: USWORD% (vb. &HEA60) '--------------------------------------------- helplowbyte& = SWORD& AND &HFFFF& word% = helplowbyte& AND &H7FFF USWORD% = word% OR -(helplowbyte& AND &H8000): END FUNCTION