📄 llascn.asm
字号:
TITLE LLASCN - GW-BASIC Advanced Screen Interface
;***
; LLASCN - GW-BASIC Advanced Screen Interface
;
; Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
; This is one of the sample OEM dependent source code modules
; required to build the GW-BASIC Interpreter or the GW-BASIC
; Compiler for the IBM PC family of computers.
;
; This module contains OEM dependent support for the following:
;
; SHELL Statement (B$SHLSAV and B$SHLRST)
; PCOPY Statement (B$PCOPYS)
;
;******************************************************************************
INCLUDE switch.inc ; feature switches [new]
INCLUDE rmacros.inc
UseSeg _DATA
UseSeg _BSS
UseSeg RT_TEXT
INCLUDE seg.inc
INCLUDE ibmunv.inc
sBegin _DATA
externW b$CurrPSize ;Current page size in paragraphs
externW b$VideoBase ;Current video base
sEnd _DATA
sBegin _BSS
externB b$MaxPage
externB b$BiosMode
externW b$KBDVEC_SAVE ;LLINI - save area for keyboard vector
externW b$CLKVEC_SAVE ;LLINI - save area for clock vector
staticW OLDCS,,1 ;used to save CS when SHELL is executed
staticW ISAV,,6 ;save area for interrupt vectors
sEnd _BSS
sBegin RT_TEXT
ASSUMES CS,RT_TEXT
externD b$OldClkTic ;LLINI - old vector of INT 1CH
externNP B$SCINIT ; initialize screen
externNP B$OutWord ;LLAGRP - write out port of EGA
;***
;B$SHLSAV - Save machine state for a SHELL
;OEM-interface routine
;
;Purpose:
; This routine will be called whenever a process is
; shelled. It saves all the machine dependent configuration
; parameters which may be changed by the shelled process.
; As of now it saves all the screen mode parameters and the
; interrupt vectors.
;
; This is a DOS only routine.
;
;Entry:
; None
;
;Exit:
; PSW.C set will cause a function call error to be declared.
; No attempt will be made to execute the user process.
;
;Uses:
; Per Convention
;
;Preserves:
; AX, BX, CX, DX
;
;Exceptions:
; None
;********************************************************************
cProc B$SHLSAV,<PUBLIC,NEAR>,<AX,BX,DX,ES,DS>
cBegin ;NOTE: exits through
;SAVXT in B$SHLRST
SAVINT ISAV,CLKINT ; save timer interrupt
SAVINT ISAV+4,TIMADR ; save timer control interrupt
SAVINT ISAV+8,KBDINT ; save keyboard interrupt
XOR DX,DX
MOV ES,DX ;[ES] := 0
MOV OLDCS,CS ;save old CS
CLI ;disable interrupts
RSTVEC TMRCTL,ES:TICSAV ;restore 'get ctl on timer INT'
POP DS ;restore DS
PUSH DS ;save DS
XFRINT KYBINT,KBDVEC/4 ;move INT EFH to INT 09H
XFRINT TIMINT,CLKVEC/4 ;move INT F0H to INT 08H
RSTVEC KBDVEC/4,b$KBDVEC_SAVE ;restore INT EF vector
POP DS ;restore seg register
PUSH DS ;save seg register...
RSTVEC CLKVEC/4,b$CLKVEC_SAVE ;restore INT F0 vector
POP DS ;restore seg register
PUSH DS ;save seg register...
JMP SAVXT ;common return for
;B$SHLSAV and B$SHLRST
cEnd <nogen>
PAGE
;***
;B$SHLRST - Restore machine state after a SHELL
;OEM-interface routine
;
;Purpose:
; This routine is called after a shelled process terminates.
; It restores the machine dependent configuration parameters
; saved by B$SHLSAV. If this restoration can not be done,
; the carry flag is set on exit and the runtime will abort
; with the error "Can't continue after SHELL".
;
; This is a DOS only routine.
;
;Entry:
; None
;
;Exit:
; PSW.C set will cause the runtime to abort with a SHELL error
;
;Uses:
; Per Convention
;
;Preserves:
; AX, BX, CX, DX
;
;Exceptions:
; None
;********************************************************************
cProc B$SHLRST,<PUBLIC,NEAR>,<AX,BX,DX,ES,DS>
cBegin
CLI ;disable interrupts
SAVINT CS:b$OldClkTic,TIMADR ; saving int vector 1ch in b$OldClkTic
MOV AX,OLDCS ;[AX] = old CS
CMP AX,[ISAV+2] ;is ISAV+1 same as old CS ?
JNE SHLRS1 ;Brif not
MOV [ISAV+2],CS ;else set it to new CS
SHLRS1:
CMP AX,[ISAV+6] ;is [ISAV+3] same as old CS ?
JNE SHLRS2 ;Brif not
MOV [ISAV+6],CS ;else set it to new CS
SHLRS2:
CMP AX,[ISAV+10] ;is [ISAV+5] same as old CS ?
JNE SHLRS3 ;Brif not
MOV [ISAV+10],CS ;else set it to new CS
SHLRS3:
PUSH DS
POP ES ;[ES] := [DS]
assumes ES,DGROUP
assumes DS,NOTHING
XFRINT KBDVEC/4,KBDINT/4 ;move INT 09H to INT EFH
XFRINT CLKVEC/4,CLKINT/4 ;move INT 04H to INT F0H
RSTVEC TIMINT,ES:ISAV ;restore timer interrupt
RSTVEC TMRCTL,ES:[ISAV+4] ;restore 'get timer ctl interrupt'
RSTVEC KYBINT,ES:[ISAV+8] ;restore keyboard interrupt
PUSH ES
POP DS ; [ds] := [es] i.e., old [ds]
assumes DS,DGROUP
assumes ES,NOTHING
SAVXT: ;exit point for B$SHLSAV
STI
CLC ;indicate no error
cEnd
PAGE
;***
;B$PCOPYS - Support for PCOPY statement
;OEM-interface routine
;
;Purpose:
; This routine provides the support for the PCOPY statement.
; It copies the contents of one screen page (either graphics
; or text) to another.
;
; If the source or destination page numbers are not in the range of
; allowable pages for the current mode as determined by the formula:
;
;
; max_page_allowed = video_memory/page_size - 1
;
;
; then the routine returns with carry set so that an Illegal Function
; Call will be issued.
;
; If the source and destination pages are the same, this routine
; can just return without trying to copy anything.
;
; NOTE: if you are supporting delayed screen initialization,
; B$SCNINT must be called before any changes to the
; screen pages are made.
;
; This is a DOS only routine.
;
;Entry:
; [AX] = source page #
; [CX] = destination page #
;
;Exit:
; PSW.C set indicates a function call error.
;
;Uses:
; Per Convention
;
;Exceptions:
; None
;********************************************************************
cProc B$PCOPYS,<PUBLIC,NEAR>,<SI,DI,DS,ES>
cBegin
CALL B$SCINIT ; initialize screen if not already done
OR CH,AH ; Check if High-bytes zero
STC ; Prepare for error condition
JNZ PCOPY_EXIT ; Brif either arg > 255
MOV CH,AL ; CH = Source page : CX = page values
MOV AL,b$MaxPage ;permitted max-pages for this mode
CMP AL,CH ; Is source-page > maximum allowed?
JB PCOPY_EXIT ; Yes, exit with error : CF = 1
CMP AL,CL ; Is destination-page > max value?
JB PCOPY_EXIT ; Yes - issue error : CF = 1
CMP CL,CH ; Src = Dst?
JE PCOPY_EXIT ; Br - nothing to do
; Get the base address of source & destination pages
MOV BX,b$VideoBase
COPY_PAGES:
; Now, get the page size for this mode
MOV DI,b$CurrPSize ;DI = 128-byte page units
CLD ; Get ready for auto-increment
; Now, compute the offset of src/dst page from the base
; The following multiplications always result in DX = 0 because only
; the paragraph size of each page is used.
MOV AL,CL ; AX = Destination page
MUL DI ; AX = dst-page * page-size
ADD AX,BX ; Add the base address also to get the final
MOV ES,AX ; Address in ES (destination base)
MOV AL,CH ; Get source page number
MOV AH,BL ; AH = BL = 0
MUL DI ; AX = src-page * page-size
ADD AX,BX ; Add the base address also to get the final
MOV BL,b$BiosMode ;get BIOS mode while we still have DS
MOV DS,AX ; Address in DS (source base)
; DI still has the page size (in paras) & convert it to word-size
MOV CL,3 ; Multiply by 8
SHL DI,CL ; DI = page size in words
MOV CX,DX ; CX = DX = 0
XCHG DI,CX ; CX = page size
; DI = 0 (destination offset from page)
; If current mode is a CGA mode then all is set for page copying
CMP BL,0DH ;Is it a CGA mode?
MOV SI,DI ; SI = 0 (Source offset from page)
JB CGA_COPY ; Brif to normal word copy
EGA_COPY:
; We can use the EGA write mode 1 to do 4-plane memory copying via
; the MOVSB instruction. This mode is documented to work so that the
; planes are written from the latches, which are loaded by a previous
; read. What in fact happens is that the MOVSB instruction handles the
; reads in such a way that the latches are correctly loaded for the
; 4-planes from DS:SI and the write to ES:DI reproduces the contents of
; the source area at the destination.
MOV DX,GRPADD ; EGA port address
MOV AX,1 SHL 8 + RWMReg ; Use write-mode 1
OutWord ;[17]Set up EGA
SHL CX,1 ; Make it a byte count
REP MOVSB ; ... and go
MOV AX,RWMReg ; Reset EGA to mode 0
OutWord ;[17]and DX is still intact
JMP SHORT PCOPY_RET ; & Exit...
CGA_COPY: ; Simple word move would do
REP MOVSW ; Copy source to destination
PCOPY_RET: ; Clear CF to indicate no error
CLC
PCOPY_EXIT: ; Time to exit - do not change flags
cEnd ; End of B$PCOPYS
sEnd RT_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -