; Pgm11_1.asm ; ; Screen Aids. ; ; This program provides some useful screen manipulation routines ; that let you do things like position the cursor, save and restore ; the contents of the display screen, clear the screen, etc. ; ; This program is not very efficient. It was written to demonstrate ; parameter passing, use of local variables, and direct conversion of ; loops to assembly language. There are far better ways of doing ; what this program does (running about 5-10x faster) using the 80x86 ; string instructions. .xlist include stdlib.a includelib stdlib.lib .list .386 ;Comment out these two statements option segment:use16 ; if you are not using an 80386. ; ScrSeg- This is the video screen's segment address. It should be ; B000 for mono screens and B800 for color screens. ScrSeg = 0B800h dseg segment para public 'data' XPosn word ? ;Cursor X-Coordinate (0..79) YPosn word ? ;Cursor Y-Coordinate (0..24) ; The following array holds a copy of the initial screen data. SaveScr word 25 dup (80 dup (?)) dseg ends cseg segment para public 'code' assume cs:cseg, ds:dseg ; Capture- Copies the data on the screen to the array passed ; by reference as a parameter. ; ; procedure Capture(var ScrCopy:array[0..24,0..79] of word); ; var x,y:integer; ; begin ; ; for y := 0 to 24 do ; for x := 0 to 79 do ; SCREEN[y,x] := ScrCopy[y,x]; ; end; ; ; ; Activation record for Capture: ; ; | | ; | Previous stk contents | ; ------------------------- ; | ScrCopy Seg Adrs | ; -- -- ; | ScrCopy offset Adrs | ; ------------------------- ; | Return Adrs (near) | ; ------------------------- ; | Old BP | ; ------------------------- <- BP ; | X coordinate value | ; ------------------------- ; | Y coordinate value | ; ------------------------- ; | Registers, etc. | ; ------------------------- <- SP ScrCopy_cap textequ <dword ptr [bp+4]> X_cap textequ <word ptr [bp-2]> Y_cap textequ <word ptr [bp-4]> Capture proc push bp mov bp, sp sub sp, 4 ;Allocate room for locals. push es push ds push ax push bx push di mov bx, ScrSeg ;Set up pointer to SCREEN mov es, bx ; memory (ScrSeg:0). lds di, ScrCopy_cap ;Get ptr to capture array. mov Y_cap, 0 YLoop: mov X_cap, 0 XLoop: mov bx, Y_cap imul bx, 80 ;Screen memory is a 25x80 array add bx, X_cap ; stored in row major order add bx, bx ; with two bytes per element. mov ax, es:[bx] ;Read character code from screen. mov ds:[di][bx], ax ;Store away into capture array. inc X_Cap ;Repeat for each character on this cmp X_Cap, 80 ; row of characters (each character jb XLoop ; in the row is two bytes). inc Y_Cap ;Repeat for each row on the screen. cmp Y_Cap, 25 jb YLoop pop di pop bx pop ax pop ds pop es mov sp, bp pop bp ret 4 Capture endp ; Fill- Copies array passed by reference onto the screen. ; ; procedure Fill(var ScrCopy:array[0..24,0..79] of word); ; var x,y:integer; ; begin ; ; for y := 0 to 24 do ; for x := 0 to 79 do ; ScrCopy[y,x] := SCREEN[y,x]; ; end; ; ; ; Activation record for Fill: ; ; | | ; | Previous stk contents | ; ------------------------- ; | ScrCopy Seg Adrs | ; -- -- ; | ScrCopy offset Adrs | ; ------------------------- ; | Return Adrs (near) | ; ------------------------- ; | Old BP | ; ------------------------- <- BP ; | X coordinate value | ; ------------------------- ; | Y coordinate value | ; ------------------------- ; | Registers, etc. | ; ------------------------- <- SP ScrCopy_fill textequ <dword ptr [bp+4]> X_fill textequ <word ptr [bp-2]> Y_fill textequ <word ptr [bp-4]> Fill proc push bp mov bp, sp sub sp, 4 push es push ds push ax push bx push di mov bx, ScrSeg ;Set up pointer to SCREEN mov es, bx ; memory (ScrSeg:0). lds di, ScrCopy_fill ;Get ptr to data array. mov Y_Fill, 0 YLoop: mov X_Fill, 0 XLoop: mov bx, Y_Fill imul bx, 80 ;Screen memory is a 25x80 array add bx, X_Fill ; stored in row major order add bx, bx ; with two bytes per element. mov ax, ds:[di][bx] ;Store away into capture array. mov es:[bx], ax ;Read character code from screen. inc X_Fill ;Repeat for each character on this cmp X_Fill, 80 ; row of characters (each character jb XLoop ; in the row is two bytes). inc Y_Fill ;Repeat for each row on the screen. cmp Y_Fill, 25 jb YLoop pop di pop bx pop ax pop ds pop es mov sp, bp pop bp ret 4 Fill endp ; Scroll_up- Scrolls the screen up on line. It does this by copying the second line ; to the first, the third line to the second, the fourth line to the third, ; etc. ; ; procedure Scroll_up; ; var x,y:integer; ; begin ; for y := 1 to 24 do ; for x := 0 to 79 do ; SCREEN[Y-1,X] := SCREEN[Y,X]; ; end; ; ; Activation record for Scroll_up: ; ; | | ; | Previous stk contents | ; ------------------------- ; | Return Adrs (near) | ; ------------------------- ; | Old BP | ; ------------------------- <- BP ; | X coordinate value | ; ------------------------- ; | Y coordinate value | ; ------------------------- ; | Registers, etc. | ; ------------------------- <- SP X_su textequ <word ptr [bp-2]> Y_su textequ <word ptr [bp-4]> Scroll_up proc push bp mov bp, sp sub sp, 4 ;Make room for X, Y. push ds push ax push bx mov ax, ScrSeg mov ds, ax mov Y_su, 0 su_Loop1: mov X_su, 0 su_Loop2: mov bx, Y_su ;Compute index into screen imul bx, 80 ; array. add bx, X_su add bx, bx ;Remember, this is a word array. mov ax, ds:[bx+160] ;Fetch word from source line. mov ds:[bx], ax ;Store into dest line. inc X_su cmp X_su, 80 jb su_Loop2 inc Y_su cmp Y_su, 80 jb su_Loop1 pop bx pop ax pop ds mov sp, bp pop bp ret Scroll_up endp ; Scroll_dn- Scrolls the screen down one line. It does this by copying the 24th line ; to the 25th, the 23rd line to the 24th, the 22nd line to the 23rd, ; etc. ; ; procedure Scroll_dn; ; var x,y:integer; ; begin ; for y := 23 downto 0 do ; for x := 0 to 79 do ; SCREEN[Y+1,X] := SCREEN[Y,X]; ; end; ; ; Activation record for Scroll_dn: ; ; | | ; | Previous stk contents | ; ------------------------- ; | Return Adrs (near) | ; ------------------------- ; | Old BP | ; ------------------------- <- BP ; | X coordinate value | ; ------------------------- ; | Y coordinate value | ; ------------------------- ; | Registers, etc. | ; ------------------------- <- SP X_sd textequ <word ptr [bp-2]> Y_sd textequ <word ptr [bp-4]> Scroll_dn proc push bp mov bp, sp sub sp, 4 ;Make room for X, Y. push ds push ax push bx mov ax, ScrSeg mov ds, ax mov Y_sd, 23 sd_Loop1: mov X_sd, 0 sd_Loop2: mov bx, Y_sd ;Compute index into screen imul bx, 80 ; array. add bx, X_sd add bx, bx ;Remember, this is a word array. mov ax, ds:[bx] ;Fetch word from source line. mov ds:[bx+160], ax ;Store into dest line. inc X_sd cmp X_sd, 80 jb sd_Loop2 dec Y_sd cmp Y_sd, 0 jge sd_Loop1 pop bx pop ax pop ds mov sp, bp pop bp ret Scroll_dn endp ; GotoXY- Positions the cursor at the specified X, Y coordinate. ; ; procedure gotoxy(x,y:integer); ; begin ; BIOS(posnCursor,x,y); ; end; ; ; Activation record for GotoXY ; ; | | ; | Previous stk contents | ; ------------------------- ; | X coordinate value | ; ------------------------- ; | Y coordinate value | ; ------------------------- ; | Return Adrs (near) | ; ------------------------- ; | Old BP | ; ------------------------- <- BP ; | Registers, etc. | ; ------------------------- <- SP X_gxy textequ <byte ptr [bp+6]> Y_gxy textequ <byte ptr [bp+4]> GotoXY proc push bp mov bp, sp push ax push bx push dx mov ah, 2 ;Magic BIOS value for gotoxy. mov bh, 0 ;Display page zero. mov dh, Y_gxy ;Set up BIOS (X,Y) parameters. mov dl, X_gxy int 10h ;Make the BIOS call. pop dx pop bx pop ax mov sp, bp pop bp ret 4 GotoXY endp ; GetX- Returns cursor X-Coordinate in the AX register. GetX proc push bx push cx push dx mov ah, 3 ;Read X, Y coordinates from mov bh, 0 ; BIOS int 10h mov al, dl ;Return X coordinate in AX. mov ah, 0 pop dx pop cx pop bx ret GetX endp ; GetY- Returns cursor Y-Coordinate in the AX register. GetY proc push bx push cx push dx mov ah, 3 mov bh, 0 int 10h mov al, dh ;Return Y Coordinate in AX. mov ah, 0 pop dx pop cx pop bx ret GetY endp ; ClearScrn- Clears the screen and positions the cursor at (0,0). ; ; procedure ClearScrn; ; begin ; BIOS(Initialize) ; end; ClearScrn proc push ax push bx push cx push dx mov ah, 6 ;Magic BIOS number. mov al, 0 ;Clear entire screen. mov bh, 07 ;Clear with black spaces. mov cx, 0000 ;Upper left corner is (0,0) mov dl, 79 ;Lower X-coordinate mov dh, 24 ;Lower Y-coordinate int 10h ;Make the BIOS call. push 0 ;Position the cursor to (0,0) push 0 ; after the call. call GotoXY pop dx pop cx pop bx pop ax ret ClearScrn endp ; A short main program to test out the above: Main proc mov ax, dseg mov ds, ax mov es, ax meminit ; Save the screen as it looks when this program is run. push seg SaveScr push offset SaveScr call Capture call GetX mov XPosn, ax call GetY mov YPosn, ax ; Clear the screen to prepare for our stuff. call ClearScrn ; Position the cursor in the middle of the screen and print some stuff. push 30 ;X value push 10 ;Y value call GotoXY print byte "Screen Manipulatation Demo",0 push 30 push 11 call GotoXY print byte "Press any key to continue",0 getc ; Scroll the screen up two lines call Scroll_up call Scroll_up getc ;Scroll the screen down four lines: call Scroll_dn call Scroll_dn call Scroll_dn call Scroll_dn getc ; Restore the screen to what it looked like prior to this call. push seg SaveScr push offset SaveScr call Fill push XPosn push YPosn call GotoXY Quit: ExitPgm ;DOS macro to quit program. Main endp cseg ends sseg segment para stack 'stack' stk byte 1024 dup ("stack ") sseg ends zzzzzzseg segment para public 'zzzzzz' LastBytes byte 16 dup (?) zzzzzzseg ends end Main