mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-18 17:36:11 +00:00
454 lines
15 KiB
NASM
454 lines
15 KiB
NASM
|
; BROWSE.ASM -- Full Screen File Pager
|
|||
|
; ====================================
|
|||
|
|
|||
|
CSEG Segment
|
|||
|
Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
|
|||
|
Org 0080h
|
|||
|
Parameter Label Byte
|
|||
|
Org 0100h
|
|||
|
Entry: Jmp Begin
|
|||
|
|
|||
|
; All Data
|
|||
|
; --------
|
|||
|
|
|||
|
db 'ATTR='
|
|||
|
Attribute db 0 ; Current screen attribute
|
|||
|
db 'SHIFT='
|
|||
|
ShiftHoriz db 8 ; Horizontal shift screen default
|
|||
|
DosVersionFail db 'Requires DOS 2.0 or above$'
|
|||
|
NoSpaceFail db 'Not enough memory$'
|
|||
|
FileFail db 'File Not Found$'
|
|||
|
ScreenFail db 'Unsupported video mode$'
|
|||
|
Delimiters db 9,' ,;=/' ; Delimiters in parameter
|
|||
|
FileHandle dw ? ; Use for saving file handle
|
|||
|
WSMode db 0FFh ; AND value for non-WordStar mode
|
|||
|
LineLength db ? ; Length of line (from BIOS)
|
|||
|
NumberLines db 25,0 ; Number of lines (check EGA BIOS)
|
|||
|
ScreenSize dw ? ; Size of screen in bytes
|
|||
|
CheckRetrace db 1 ; Flag zero if EGA or MONO used
|
|||
|
Addr6845 dw ? ; Could use for retrace check
|
|||
|
ScreenAddr Label DWord ; Address of screen
|
|||
|
ScreenOff dw 0 ; Higher for non-page 0
|
|||
|
ScreenSeg dw 0B800h ; Set to B000h for Mono Mode 7
|
|||
|
ScreenStart dw ? ; Points within buffer
|
|||
|
EndOfFile dw ? ; Points within buffer
|
|||
|
FileOffset dw -1, -1 ; Address within file of buffer data
|
|||
|
HorizOffset dw 0 ; Horizontal offset for display
|
|||
|
RightMargin dw 0 ; Right margin for offset display
|
|||
|
Dispatch dw Home, Up, PgUp, Dummy, Left
|
|||
|
dw Dummy, Right, Dummy, End, Down, PgDn
|
|||
|
|
|||
|
; Check DOS Version for 2.0 or above
|
|||
|
; ----------------------------------
|
|||
|
|
|||
|
Begin: Cld ; All string directions forward
|
|||
|
Mov AH,30h
|
|||
|
Int 21h ; Get DOS Version Number
|
|||
|
Cmp AL,2 ; Check for 2.0 or later
|
|||
|
Jae DOSVerOK
|
|||
|
Mov DX,Offset DOSVersionFail
|
|||
|
ErrorExit: Mov AH,9 ; Write error message
|
|||
|
Int 21h
|
|||
|
Int 20h
|
|||
|
|
|||
|
; Parse Command Line to get File Name and WordStar flag
|
|||
|
; -----------------------------------------------------
|
|||
|
|
|||
|
DOSVerOK: Mov SI,1 + Offset Parameter ; Points to parameter
|
|||
|
NameSearch: Lodsb ; Get byte
|
|||
|
Cmp AL,13 ; Check if carriage return
|
|||
|
Jz NoFileFound ; If so, no file name
|
|||
|
Mov DI,Offset Delimiters ; String of delimiters
|
|||
|
Mov CX,5 ; Number of delimiters (no /)
|
|||
|
Repne Scasb ; See if a match
|
|||
|
Je NameSearch ; If a delimiter, keep looking
|
|||
|
Mov DX,SI ; Otherwise found file name
|
|||
|
Dec DX ; Points to beginning of it
|
|||
|
EndSearch: Lodsb ; Get next byte
|
|||
|
Cmp AL,13 ; See if carriage return
|
|||
|
Je GotFileEnd ; If so, we're all done
|
|||
|
Mov DI,Offset Delimiters ; String of delimiters
|
|||
|
Mov CX,6 ; Number (including /)
|
|||
|
Repne Scasb ; See if a match
|
|||
|
Jne EndSearch ; If not, still in file name
|
|||
|
Mov Byte Ptr [SI - 1],0 ; If so, mark end of file name
|
|||
|
Jcxz GotFlag ; If slash, check for W
|
|||
|
Jmp EndSearch ; Or continue flag search
|
|||
|
GotFlag: Lodsb ; Get byte after / flag
|
|||
|
Or AL,20h ; Uncapitalize
|
|||
|
Cmp AL,'w' ; See if w for WordStar mode
|
|||
|
Jnz GotFileEnd ; If not, just ignore it
|
|||
|
Mov [WSMode],7Fh ; AND value for WordStar
|
|||
|
|
|||
|
; Open the File
|
|||
|
; -------------
|
|||
|
|
|||
|
GotFileEnd: Mov Byte Ptr [SI - 1],0 ; Mark end of file name
|
|||
|
; DX still points to name
|
|||
|
Mov AX,3D00h ; Open file for reading
|
|||
|
Int 21h ; by calling DOS
|
|||
|
Jnc GotTheFile ; If no error, continue
|
|||
|
NoFileFound: Mov DX,Offset FileFail ; Otherwise print a message
|
|||
|
Jmp ErrorExit
|
|||
|
GotTheFile: Mov [FileHandle],AX ; Save the file handle
|
|||
|
|
|||
|
; Get Screen Mode Information from BIOS Data Area
|
|||
|
; -----------------------------------------------
|
|||
|
|
|||
|
Push ES ; Save register
|
|||
|
Sub AX,AX
|
|||
|
Mov ES,AX ; Set ES to 0 (BIOS Data)
|
|||
|
Mov AL,ES:[0449h] ; Current Video Mode
|
|||
|
Cmp AL,3 ; Check if Color Alpha
|
|||
|
Jbe DisplayOK ; Continue if so
|
|||
|
Cmp AL,7 ; Check if monochrome display
|
|||
|
Je Monochrome ; If so, branch
|
|||
|
Mov DX,Offset ScreenFail ; We can't handle graphics
|
|||
|
Jmp ErrorExit ; So print an error message
|
|||
|
Monochrome: Mov [ScreenSeg],0B000h ; Use Monochrome Segment
|
|||
|
Mov [CheckRetrace],0 ; Don't have to check retrace
|
|||
|
DisplayOK: Mov AL,ES:[044Ah] ; Number of Columns
|
|||
|
Mov [LineLength],AL ; Save it
|
|||
|
Mov AX,ES:[044Eh] ; Offset into screen buffer
|
|||
|
Mov [ScreenOff],AX ; Save it
|
|||
|
Mov AX,ES:[0463h] ; Address of 6845 Regsiter
|
|||
|
Mov [Addr6845],AX ; Save it
|
|||
|
Push ES
|
|||
|
Sub DL,DL ; Set Rows to zero first
|
|||
|
Sub BH,BH
|
|||
|
Mov AX,1130h ; EGA BIOS: Get Information
|
|||
|
Int 10h
|
|||
|
Pop ES
|
|||
|
Or DL,DL ; Check if DL is still zero
|
|||
|
Jz NoEGA ; If so, skip rest of stuff
|
|||
|
Inc DL
|
|||
|
Mov [NumberLines],DL ; Save Number of Lines
|
|||
|
Test Byte Ptr ES:[0487h],4 ; Check if must check retrace
|
|||
|
Jnz NoEGA
|
|||
|
Mov [CheckRetrace],0 ; EGA says we don't have to
|
|||
|
NoEGA: Mov BH,ES:[0462h] ; Get Current Page (use later)
|
|||
|
Pop ES
|
|||
|
Mov AL,[LineLength] ; Length of each line
|
|||
|
Mul [NumberLines] ; Total chars on screen
|
|||
|
Add AX,AX ; Double for attributes
|
|||
|
Mov [ScreenSize],AX ; And Save it
|
|||
|
|
|||
|
; See if enough memory is left
|
|||
|
; ----------------------------
|
|||
|
|
|||
|
Add AX,Offset ScreenHold ; Add ScreenSize to code end
|
|||
|
Add AX,256 ; Add a little stack room
|
|||
|
Cmp AX,SP ; Check against stack pointer
|
|||
|
Jbe GotEnufMemory ; Continue if OK
|
|||
|
Mov DX,Offset NoSpaceFail ; Otherwise end program
|
|||
|
Jmp ErrorExit ; with error messae
|
|||
|
|
|||
|
; Get Current Screen Attribute
|
|||
|
; ----------------------------
|
|||
|
|
|||
|
GotEnufMemory: Cmp [Attribute],0 ; Check if attribute pre-set
|
|||
|
Jnz GotAttribute ; If so, move on
|
|||
|
Mov DL,' ' ; Write out a byte
|
|||
|
Mov AH,2 ; using DOS
|
|||
|
Int 21h
|
|||
|
Mov AL,8 ; Now backspace
|
|||
|
Mov AH,14 ; using BIOS call
|
|||
|
Int 10h
|
|||
|
Mov AH,8 ; Read character & attribute
|
|||
|
Int 10h ; using BIOS call (BH = pg)
|
|||
|
Mov [Attribute],AH ; And save attribute
|
|||
|
|
|||
|
; Save Current Screen
|
|||
|
; -------------------
|
|||
|
|
|||
|
GotAttribute: Mov DX,Offset Terminate ; Set Ctrl-Break exit
|
|||
|
Mov AX,2523h ; to terminate that way
|
|||
|
Int 21h
|
|||
|
Mov DI,Offset ScreenHold ; Destination of screen
|
|||
|
Mov CX,[ScreenSize] ; Size of screen
|
|||
|
Push DS ; Save Source Segment
|
|||
|
Lds SI,[ScreenAddr] ; Get screen address
|
|||
|
Rep Movsb ; Move in the bytes
|
|||
|
Pop DS ; Restore Source Segment
|
|||
|
|
|||
|
; Get Keyboard Key and Decide on Action
|
|||
|
; -------------------------------------
|
|||
|
|
|||
|
Call Home ; Read file in
|
|||
|
Mov [ScreenStart],SI ; Set buffer address
|
|||
|
KeyLoop: Call UpDateScreen ; Write file to screen
|
|||
|
GetKey: Mov AH,8 ; Get key
|
|||
|
Int 21h ; by calling DOS
|
|||
|
Cmp AL,27 ; Check if ESC
|
|||
|
Je Terminate ; If so, terminate
|
|||
|
Cmp AL,0 ; Check if extended
|
|||
|
Jnz GetKey ; If not, try again
|
|||
|
Mov AH,8 ; Get extended code
|
|||
|
Int 21h ; by calling DOS
|
|||
|
Sub AL,71 ; Subtract Home key value
|
|||
|
Jb GetKey ; If below that, not valid
|
|||
|
Cmp AL,(81 - 71) ; Check if above PgDn
|
|||
|
Ja GetKey ; If so, ignore it
|
|||
|
Sub AH,AH ; Zero out top byte
|
|||
|
Add AX,AX ; Double for word access
|
|||
|
Mov BX,AX ; Offset in dispatch table
|
|||
|
Mov SI,[ScreenStart] ; Set current buffer pointer
|
|||
|
Call [Dispatch + BX] ; Do the call
|
|||
|
Mov [ScreenStart],SI ; Set new buffer pointer
|
|||
|
Jmp KeyLoop ; And update the screen
|
|||
|
|
|||
|
; Terminate -- Restore screen and close file
|
|||
|
; ------------------------------------------
|
|||
|
|
|||
|
Terminate: Mov SI,Offset ScreenHold ; Address of Saved Screen
|
|||
|
Les DI,[ScreenAddr] ; Address of Display
|
|||
|
Mov CX,[ScreenSize] ; Number of characters
|
|||
|
Rep Movsb ; Move them back
|
|||
|
Mov BX,[FileHandle] ; Get File Handle
|
|||
|
Mov AH,3Eh ; Close File
|
|||
|
Int 21h
|
|||
|
Int 20h ; Terminate
|
|||
|
|
|||
|
; Cursor Key Routines -- Home Key
|
|||
|
; -------------------------------
|
|||
|
|
|||
|
Home: Sub BX,BX ; For zeroing out values
|
|||
|
Mov AX,[FileOffset] ; Check if read in file
|
|||
|
Or AX,[FileOffset + 2]
|
|||
|
Mov [FileOffset],BX ; Zero out file address
|
|||
|
Mov [FileOffset + 2],BX
|
|||
|
Mov [HorizOffset],BX ; Zero out horizontal offset
|
|||
|
Mov SI,Offset Buffer ; Reset buffer pointer
|
|||
|
Jz Dummy ; Skip file read if in already
|
|||
|
Mov DX,Offset Buffer ; Area to read file in
|
|||
|
Mov CX,32768 ; Number of bytes to read
|
|||
|
Call FileRead ; Read in file
|
|||
|
Dummy: Ret
|
|||
|
|
|||
|
; Up and PgUp Keys
|
|||
|
; ----------------
|
|||
|
|
|||
|
Up: Call GetPrevChar ; Get previous char in buffer
|
|||
|
Jc UpDone ; If none available, finish
|
|||
|
UpLoop: Call GetPrevChar ; Get previous char again
|
|||
|
Jc UpDone ; if none, we're done
|
|||
|
Cmp AL,10 ; Check if line feed
|
|||
|
Jnz UpLoop ; If not, try again
|
|||
|
Call GetNextChar ; Get char after line feed
|
|||
|
UpDone: Ret
|
|||
|
|
|||
|
PgUp: Mov CX,Word Ptr [NumberLines] ; Number of lines
|
|||
|
PgUpLoop: Call Up ; Do UP that many times
|
|||
|
Loop PgUpLoop
|
|||
|
Ret
|
|||
|
|
|||
|
; Left and Right Keys
|
|||
|
; -------------------
|
|||
|
|
|||
|
Left: Mov [HorizOffset],0 ; Reset Horizontal Offset
|
|||
|
Ret
|
|||
|
|
|||
|
Right: Mov AL,[ShiftHoriz] ; Get places to shift
|
|||
|
Sub AH,AH
|
|||
|
Add [HorizOffset],AX ; Move that many right
|
|||
|
Ret
|
|||
|
|
|||
|
; End, Down, and PgDn Keys
|
|||
|
; ------------------------
|
|||
|
|
|||
|
End: Mov BX,SI ; Save buffer pointer
|
|||
|
Call PgDn ; Go page down
|
|||
|
Cmp BX,SI ; Check if we did so
|
|||
|
Jnz End ; If so, do it again
|
|||
|
Ret
|
|||
|
|
|||
|
Down: Call GetNextChar ; Get next character
|
|||
|
Jc NoMoreDown ; If no more, we're done
|
|||
|
DownLoop: Call GetNextChar ; Get one again
|
|||
|
Jc UpLoop ; If no more, find prev LF
|
|||
|
Cmp AL,10 ; See if line feed
|
|||
|
Jnz DownLoop ; If not, continue
|
|||
|
NoMoreDown: Ret
|
|||
|
|
|||
|
PgDn: Mov CX,Word Ptr [NumberLines] ; Number of lines
|
|||
|
PgDnLoop: Call Down ; Do DOWN that many times
|
|||
|
Loop PgDnLoop
|
|||
|
Ret
|
|||
|
|
|||
|
; Update Screen
|
|||
|
; -------------
|
|||
|
|
|||
|
UpdateScreen: Push ES
|
|||
|
Mov SI,[ScreenStart] ; Address of data in buffer
|
|||
|
Les DI,[ScreenAddr] ; Address of display
|
|||
|
Mov CX,ScreenSize ; Number of bytes in screen
|
|||
|
Shr CX,1 ; Half for number of chars
|
|||
|
Mov AL,' ' ; Will blank screen
|
|||
|
Mov AH,[Attribute] ; With screen attribute
|
|||
|
Rep Stosw ; Blank it
|
|||
|
Mov AL,[LineLength] ; Length of display line
|
|||
|
Sub AH,AH
|
|||
|
Add AX,[HorizOffset] ; Add Horizontal Offset
|
|||
|
Mov [RightMargin],AX ; That's right display margin
|
|||
|
Sub DL,DL ; Line Number
|
|||
|
LineLoop: Sub BX,BX ; Column Number
|
|||
|
Mov AL,[LineLength] ; Use Line Length
|
|||
|
Mul DL ; and Line Number
|
|||
|
Add AX,AX ; to recalculate
|
|||
|
Mov DI,AX ; display destination
|
|||
|
Add DI,[ScreenOff] ; Add beginning address
|
|||
|
CharLoop: Call GetNextChar ; Get next character
|
|||
|
Jc EndOfScreen ; If no more, we're done
|
|||
|
And AL,[WSMode] ; Will be 7Fh for WordStar
|
|||
|
Cmp AL,13 ; Check for carriage return
|
|||
|
Je CharLoop ; Do nothing if so
|
|||
|
Cmp AL,10 ; Check for line feed
|
|||
|
Je LineFeed ; Do routine if so
|
|||
|
Cmp AL,9 ; Check for tab
|
|||
|
Je Tab ; Do routine if so
|
|||
|
Mov CX,1 ; Just 1 char to display
|
|||
|
PrintChar: Cmp BX,[HorizOffset] ; See if we can print it
|
|||
|
Jb NoPrint
|
|||
|
Cmp BX,[RightMargin] ; See if within margin
|
|||
|
Jae NoPrint
|
|||
|
Mov AH,[Attribute] ; Attribute for display
|
|||
|
Cmp [CheckRetrace],0 ; See if must stop snow
|
|||
|
Jz WriteIt ; If not, skip retrace wait
|
|||
|
Push BX
|
|||
|
Push DX
|
|||
|
Mov BX,AX ; Save character and attribute
|
|||
|
Mov DX,[Addr6845] ; Set up I/O address
|
|||
|
Add DX,6
|
|||
|
RetraceWait1: In AL,DX ; Check until
|
|||
|
Shr AL,1 ; vertical retrace
|
|||
|
Jc RetraceWait1 ; ends
|
|||
|
Cli ; Clear interrupts
|
|||
|
RetraceWait2: In AL,DX ; Check until
|
|||
|
Shr AL,1 ; vertical retrace
|
|||
|
Jnc RetraceWait2 ; begins
|
|||
|
Mov AX,BX ; Get back character & attr
|
|||
|
Stosw ; Write to display
|
|||
|
Sti ; Enable interrupts again
|
|||
|
Pop DX
|
|||
|
Pop BX
|
|||
|
Jmp Short NoPrint ; Skip around "no snow" write
|
|||
|
WriteIt: Stosw ; Write without retrace wait
|
|||
|
NoPrint: Inc BX ; Bump up line counter
|
|||
|
Loop PrintChar ; Do it CX times
|
|||
|
Jmp CharLoop ; Then go back to top
|
|||
|
Tab: Mov AX,BX ; Current column number
|
|||
|
And AX,07h ; Take lower three bits
|
|||
|
Mov CX,8
|
|||
|
Sub CX,AX ; Subtract from 8
|
|||
|
Mov AL,' ' ; Will print CX blanks
|
|||
|
Jmp PrintChar
|
|||
|
LineFeed: Inc DL ; Next line
|
|||
|
Cmp DL,[NumberLines] ; See if down at bottom
|
|||
|
Jb LineLoop ; If not, continue
|
|||
|
EndOfScreen: Pop ES ; All done -- leave
|
|||
|
Ret
|
|||
|
|
|||
|
; Get Next Character from buffer
|
|||
|
; ------------------------------
|
|||
|
; (Input is SI pointing to buffer, Returns AL, CY if no more)
|
|||
|
|
|||
|
GetNextChar: Cmp SI,[EndOfFile] ; See if at end of file
|
|||
|
Jae NoMoreNext ; If so, no more chars
|
|||
|
Cmp SI,Offset BufferEnd ; See if at end of buffer
|
|||
|
Jb CanGetNext ; If not, just get character
|
|||
|
Push CX ; Otherwise save registers
|
|||
|
Push DX
|
|||
|
Push DI
|
|||
|
Push ES
|
|||
|
Push DS ; Set ES to DS
|
|||
|
Pop ES ; (could be different)
|
|||
|
Mov SI,Offset BufferMid ; Move 2nd buffer half
|
|||
|
Mov DI,Offset Buffer ; to 1st buffer half
|
|||
|
Mov CX,16384
|
|||
|
Sub [ScreenStart],CX ; New buffer pointer
|
|||
|
Rep Movsb ; Move them
|
|||
|
Mov SI,DI ; SI also buffer pointer
|
|||
|
Add [FileOffset],32768 ; Adjust file addr to read
|
|||
|
Adc [FileOffset + 2],0
|
|||
|
Mov DX,Offset BufferMid ; Place to read file
|
|||
|
Mov CX,16384 ; Number of bytes
|
|||
|
Call FileRead ; Read the file
|
|||
|
Sub [FileOffset],16384 ; Now adjust so reflects
|
|||
|
Sbb [FileOffset + 2],0 ; 1st half of buffer
|
|||
|
Pop ES ; Get back registers
|
|||
|
Pop DI
|
|||
|
Pop DX
|
|||
|
Pop CX
|
|||
|
Jmp GetNextChar ; And try again to get char
|
|||
|
CanGetNext: Lodsb ; Get the character
|
|||
|
NoMoreNext: Cmc ; So CY set if no more
|
|||
|
Ret
|
|||
|
|
|||
|
; Get Previous Character from buffer
|
|||
|
; ----------------------------------
|
|||
|
|
|||
|
GetPrevChar: Cmp SI,Offset Buffer ; See if at top of buffer
|
|||
|
Ja CanGetPrev ; If not, just get character
|
|||
|
Mov AX,[FileOffset] ; See if at top of file
|
|||
|
Or AX,[FileOffset + 2]
|
|||
|
Jz AtTopAlready ; If so, can't get anymore
|
|||
|
Push CX ; Save some registers
|
|||
|
Push DX
|
|||
|
Mov SI,Offset Buffer ; Move 1st half of buffer
|
|||
|
Mov DI,Offset BufferMid ; to 2nd half of buffer
|
|||
|
Mov CX,16384
|
|||
|
Add [ScreenStart],CX ; New buffer pointer
|
|||
|
Rep Movsb ; Do the move
|
|||
|
Sub [FileOffset],16384 ; Adjust file addr for read
|
|||
|
Sbb [FileOffset + 2],0
|
|||
|
Mov DX,Offset Buffer ; Area to read file into
|
|||
|
Mov CX,16384 ; Number of bytes
|
|||
|
Call FileRead ; Read the file
|
|||
|
Pop DX ; Get back registers
|
|||
|
Pop CX
|
|||
|
Jmp Short CanGetPrev ; Now get character
|
|||
|
AtTopAlready: Stc ; CY flag set for no more
|
|||
|
Ret
|
|||
|
CanGetPrev: Dec SI ; Move pointer back
|
|||
|
Mov AL,[SI] ; Get the character
|
|||
|
Clc ; CY flag reset for success
|
|||
|
Ret
|
|||
|
|
|||
|
; Read CX bytes from the file into DX buffer
|
|||
|
; ------------------------------------------
|
|||
|
|
|||
|
FileRead: Push AX ; Save some registers
|
|||
|
Push BX
|
|||
|
Push CX
|
|||
|
Push DX
|
|||
|
Mov [EndOfFile],-1 ; Initialize this
|
|||
|
Mov DX,[FileOffset] ; Get file address to read
|
|||
|
Mov CX,[FileOffset + 2]
|
|||
|
Mov BX,[FileHandle] ; Get file Handle
|
|||
|
Sub AL,AL ; Do LSEEK from beginning
|
|||
|
Mov AH,42h ; LSEEK call
|
|||
|
Int 21h
|
|||
|
Pop DX ; Get back destination
|
|||
|
Pop CX ; Get back count
|
|||
|
Mov AH,3Fh ; Read file function call
|
|||
|
Int 21h
|
|||
|
Jnc NoReadError ; If no error, continue
|
|||
|
Sub AX,AX ; Otherwise read zero bytes
|
|||
|
NoReadError: Cmp AX,CX ; See if 32K has been read
|
|||
|
Je GotItAll ; If so, we're home free
|
|||
|
Add AX,DX ; Otherwise add to buffer addr
|
|||
|
Mov [EndOfFile],AX ; And save as end of file
|
|||
|
GotItAll: Pop BX
|
|||
|
Pop AX
|
|||
|
Ret
|
|||
|
|
|||
|
; File Buffer and Screen Hold Areas
|
|||
|
; ---------------------------------
|
|||
|
|
|||
|
Buffer Label Byte ; Area for file reads
|
|||
|
BufferMid equ Buffer + 16384 ; Halfway through it
|
|||
|
BufferEnd equ BufferMid + 16384 ; At end of it
|
|||
|
ScreenHold equ BufferEnd ; Area for holding screen
|
|||
|
CSEG EndS ; End of segment
|
|||
|
End Entry ; Denotes entry point
|
|||
|
|