|Dͻ
|D |5The Happy Hacker |D
|Dͼ

^C^1Bits 'N PC's
^Cby
^CGeorge Leritte

   This column explores assembly language subroutines and how to use them in 
BASIC programs.  There are two major reasons to use assembly language --  1) 
speed;  and 2)  to accomplish something you ordinarily wouldn't be able to do.  
We'll explore the second reason this time. 

  How many times have you needed to clear half of the screen or to scroll part 
of the screen?  To do this in BASIC requires laboriously-coded PRINT statements 
to put spaces to clear the section.  The alternative to this headache is just 
not to do it at all.  Well, a little reading can turn up a better answer. 

   In the hardware reference manual is a section on the PC's ROM BIOS driver 
services.  This section looks like gibberish to the non-assembly language 
programmer.  The first time I looked at mine, it was definitely a foreign 
language.  But the solutions are there.  Consider the structure of 8086/8088 
assembly language.  There are four 16-bit general purpose registers, called AX, 
BX, CX, and DX. Each register can also be described as a pair of eight-bit 
registers.  The left hand byte is the High byte and the right hand byte is the 
Low.  Thus, AX can be referenced as AH and AL, BX as BH and BL, CX as CH and 
CL, and DX as DH and DL.  This is all we need to know for now. 

  The manual talks about video services.  You will see an 'Int 10H' that has a 
list of functions under it.  These functions are listed as 'AH = xxH' where xx 
is a hexadecimal number.  Under each function is a list that looks something 
like this (e. g. for function 6 -- scroll window up):

^1AH = 06H
^1AL = number of lines to scroll (if zero, entire window is cleared)
^1BH = attribute for cleared area
^1CH = upper left hand column of window
^1CL = upper left hand row of window
^1DH = lower right hand column of window
^1DL = lower right hand row of window

This is the gibberish I referred to earlier.  What this means is that the 
registers listed above should contain the information before an assembly 
language INT 10H is called.  This ROM BIOS video service can be used to scroll 
up a portion of the screen or to clear a portion of the screen.  Its scroll 
down companion is function number 7 (AH = 07H).  With these two functions, we 
can do some interesting effects with the PC's screen.

  The assembly language listing for such a routine looks something like this 
(the H after a number means that number is hexadecimal): 

^1     MOV AH, 7        ;function 7 
^1     MOV AL, 0        ;clear window 
^1     MOV BH, 70H      ;normal video attribute 
^1     MOV CH, 0        ;upper left column 
^1     MOV CL, 0        ;upper left row 
^1     MOV DH, 24       ;lower right column 
^1     MOV DL, 39       ;lower right row 
^1     INT 10H 

   This clears a window in reverse video from the upper left corner to the 
middle of the bottom of the screen in 80 column mode.  Because we're using this 
routine in a BASIC program, it will look a little different.  First, BASIC 
counts the rows and columns starting from one, but assembly language starts 
from zero.  Second, due to the way we're storing and using the routine in the 
program it is easier to load the registers this way: 

^1     NOP              ;integer spacer
^1     MOV AX, 700H
^1     NOP
^1     MOV BX, 7000H
^1     NOP
^1     MOV CX, 0
^1     NOP
^1     MOV DX 1827H
^1     SUB CX,0101H     ;this subtracts 1 from the upper left row and column
^1     SUB DX,0101H     ;this subtracts 1 from the lower right row and column 
^1     INT 10H
^1     RETF

   We could enter this with a word processor, enter the necessary support  
statements and run the macro assembler on the file, then link it and then 
convert it to a binary file and then decode the binary file.  But we will use 
the assembler from DEBUG.COM.  Type debug <cr>, then type 'a' <cr> then the 
statements above.  After the last statement, enter <cr> by itself and you're 
back in DEBUG.  Type 'u100' and note the hex number to the left of 'RETF' - 
'CB' (That's our end byte.  RETF means 'return far'.  This always ends our 
assembly language subroutines.)

   Type 'd100' and look at the letters and numbers in the center of the screen.
This memory dump moves horizontally across the screen.  Write them down until 
you get to the 'CB'.  These are the machine language equivalents of our 
assembly routine. In BASIC, type a data statement with these letters and 
numbers.  Count them.  Our routine takes 27 bytes. 

   We will store the routine in an integer array.  Since each integer takes 2 
bytes, add a 0 to the end of the data statement to bring the total to 28 bytes.
Now, dimension your array carefully.  The number is 13, not 14, because array 
indexes start at 0, not 1.  Load the data into the array with the routine below 
(lines 30-60).  Create your subroutine (lines 500-560) then build the rest of 
the program. 
       
^110 DIM SCROLL%(13)
^120 DATA 90,B8,0,6,90,BB,7,0,90,B9,1,1,90,BA,50,37,81,E9,1,1,81,EA,1,1,CD,10,CB,0
^130 FOR I=0 TO 13
^140 READ A$,B$ : C$ = CHR$(VAL("&H"+A$)) + CHR$(VAL("&H"+B$))
^150 SCROLL%(I) = CVI(C$)
^160 NEXT I
^170 REM  ATTRibute = 256 * Background_Color + Foreground_Color
^180 KEY OFF : CLS
^1100 AH = 7 : AL = 0 : ATTR = &H70 : CH = 1 : CL = 1 : DH = 25 : DL = 40
^1110 GOSUB 500
^1120 A$=INPUT$(1)
^1500 REM machine language subroutine preparation and call
^1510 SCROLL%(1) = AH * 256 + AL :
^1520 SCROLL%(3) = ATTR * 256 :
^1530 SCROLL%(5) = CH * 256 + CL :
^1540 SCROLL%(7) = DH * 256 + DL :
^1550 SUBROUT = VARPTR(SCROLL%(0)) : CALL SUBROUT
^1560 RETURN

   The program, SCROLL.BAS, is included on the disk.  It can be run from outside
of Big Blue Disk's menu, and illustrates some of the possible uses of this 
assembly language subroutine.
