'=========================================================================== ' Subject: ASSEMBLY IN QBASIC 3: PASSING Date: 02-19-97 (21:10) ' Author: Rick Elbers Code: QB, QBasic, PDS ' Origin: rick@tip.nl Packet: ASMCODE.ABC '=========================================================================== 'ASSEMBLY IN QBASIC 3: PASSING VARIABLES, ARRAYS, STRING to the STACK '--------------------------------------------------------------------- 'RICK ELBERS februari 1997 '--------------- 'Introduction '-------------- 'This routine is exploring the way array's, long integers 'and strings are passed to the assembly routine. There will 'be developed efficient procedures for doing this. 'In addition I will demonstrate some of the uses you can make 'of this knowledge. You absolutely need to understand the 'informations and tools presented in this article to make 'some progress with assembly in QBASIC. 'And the other way around too: when you understand them well,I 'think you have ways to gooo. '---------------------------------------------------------------- DEFINT A-Z 'INFORMATIONS: '************* DECLARE SUB integerinfo () 'information about integer passing DECLARE SUB longinfo (longs&) 'information about long passing DECLARE SUB stringinfo (a$) 'information about variable string passing DECLARE SUB fixedstringinfo () 'information about fixed string passing DECLARE SUB intarrayinfo () 'information about integer array passing DECLARE SUB intarrayinfo2 () 'information about integer array passing 2 DECLARE SUB longarrayinfo () 'information about long array passing DECLARE SUB stringarrayinfo () 'information about string array passing DECLARE SUB typeinfo () 'information about type passing 'DEMONSTRATIONS: '*************** DECLARE FUNCTION dosprn$ () 'demonstration of stringpassing DECLARE SUB movearr2arr () 'demonstration of integer array passing DECLARE SUB swapstringarray () 'demonstration of string array passing DECLARE SUB ascicntdemo () 'demonstration of long array passing TYPE testtype astring AS STRING * 5 ainteger AS INTEGER along AS LONG END TYPE DIM SHARED test AS testtype test.astring = "hallo" test.ainteger = &HFFFF test.along = &HF0F0F0F0 CLS COLOR 0, 7: PRINT "Let us get some information about passing .."; COLOR 7, 0: VIEW PRINT 3 TO 25 PRINT : PRINT : PRINT "Press a key for integer pass info": SLEEP: CLS CALL integerinfo PRINT : PRINT : PRINT "Press a key for long integer pass info": SLEEP: CLS CALL longinfo(&H123F546F) PRINT : PRINT : PRINT "Press a key for string pass info ": SLEEP: CLS CALL stringinfo("Wat is dit") PRINT : PRINT : PRINT "Press a key for fixed string pass info ": SLEEP: CLS CALL fixedstringinfo PRINT : PRINT : PRINT "Press a key for integer array pass info": SLEEP: CLS CALL intarrayinfo CALL intarrayinfo2 PRINT : PRINT : PRINT "Press a key for long array pass info": SLEEP: CLS CALL longarrayinfo PRINT : PRINT : PRINT "Press a key for array of strings pass info ": SLEEP: CLS CALL stringarrayinfo PRINT : PRINT : PRINT "Press a key for type pass info ": SLEEP: CLS CALL typeinfo PRINT : PRINT "Press a key": SLEEP: VIEW PRINT: CLS COLOR 0, 7: PRINT "Let us demonstrate barely the powers that we discovered.."; COLOR 7, 0: VIEW PRINT 3 TO 25 PRINT : PRINT "Press a key for string print demo ": SLEEP: CLS 2 'Using this information we can write an efficient dosprn COLOR 0, 7: PRINT "STRING PRINT DEMONSTRATION": COLOR 7, 0: PRINT : asm$ = dosprn$: Codeoff = SADD(asm$): DEF SEG = VARSEG(asm$): CALL absolute("HaHaThisisAll$", Codeoff) DEF SEG PRINT : PRINT : PRINT "Press a key for array movet demo ": SLEEP: CLS 2 'Using this information we can write an efficient movearray CALL movearr2arr PRINT : PRINT : PRINT "Press a key for stringswap demo ": SLEEP: CLS 2 'Using this information we can write an very efficient stringsort CALL swapstringarray PRINT : PRINT : PRINT "Press a key for ascicount(long array) demo ": SLEEP: CLS 2 CALL ascicntdemo PRINT : PRINT : PRINT "Press a key for conclusions ": SLEEP: VIEW PRINT: CLS 'The use of stringarrays can hardly be overestimated. First they default 'to the stringsegment and second there location is stable. This makes them 'very useful for the storage of asm functions as we will see in the next 'issues of ASM in QBASIC. Also because of the descriptors you could sort 'a complete array of strings with a resultant indexarray of elements 'which make it possible to get the array sorted in QBASIC by: 'FOR i=lbound(arraystring$) TO ubound(arraystring$) ' print arraystring$(index(i)) 'NEXT 'This will be very very fast since the only thing you sort is the index 'and you are not going to copy the strings themselves.... PRINT SPACE$(30); : COLOR 0, 7: PRINT " CONCLUSIONS ": COLOR 7, 0 PRINT COLOR 0, 7: PRINT " MEMORY LOCATIONS ": COLOR 7, 0 PRINT "- The memory LOCATIONS of integers, stringarrays and types are STABLE." PRINT "- The memory LOCATION of a fixed length string is also STABLE." PRINT "- A variable length string is prone to garbage collection(<>STABLE)." PRINT COLOR 0, 7: PRINT " MEANINGFULL STACKPASSING POSSIBILITIES ": COLOR 7, 0 PRINT "-You can pass all types of variables in a meaningful manner through" PRINT " the stack except the FIXED LENGTH string." PRINT COLOR 0, 7: PRINT " PASSING BY VALUE ": COLOR 7, 0 PRINT "-INTEGERS and TYPES are the only 'variables' that are passed by VALUE by default" PRINT "-It is possible to pass LONG integers by VALUE while using BYVAL" PRINT COLOR 0, 7: PRINT " PASSING BY REFERENCE ": COLOR 7, 0 PRINT "-All variables except INTEGERS and TYPES are passed by REFERENCE by default." PRINT "-INTEGER/TYPE REFERENCING(pointing)is possible by reference to there STACKADRESS" PRINT COLOR 0, 7: PRINT " STRANGE BEHAVIORS ": COLOR 7, 0 PRINT "-Like Gunter Ilzig pointed out PASSING by REFERENCE is ALWAYS faster" PRINT " This is also true for integer and type passing( strange fact)": PRINT PRINT "Good bye" END DEFSTR A-Z SUB ascicntdemo COLOR 0, 7: PRINT "LONG ARRAY DEMONSTRATION": COLOR 7, 0: PRINT : '--------------------------------------- 'THIS FUNCTION TRIES TO SPEED UP 'THE SORT OF FREQUENCY OF CHARACTERS. 'EOF IS STORED TOO! 'STACKPASSING FREQ&(),A$ 'IN: FREQ ARRAY ' STRING TO CNT 'OUT FREQ ARRAY UPDATED 'Its just an example of the use of long 'array's.. '--------------------------------------- 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 'DS[SI] TO STRING,CX TO LEN asm = asm + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'MOV BX,[BP+06] asm = asm + CHR$(&H8B) + CHR$(&HF) 'MOV CX,[BX] LENGTH asm = asm + CHR$(&H8B) + CHR$(&H77) + CHR$(&H2) 'MOV SI,[BX+2]DS[SI] STRING 'ES[DI] TO ARRAY asm = asm + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'MOV BX,[BP+08] asm = asm + CHR$(&HC4) + CHR$(&H3F) 'LES DI,[BX] ES[DI] ASCARRAY asm = asm + CHR$(&HFC) 'CLD FUTURE 'LOOPJE: asm = asm + CHR$(&HAC) 'LODSB DS[SI] > AL asm = asm + CHR$(&H30) + CHR$(&HE4) 'XOR AH,AH asm = asm + CHR$(&HC1) + CHR$(&HE0) + CHR$(2) 'SHL AX,2 ASC TO INTELEMENT asm = asm + CHR$(&H89) + CHR$(&HC3) 'MOV BX,AX TO ADRESS IN ARRAY asm = asm + CHR$(&H26) + CHR$(&HFF) + CHR$(&H7) 'ES:INC[BX] asm = asm + CHR$(&H49) 'DEC CX asm = asm + CHR$(&H75) + CHR$(&HF2) 'JNZ -12 ANOTHER ELEMENT ? asm = asm + CHR$(&H7) 'POP ES asm = asm + CHR$(&H1F) 'POP DS asm = asm + CHR$(&H5D) 'POP BP asm = asm + CHR$(&HCA) + CHR$(&H4) + CHR$(&H0) 'RETF 4 ascicnt = asm '------------------------------------------------- 'LONGDIVINT: 'This function is returning both the division 'and the remainder from an SDWORD to SWORD division. 'STACKPASSING Word&,Div& 'IN : Word& the Dword to divide ' Div% the word to divide by 'OUT: Word& the result of Longintegerdivision ' DIv% the remainder of the Longintegerdivision '-------------------------------------------------- asm = "" asm = asm + CHR$(&H55) 'push bp 4 asm = asm + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp 1 asm = asm + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+0a] 1+9 asm = asm + CHR$(&H8B) + CHR$(&H7) 'mov AX,[bx] 1+5 low asm = asm + CHR$(&H8B) + CHR$(&H57) + CHR$(2) 'mov DX,[bx+2] 1+9 high asm = asm + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+06] 1+9 asm = asm + CHR$(&H8B) + CHR$(&HF) 'mov CX,[bx] 1+5 asm = asm + CHR$(&HF7) + CHR$(&HF9) 'idiv cx 27 asm = asm + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+0A] 1+9 asm = asm + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax 1+5 asm = asm + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+08] 1+9 asm = asm + CHR$(&H89) + CHR$(&H17) 'mov [bx],dx 1+5 asm = asm + CHR$(&H5D) 'pop bp 4 asm = asm + CHR$(&HCA) + CHR$(&H6) + CHR$(&H0) 'retf 4 14 longdivint = asm 'clocks 105 'Initiating functions ,arrays and string: DIM freq&(255): a$ = SPACE$(10000): FOR I% = 0 TO 255: freq&(I%) = 0: NEXT: DEF SEG = &H40: POKE &H1C, PEEK(&H1A) DEF SEG = VARSEG(ascicnt) 'Oke and lets go for it( you can hold your breath!even for 300 KB text!) PRINT "Give a path of very large(< 100 MB) text file.. "; f$ = "": DO UNTIL f$ <> "": COLOR 0, 7: LINE INPUT f$: LOOP: COLOR 7, 0 PRINT : a! = TIMER: OPEN f$ FOR BINARY AS #1 mods% = 10000: CALL absolute(LOF(1), divs%, mods%, SADD(longdivint)) FOR I% = 1 TO divs% GET #1, , a$: '___________________________________________________________ CALL absolute(freq&(), a$, SADD(ascicnt)) '___________________________________________________________ NEXT a$ = SPACE$(mods%): GET #1, , a$ 'last part CALL absolute(freq&(), a$, SADD(ascicnt)) leof& = LOF(1): CLOSE : DEF SEG c! = TIMER COLOR 0, 7: PRINT "Frekwenties of 'text' ASCI's"; : COLOR 7, 0: PRINT : FOR I% = 32 TO 126: PRINT CHR$(I%); ":"; : PRINT USING "#######"; freq&(I%); : PRINT " "; : IF (I% - 32) MOD 8 = 7 THEN PRINT NEXT PRINT : PRINT PRINT "For a file of "; : COLOR 0, 7: PRINT leof&; : COLOR 7, 0: PRINT " bytes we needed "; : COLOR 0, 7: PRINT c! - a!; : COLOR 7, 0 END SUB DEFSNG A-Z FUNCTION dosprn$ 'This functions prints a string with only passing the string itself. Period 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$(&H57) + CHR$(&H2) 'mov dx,[bx+2] get sadd asm$ = asm$ + CHR$(&HB4) + CHR$(&H9) 'mov ah,9 ds points already to stringseg asm$ = asm$ + CHR$(&HCD) + CHR$(&H21) 'int 21 asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H2) + CHR$(&H0) 'retf 8 dosprn$ = asm$ END FUNCTION DEFINT A-Z SUB fixedstringinfo '------------------------------------------------- 'This function checks how fixed strings are passed 'through a call absolute procedure '------------------------------------------------- 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$(&H89) + CHR$(&HD9) 'mov cx,bx get varptr asm$ = asm$ + CHR$(&H8B) + CHR$(&H7) 'mov ax,[bx] get len asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+0A] first var asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] sec var asm$ = asm$ + CHR$(&H89) + CHR$(&HF) 'mov [bx],cx asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H6) + CHR$(&H0) 'retf 6 DIM als AS STRING * 31 '________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$) CALL absolute(a, b, als$, Codeoff) '________________________________________ DEF SEG COLOR 0, 7: PRINT "FIXED STRING PASSING INFORMATION": COLOR 7, 0: PRINT : COLOR 0, 7: PRINT "Fixed String passed to the stack as a$": PRINT "CALL ABSOLUTE (a,b,a$,codeoff)" COLOR 7, 0: PRINT "BX is initialized as BX = [BP+06]" PRINT "After that:" PRINT "First variabele( Length of string at [BX]) : "; a PRINT "Second variabele( 'VARPTR' of string at BX) : "; HEX$(b) PRINT "The control values of LEN and VARPTR are :"; : COLOR 0, 7: PRINT LEN(als$); " "; HEX$(VARPTR(als$)); " "; COLOR 7, 0 END SUB SUB intarrayinfo '------------------------------------------------------- 'This sub does nothing more then change an array! 'SI and DI are used since they are basedisplacement for 'DS where BP is basedisplacement for SS! '------------------------------------------------------- DIM a(1, 1): segje = VARSEG(a(0, 0)): offje = VARPTR(a(0, 0)) COLOR 0, 7: PRINT "Array passing information "; : COLOR 7, 0: PRINT : PRINT "The array as initialized:" FOR j = 0 TO 1: FOR I = 0 TO 1: a(I, j) = I * 10 + j: PRINT "element :"; j; ","; I; "value :"; a(I, j): NEXT: NEXT asm$ = "" asm$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp asm$ = asm$ + CHR$(&H1E) 'push ds '--------------------------------- 'Get si to point to offset array: '--------------------------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&H37) 'mov si,[bx] '----------------------- 'segment of array to ds: '---------------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] asm$ = asm$ + CHR$(&H8E) + CHR$(&H1F) 'mov ds,[bx] '------------------------------------- 'Increment first element and store it: '------------------------------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H3C) 'mov di,[si] asm$ = asm$ + CHR$(&H47) 'inc di asm$ = asm$ + CHR$(&H89) + CHR$(&H3C) 'mov [si],di '-------------------------------------- 'Decrement second element and store it: '-------------------------------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H7C) + CHR$(&H2) 'mov di,[si+2] asm$ = asm$ + CHR$(&H4F) 'dec di asm$ = asm$ + CHR$(&H89) + CHR$(&H7C) + CHR$(&H2) 'mov [si+2],di asm$ = asm$ + CHR$(&H1F) 'pop ds 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(segje, offje, Codeoff) '________________________________________ DEF SEG PRINT "The array after machinations: increment first/decrement second element" FOR j = 0 TO 1: FOR I = 0 TO 1: PRINT "element :"; j; ","; I; "value :"; a(I, j): NEXT: NEXT END SUB SUB intarrayinfo2 '--------------------------------------------------------- 'This sub does nothing more then get elements of an array '--------------------------------------------------------- DIM a(1, 1): FOR j = 0 TO 1: FOR I = 0 TO 1: a(I, j) = I * 10 + j + 1: NEXT: NEXT segje = VARSEG(a(0, 0)): offje = VARPTR(a(0, 0)) asm$ = "" asm$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp asm$ = asm$ + CHR$(&H1E) 'push ds '--------------------------------- 'Get si to point to offset array: '--------------------------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+06] asm$ = asm$ + CHR$(&HC5) + CHR$(&H37) 'lds si,[bx] get ptr to array asm$ = asm$ + CHR$(&H8C) + CHR$(&HD8) 'mov ax,ds and saving asm$ = asm$ + CHR$(&H8B) + CHR$(&H4C) + CHR$(4) 'mov cx,[si+04] get an arrayelement 'third element! asm$ = asm$ + CHR$(&H1F) 'pop ds asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] last var asm$ = asm$ + CHR$(&H89) + CHR$(&HF) 'mov [bx],cx asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+0a] sec var asm$ = asm$ + CHR$(&H89) + CHR$(&H37) 'mov [bx],si asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC) 'mov bx,[bp+08] first var asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H8) + CHR$(&H0) 'retf 8 '________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$) CALL absolute(b, c, d, a(), Codeoff) '________________________________________ DEF SEG PRINT COLOR 0, 7: PRINT "Original array passed to the stack as array a()": PRINT "CALL ABSOLUTE (b,c,d,a(),codeoff)" COLOR 7, 0: PRINT "BX is initialized as BX = [BP+06]" PRINT "After that:" PRINT "First variabele( segment of array at [BX+2]) : "; HEX$(b) PRINT "Second variabele( offset of array at [BX]) : "; HEX$(c) PRINT "Third variabele (value of element at [BX+2]:[BX+2*elementnr] :"; d PRINT "The control values are resp.: "; : COLOR 0, 7: PRINT HEX$(segje), HEX$(offje), a(0, 1); : COLOR 7, 0 END SUB SUB integerinfo '-------------------------------------------------------------- 'This function checks how integers are passed to call absolute 'First by reference and then by value.. '-------------------------------------------------------------- asm$ = "" asm$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp asm$ = asm$ + CHR$(&H8B) + CHR$(&H76) + CHR$(&H6) 'mov si,[bp+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&H4) 'mov ax,[si] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] asm$ = asm$ + CHR$(&H8B) + CHR$(&H1F) 'mov bx,[bx] asm$ = asm$ + CHR$(&H89) + CHR$(&H1C) 'mov [si],bx asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+0a] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] asm$ = asm$ + CHR$(&H89) + CHR$(&H37) 'mov [bx],si asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H6) + CHR$(&H0) 'retf 6 '______________________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$): fill = 76: in = 5: ints = in CALL absolute(a, fill, ints, Codeoff) '_______________________________________________________ DEF SEG COLOR 0, 7: PRINT "INTEGER PASSING INFORMATION"; : COLOR 7, 0: PRINT : PRINT COLOR 0, 7: PRINT "Integer passed to the stack by reference as ints": PRINT "CALL ABSOLUTE (a,fill,ints,codeoff)" COLOR 7, 0: PRINT "BX is intialized as BX =[SP+6]" PRINT "After that:" PRINT "First variabele( Value of ints at [BX]) : "; HEX$(a) PRINT "Second variabele( Varptr of ints at BX) : "; HEX$(fill) PRINT "We changed the ints to fill : "; HEX$(ints) PRINT "The control values VARPTR and value are : "; : COLOR 0, 7: PRINT HEX$(VARPTR(ints)), HEX$(in): COLOR 7, 0 'And lets do it by value... asm$ = "" asm$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp asm$ = asm$ + CHR$(&H8B) + CHR$(&H46) + CHR$(&H6) 'mov ax,[bp+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+0A] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H4) + CHR$(&H0) 'retf 4 '________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$): ints = 8 CALL absolute(ax, BYVAL (ints), Codeoff) '________________________________________ DEF SEG PRINT COLOR 0, 7: PRINT "Integer passed to the stack by value as BYVAL(ints)": PRINT "CALL ABSOLUTE (AX,BYVAL(ints),codeoff)" COLOR 7, 0: PRINT "AX is intialized as AX=[SP+6]" PRINT "After that:" PRINT "First variabele( Value of ints at AX ) : "; HEX$(ax) PRINT "The control value of ints is : "; : COLOR 0, 7: PRINT HEX$(ints): COLOR 7, 0 END SUB SUB longarrayinfo '--------------------------------------------------------- 'This sub does nothing more then get elements of a 'array of long integers '--------------------------------------------------------- COLOR 0, 7: PRINT "LONG INTEGER ARRAY passing information "; : COLOR 7, 0: PRINT : DIM a&(1, 1): FOR j = 0 TO 1: FOR I = 0 TO 1: a&(I, j) = &HFFFFF + I * 10 + j + 1: NEXT: NEXT segje = VARSEG(a&(0, 0)): offje = VARPTR(a&(0, 0)) asm$ = "" asm$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp asm$ = asm$ + CHR$(&H1E) 'push ds '--------------------------------- 'Get si to point to offset array: '--------------------------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+06] asm$ = asm$ + CHR$(&HC5) + CHR$(&H37) 'lds si,[bx] get ptr to array asm$ = asm$ + CHR$(&H8C) + CHR$(&HD8) 'mov ax,ds and saving asm$ = asm$ + CHR$(&H66) + CHR$(&H8B) + CHR$(&H4C) + CHR$(8)'mov ecx,[si+08]get an arrayelement 'third element! asm$ = asm$ + CHR$(&H1F) 'pop ds asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] last var asm$ = asm$ + CHR$(&H66) + CHR$(&H89) + CHR$(&HF) 'mov [bx],ecx asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+0a] sec var asm$ = asm$ + CHR$(&H89) + CHR$(&H37) 'mov [bx],si asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC) 'mov bx,[bp+08] first var asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H8) + CHR$(&H0) 'retf 8 '________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$) CALL absolute(b, c, d&, a&(), Codeoff) '________________________________________ DEF SEG PRINT COLOR 0, 7: PRINT "Original array passed to the stack as array a&()": PRINT "CALL ABSOLUTE (b,c,d&,a&(),codeoff)" COLOR 7, 0: PRINT "BX is initialized as BX = [BP+06]" PRINT "After that:" PRINT "First variabele( segment of array at [BX+2]) : "; HEX$(b) PRINT "Second variabele( offset of array at [BX]) : "; HEX$(c) PRINT "Third variabele (value of element at [BX+2]:[BX+4*elementnr] :"; d& PRINT "The control values are resp.: "; : COLOR 0, 7: PRINT HEX$(segje), HEX$(offje), a&(0, 1); : COLOR 7, 0 END SUB SUB longinfo (longs&) '------------------------------------------------------------ 'This function checks how longs are passed to call absolute 'First by reference and then by value.. '------------------------------------------------------------ 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$(&H7) 'mov ax,[bx] asm$ = asm$ + CHR$(&H8B) + CHR$(&H4F) + CHR$(&H2) 'mov cx,[bx+2] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] asm$ = asm$ + CHR$(&H89) + CHR$(&HF) 'mov [bx],cx asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+0a] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H6) + CHR$(&H0) 'retf 6 '________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$) CALL absolute(a, b, longs&, Codeoff) '________________________________________ DEF SEG COLOR 0, 7: PRINT "LONG INTEGER PASSING INFORMATION": COLOR 7, 0: PRINT : COLOR 0, 7: PRINT "Long integer passed to the stack by reference as longs&": PRINT "CALL ABSOLUTE (a,b,longs&,codeoff)" COLOR 7, 0: PRINT "BX is initialized as BX = [BP+06]" PRINT "After that:" PRINT "First variabele( Lowword of long at [BX]) : "; HEX$(a) PRINT "Second variabele( Highword of array at [BX+2]) : "; HEX$(b) PRINT "The control value of the long integer is: : "; : COLOR 0, 7: PRINT HEX$(longs&): COLOR 7, 0 'And lets do it by value... asm$ = "" asm$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp asm$ = asm$ + CHR$(&H8B) + CHR$(&H46) + CHR$(&H6) 'mov ax,[bp+06] asm$ = asm$ + CHR$(&H8B) + CHR$(&H4E) + CHR$(&H8) 'mov cx,[bp+08] asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+08] asm$ = asm$ + CHR$(&H89) + CHR$(&HF) 'mov [bx],cx asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC) 'mov bx,[bp+0a] asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H8) + CHR$(&H0) 'retf 8 '________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$) CALL absolute(a, b, BYVAL (longs&), Codeoff) '________________________________________ DEF SEG PRINT COLOR 0, 7: PRINT "Long integer passed by value to the stack as longs&": PRINT "CALL ABSOLUTE (a,b,longs&,codeoff)" COLOR 7, 0: PRINT "BP is initialized as BP = SP" PRINT "After that:" PRINT "First variabele( Lowword of long at [BP+06]) : "; HEX$(a) PRINT "Second variabele( Highword of array at [BP+08]) : "; HEX$(b) PRINT "The control value of the long integer is: : "; : COLOR 0, 7: PRINT HEX$(longs&): COLOR 7, 0 END SUB SUB movearr2arr 'Wat this function does is something that you need surprisingly 'often. When you take a good look at some interruptlist you 'will notice some difficult parameterblocks there that you have 'to pass to the interrupt. Often those parameterblocks are 'discontinue( if that is the right word) in that they consist 'of bytes,words and dubbel words. That is why this function 'might be extremely useful for loading up some parameterblock 'This is just an example of loading up a parameterblock 'with: DW length is a long ' W handle is an integer ' DW offset:segment of array ' W handle is an integer ' DW 32 bit offset is a long '--actually this is the syntax for XMS.move( just to let you know it) 'You should notice that the uploading of elements is redundant, and that 'is the reason why some large sorting algorithm can be quite small in 'asm source!. Also notice that we never used DS[si] so far since there 'where no strings to pass to the params! 'STACKPASSING nrbytes&,XMShandle,source(),XMSoffset,Params() 'IN : ES[DI] parameterblock ' .... parameters to pass to the block 'nrbytes& 'XMShandle 'sourcearray 'XMSoffset& 'OUT : ES[DI] filled parameterblock 'USING IN QBASIC: ARRAYPASSING, "ALL TYPES" PASSING '------------------------------------------------------------- asm$ = "" asm$ = asm$ + CHR$(&H55) 'push bp asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp asm$ = asm$ + CHR$(&H6) 'push Es '---------------------------------------- 'Let us first put the destiny in ES[DI]: '---------------------------------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'mov bx,[bp+06] asm$ = asm$ + CHR$(&HC4) + CHR$(&H3F) 'LES DI,[bx] get ptr to array '------------ 'Get nrbytes& '------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HE) 'mov bx,[bp+0e] asm$ = asm$ + CHR$(&H8B) + CHR$(&H7) 'mov ax,[bx] asm$ = asm$ + CHR$(&HAB) 'stosw naar es[di] lowbyte asm$ = asm$ + CHR$(&H8B) + CHR$(&H47) + CHR$(&H2) 'mov ax,[bx+2] asm$ = asm$ + CHR$(&HAB) 'stosw naar es[di] highbyte '-------------------------- 'Store 0 for source handle '-------------------------- asm$ = asm$ + CHR$(&H31) + CHR$(&HC0) 'xor ax,ax asm$ = asm$ + CHR$(&HAB) 'stosw naar es[di] 0 '--------------------------------------- 'Get offset and segment of source array '--------------------------------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+0A] asm$ = asm$ + CHR$(&H8B) + CHR$(&H7) 'mov ax,[bx] get OFFSRC asm$ = asm$ + CHR$(&HAB) 'stosw naar es[di] asm$ = asm$ + CHR$(&H8B) + CHR$(&H47) + CHR$(&H2) 'mov ax,[bx+2] get SEGSRC asm$ = asm$ + CHR$(&HAB) 'stosw naar es[di] '----------------- 'Get XMS handle '----------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC) 'mov bx,[bp+0C] asm$ = asm$ + CHR$(&H8B) + CHR$(&H7) 'mov ax,[bx] get handle asm$ = asm$ + CHR$(&HAB) 'stosw naar es[di] '---------------------- 'Get XMS 32 bit offset '---------------------- asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] asm$ = asm$ + CHR$(&H8B) + CHR$(&H7) 'mov ax,[bx] asm$ = asm$ + CHR$(&HAB) 'stosw naar es[di] lowbyte asm$ = asm$ + CHR$(&H8B) + CHR$(&H47) + CHR$(&H2) 'mov ax,[bx+2] asm$ = asm$ + CHR$(&HAB) 'stosw naar es[di] highbyte '-------------------------------------------------- 'Well in fact we are done. Here is where the real 'XMS thing starts..but thats for later '-------------------------------------------------- asm$ = asm$ + CHR$(&H7) 'push Es asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&HA) + CHR$(&H0) 'retf a nrbytes& = &HF1234567: DIM src(10000): xmsoff& = &HFEDCBA98 DIM params(7): xmshandle = &H1122 '________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$) CALL absolute(nrbytes&, xmshandle, src(), xmsoff&, params(), Codeoff) '________________________________________ COLOR 0, 7: PRINT "ARRAY MOVE DEMONSTRATION": COLOR 7, 0: PRINT : COLOR 0, 7 FOR I = 0 TO 7: PRINT I, HEX$(params(I)): NEXT COLOR 7, 0 PRINT "There was passed a:" COLOR 0, 7: PRINT "CALL ABSOLUTE(nrbytes&, xmshandle, src(), xmsoff&, params(), Codeoff) " COLOR 7, 0: PRINT "Controlvalues are:": COLOR 0, 7 PRINT "0 DW Nrbytes : "; HEX$(nrbytes&) PRINT "2 W handle :"; 0 PRINT "3 W offset src : "; HEX$(VARPTR(src(0))) PRINT "4 W segment src : "; HEX$(VARSEG(src(0))) PRINT "5 W XMShandle : "; HEX$(xmshandle) PRINT "6 DW XMSoffset : "; HEX$(xmsoff&) COLOR 7, 0 END SUB SUB stringarrayinfo '-------------------------------------------------- 'This function checks how string array's are passed 'through a call absolute procedure '-------------------------------------------------- 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$(&H57) + CHR$(&H2) 'mov dx,[bx+2] get seg asm$ = asm$ + CHR$(&H8B) + CHR$(&H37) 'mov si,[bx] get varptr asm$ = asm$ + CHR$(&H8B) + CHR$(&HC) 'mov cx,[si] get len first element asm$ = asm$ + CHR$(&H8B) + CHR$(&H44) + CHR$(&H2) 'mov ax,[si+2] get sadd first element asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HE) 'mov bx,[bp+0E] first var asm$ = asm$ + CHR$(&H89) + CHR$(&H17) 'mov [bx],dx seg asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC) 'mov bx,[bp+0C] sec var asm$ = asm$ + CHR$(&H89) + CHR$(&H37) 'mov [bx],si varptr asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+0A] third var asm$ = asm$ + CHR$(&H89) + CHR$(&HF) 'mov [bx],cx len asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] fourth var asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax sadd asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&HA) + CHR$(&H0) 'retf A CLS : DIM arraystrings$(10) arraystrings$(0) = "doei" arraystrings$(1) = "b" arraystrings$(2) = "En dit dan als ik vragen mag ?" '________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$) CALL absolute(a, b, c, d, arraystrings$(), Codeoff) '________________________________________ DEF SEG COLOR 0, 7: PRINT "STRINGARRAY PASSING INFORMATION": COLOR 7, 0: PRINT : COLOR 0, 7: PRINT "String passed to the stack as arraystring$()": PRINT "CALL ABSOLUTE (a,b,c,d,arraystrings$(),codeoff)" COLOR 7, 0: PRINT "BX is initialized as BX = [BP+06]" PRINT "After that:" PRINT "First variabele( VARSEG of stringsarray at [BX+2] ) : "; HEX$(a) PRINT "Second variabele( VARPTR of stringsarray at [BX]) : "; HEX$(b) PRINT "Third variabele( LEN of first string at [VARPTR]) : "; HEX$(c) PRINT "Fourth variabele( SADD of first string at [VARPTR+2]) : "; HEX$(d) PRINT "The control values of SEG, VARPTR, LEN and SADD are : "; : COLOR 0, 7: PRINT HEX$(VARSEG(arraystrings$(0))); " "; HEX$(VARPTR(arraystrings$(0))); " "; HEX$(LEN(arraystrings$(0))); " "; HEX$(SADD(arraystrings$(0))) COLOR 7, 0 END SUB SUB stringinfo (a$) '--------------------------------------------- 'This function checks how strings are passed 'through a call absolute procedure '------------------------------------------- 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$(&H89) + CHR$(&HD9) 'mov cx,bx get varptr asm$ = asm$ + CHR$(&H8B) + CHR$(&H7) 'mov ax,[bx] get len asm$ = asm$ + CHR$(&H8B) + CHR$(&H57) + CHR$(&H2) 'mov dx,[bx+2] get sadd asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC) 'mov bx,[bp+0c] first var asm$ = asm$ + CHR$(&H89) + CHR$(&H7) 'mov [bx],ax asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+0a] sec var asm$ = asm$ + CHR$(&H89) + CHR$(&HF) 'mov [bx],cx asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] third var asm$ = asm$ + CHR$(&H89) + CHR$(&H17) 'mov [bx],dx asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H8) + CHR$(&H0) 'retf 8 '________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$) CALL absolute(a, b, c, a$, Codeoff) '________________________________________ DEF SEG COLOR 0, 7: PRINT "STRING PASSING INFORMATION": COLOR 7, 0: PRINT : COLOR 0, 7: PRINT "String passed to the stack as a$": PRINT "CALL ABSOLUTE (a,b,c,a$,codeoff)" COLOR 7, 0: PRINT "BX is initialized as BX = [BP+06]" PRINT "After that:" PRINT "First variabele( Length of string at [BX] ) : "; a PRINT "Second variabele( VARPTR of string at BX) : "; HEX$(b) PRINT "Second variabele( SADD of string at [BX+2]) : "; HEX$(c) PRINT "The control values of LEN, VARPTR and SADD are :"; : COLOR 0, 7: PRINT LEN(a$); " "; HEX$(VARPTR(a$)); " "; HEX$(SADD(a$)) COLOR 7, 0 END SUB SUB swapstringarray '---------------------------------------------------------------- 'This procedure will swap some elements of a stringarray. 'Very useful when you want a fast sort of stringelements. 'The better method then the one used here for an array of 'fixed length strings is to sort the stringdescriptors. That way 'you only need to copy the strings one time. However QBASIC seems 'to prevent the straightforward updating of the descriptors. 'What IS possible is to pass an index (integerarray) along with 'the array of strings and 'sort' the indexarray. '---------------------------------------------------------------- asm$ = "" asm$ = asm$ + CHR$(&H55) 'push bp 4 asm$ = asm$ + CHR$(&H89) + CHR$(&HE5) 'mov bp,sp 1 asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6)'mov bx,[bp+06] 1+9 asm$ = asm$ + CHR$(&H8B) + CHR$(&H1F) 'mov bx,[bx] get varptr 1+5 asm$ = asm$ + CHR$(&HBE) + MKI$(&HA) 'mov si,a 1 asm$ = asm$ + CHR$(&H8B) + CHR$(&H28) 'mov bp,[bx+si]ptr sadd 3d element 1+7 asm$ = asm$ + CHR$(&HBE) + MKI$(&H2) 'mov si,2 1 asm$ = asm$ + CHR$(&H8B) + CHR$(&H18) 'mov bx,[bx+si]ptr sadd 1st element 1+7 asm$ = asm$ + CHR$(&HBE) + MKI$(&H8) 'mov si,A bytes to copy 1 asm$ = asm$ + CHR$(&H8B) + CHR$(&H0) 'mov al,[bx+si] get first element first 2 char 1+7 asm$ = asm$ + CHR$(&H87) + CHR$(&H2) 'xchg al,[bp+si]xchg with third element 3+7 asm$ = asm$ + CHR$(&H89) + CHR$(&H0) 'mov [bx+si],al 1+7 asm$ = asm$ + CHR$(&H83) + CHR$(&HEE) + CHR$(2) 'sub si,2 1 asm$ = asm$ + CHR$(&H79) + CHR$(&HF5) 'jns - 11 3/1 asm$ = asm$ + CHR$(&H5D) 'pop bp 4 asm$ = asm$ + CHR$(&HCA) + CHR$(&H2) + CHR$(&H0) 'retf 2 14 CLS : DIM arraystrings$(2) arraystrings$(0) = "doei" + SPACE$(7) arraystrings$(1) = "b" + SPACE$(9) arraystrings$(2) = "En dit dan" COLOR 0, 7: PRINT "STRINGARRAY SWAPPING DEMONSTRATION": COLOR 7, 0: PRINT : PRINT : COLOR 0, 7: PRINT "ARRAY BEFORE SWAP": COLOR 7, 0 FOR I = 0 TO 2 PRINT I; ":", arraystrings$(I) NEXT '________________________________________ Codeoff = SADD(asm$) DEF SEG = VARSEG(asm$) CALL absolute(arraystrings$(), Codeoff) '________________________________________ DEF SEG : PRINT COLOR 0, 7: PRINT "ARRAY AFTER SWAP": COLOR 7, 0 FOR I = 0 TO 2 PRINT I; ":", arraystrings$(I) NEXT ' END SUB DEFSNG A-Z SUB typeinfo '--------------------------------------------- 'This function checks how types are passed 'through a call absolute procedure '------------------------------------------- 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$(&H66) + CHR$(&H8B) + CHR$(&H7) 'mov eax,[bx] get string asm$ = asm$ + CHR$(&H8B) + CHR$(&H4F) + CHR$(5) 'mov cx,[bx+5] get int asm$ = asm$ + CHR$(&H66) + CHR$(&H8B) + CHR$(&H57) + CHR$(7)'mov edx,[bx+7] get long asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC) 'mov bx,[bp+0c] first var asm$ = asm$ + CHR$(&H66) + CHR$(&H89) + CHR$(&H7) 'mov [bx],eax asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) 'mov bx,[bp+0a] sec var asm$ = asm$ + CHR$(&H89) + CHR$(&HF) 'mov [bx],cx asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) 'mov bx,[bp+08] third var asm$ = asm$ + CHR$(&H66) + CHR$(&H89) + CHR$(&H17) 'mov [bx],edx asm$ = asm$ + CHR$(&H5D) 'pop bp asm$ = asm$ + CHR$(&HCA) + CHR$(&H8) + CHR$(&H0) 'retf 8 '________________________________________ Codeoff% = SADD(asm$) DEF SEG = VARSEG(asm$) CALL absolute(a&, b%, c&, test, Codeoff%) '________________________________________ DEF SEG COLOR 0, 7: PRINT "TYPE PASSING INFORMATION": COLOR 7, 0: PRINT : COLOR 0, 7: PRINT "TYPE passed to the stack as test:" PRINT "CALL ABSOLUTE (a&,b%,c&,test,codeoff%)" COLOR 7, 0: PRINT "BX is initialized as BX = [BP+06]" PRINT "After that:" PRINT "First variable (MKL-ed string at [BX]) : "; MKL$(a&) PRINT "Second variable(integer at [BX+5]) : "; HEX$(b%) PRINT "Third variabele( long at [BX+7]) : "; HEX$(c&) PRINT "The control values of string, int and long are :"; : COLOR 0, 7: PRINT test.astring; " "; HEX$(test.ainteger); " "; HEX$(test.along) COLOR 7, 0 END SUB