'#Direkt Video Write / PowerBasic 3.0 $IF 0 ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß PROGRAM: asmprint.bas AUTHOR: Erik Olson DATE: 2/27/93 REPLACES: QPRINT.ASM VERSION: 1 COMPILER: PowerBASIC 3.x PURPOSE: performs a direct video write, demonstrates inline assembler ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ $ENDIF DECLARE SUB GetStrLoc() 'we have to declare this because we need it A$="THIS IS A STRING BEING WRITTEN TO THE SCREEN REALLY FAST" Ver%=15 ' vertical position to write on the screen Hor%=10 ' horizontal position to write Attr%=&H71 ' blue text on white (7 = background, 1 = foreground) CLS CALL QPRINT(Ver%, Hor%,A$,Attr%) ' call out ASM subroutine SUB QPRINT(byval ver%, byval Hor%, A$, byval Attr%) ' QPRINT is for doing a direct video write on a color monitor ! push ds ;save the good stuff ! push di ;because we're gonna destroy it ! push si ! mov ax,ver% ;put vertical position into ax '************************************************************************ 'if we had not passed ver% BYVAL then it would be the ADDRESS and not the 'actual value and it would be harder to play with. '************************************************************************ ! mov dl,160 ;put 160 into dl ! mul dl ;multiply ax by 160 (Mul only multiplies AX) ! sub ax,160 ;subtract 160 from ax ! push ax ;save it ! mov ax,Hor% ;put horizontal position into ax ! mov dl,2 ;put 2 into dl ! mul dl ;multiply ax by 2 (mul only works on AX) ! mov bx,ax ;put horizontal offset into bx ! pop ax ;put vertical into ax ! add ax,bx ;add them together ! dec ax ! dec ax ;and subtract 2 '************************************************************************* 'we had to do all that stuff in order to calculate how many bytes from the 'beginning of video ram our data is going to begin at. the formula is '(ver*160)-160 + (hor*2) - 2. I didn't know that MUL will only multiply 'the AX register with the operand. I thought you needed 2 operands. Boy 'it took me a long time to figure that one out! Party. '************************************************************************* ! push ax ;push the value ! pop di ;pop it into di register ! mov ax,&HB800 ;and put video segment into ax ! push ax ;and push it ! pop es ;and pop it into es '************************************************************************* 'once we know how many bytes offset from the start of video ram our string 'is going to be written at, we put the number into DI. Then we set ES to 'equal &HB800 so now we can read or write from video ram by referring to 'it as ES:[DI]. Of course, now we need a source of data to write to video 'so now we have to get out hands on the data contained in A$ '************************************************************************* ! lds si,a$ ;get the address if a$'s handle '************************************************************************* 'the literal value of A$ when used in assembler is actually a pointer to 'the string handle. with LDS SI,A$ we can put the load the segment and 'offset of the handle into DS:[SI]. Then we grab the handle and put it 'into AX for pushing, and we call GETSTRLOC, which is an internal PB 'subroutine that finds the address of a string. That's why we declared 'it up top. '************************************************************************* ! mov ax,ds:[si] ;put the handle into ax ! push ax ;push the handle call GetStrLoc 'find the location of the string ! push ax ;push the offset ! push dx ;push the segment ! pop ds ;pop the segment ! pop si ;pop the offset (cx already contains length) '************************************************************************* 'GETSTRLOC takes the handle that we pushed and finds the string, putting 'the segment into DX and the offset into AX. In order to address the 'memory, we need it to be in DS:[SI] (for our purposes). GETSTRLOC also 'places the length of the string in CX, which is perfect, because we need 'it there for the LOOP instruction. '************************************************************************* ! mov ah,attr% ;the color attribute will be needed forloop: 'a label for looping ! mov al,ds:[si] ;get a character from the string ! mov es:[di],al ;put the character into video ram ! inc di ;increment the di pointer ! mov es:[di],ah ;poke the attribute into vidram ! inc di ;increment to the next vidram position ! inc si ;increment to the next string position ! loop forloop ;loop until cx=0 '************************************************************************* 'LOOP is just like a FOR..NEXT loop and it iterates whatever number of times 'is in the CX register, decrementing it as it loops. When CX=0 it terminates 'the loop and goes on. Bonus. During this loop we increment our offsets 'and copy the bytes from the string into video RAM, adding the color 'attribute as we go along. '************************************************************************* ! pop si ;restore the good stuff ! pop di ! pop ds 'abadee abadee abadee a a a tha tha that's all folks! END SUB