📄 misc.asm
字号:
.modeL small, pascal, os_dos
INCLUDE demo.inc
.DATA
_psp PSEG ? ; Segment of PSP
_env PSEG ? ; Segment of environment
.CODE
;* WinOpen - Saves portion of screen to allocated memory, then opens a window
;* with specified fill attribute. See also the WinClose procedure.
;*
;* Shows: DOS Function - 48h (Allocate Memory Block)
;* Instructions - movsw stosw rep
;*
;* Uses: vconfig - Video configuration structure (initialized
;* by calling the GetVidConfig procedure)
;*
;* Params: Row1 - Row at top of window
;* Col1 - Column at left edge of window
;* Row2 - Row at bottom of window
;* Col2 - Column at right edge of window
;* Attr - Fill attribute for window
;*
;* Return: Short integer with segment address of allocated buffer, or
;* 0 if unable to allocate memory
WinOpen PROC USES ds di si,
Row1:WORD, Col1:WORD, Row2:WORD, Col2:WORD, Attr:WORD
GetVidOffset Row1, Col1 ; Get offset in video segment
mov si, ax ; SI = video offset for window
mov bx, Row2
sub bx, Row1
inc bx ; BX = number of window rows
mov cx, Col2
sub cx, Col1
inc cx ; CX = number of columns
mov ax, cx ; Compute number of video
mul bl ; cells in window
add ax, 3 ; Plus 3 additional entries
shr ax, 1 ; Shift right 3 times to
shr ax, 1 ; multiply by 2 bytes/cell,
shr ax, 1 ; divide by 16 bytes/paragraph
inc ax ; Add a paragraph
push bx ; Save number of rows
mov bx, ax ; BX = number of paragraphs
mov ah, 48h ; Request DOS Function 48h
int 21h ; Allocate Memory Block
pop bx
.IF carry? ; If unsuccessful,
sub ax, ax ; return null pointer
.ELSE
mov es, ax ; Point ES:DI to allocated
sub di, di ; buffer
mov ax, si
stosw ; Copy video offset to buffer
mov ax, bx
stosw ; Number of rows to buffer
mov ax, cx
stosw ; Number of cols to buffer
mov ax, 160 ; Number of video cells/row
mov ds, vconfig.sgmnt ; DS = video segment
.REPEAT
push si ; Save ptr to start of line
push cx ; and number of columns
; For CGA adapters, WinOpen avoids screen "snow" by disabling the video prior
; to block memory moves, then reenabling it. Although this technique can
; result in brief flickering, it demonstrates the fastest way to access a
; block in the CGA video buffer without causing display snow. See also the
; StrWrite procedure for another solution to the problem of CGA snow.
.IF vconfig.adapter == CGA ; If not CGA adapter,
INVOKE DisableCga ; disable video
.ENDIF
rep movsw ; Copy one row to buffer
.IF vconfig.adapter == CGA ; If CGA adapter,
INVOKE EnableCga ; reenable CGA video
.ENDIF
pop cx ; Recover number of columns
pop si ; and start of line
add si, ax ; Point to start of next line
dec bx ; Decrement row counter
.UNTIL zero? ; Until no rows remain
; Screen contents (including display attributes) are now copied to buffer.
; Next open window, overwriting the screen portion just saved.
mov ax, 0600h ; Scroll service
mov bh, BYTE PTR Attr ; Fill attribute
mov cx, Col1 ; CX = row/col for upper left
mov ch, BYTE PTR Row1
mov dx, Col2 ; DX = row/col for lower right
mov dh, BYTE PTR Row2
int 10h ; Blank window area on screen
mov ax, es ; Return address of allocated
.ENDIF ; segment
ret
WinOpen ENDP
;* WinClose - "Closes" a window previously opened by the WinOpen procedure.
;* See also the WinOpen procedure.
;*
;* Shows: DOS Function - 49h (Release Memory Block)
;* Instructions - lodsw
;* Operators - : (segment override) SEG
;*
;* Uses: vconfig - Video configuration structure (initialized
;* by calling the GetVidConfig procedure)
;*
;* Params: Adr - Segment address of buffer that holds screen contents
;* saved in WinOpen procedure
;*
;* Return: None
WinClose PROC USES ds di si,
Adr:WORD
mov ds, Adr ; DS:SI points to buffer
sub si, si
lodsw
mov di, ax ; DI = video offset of window
lodsw
mov bx, ax ; BX = number of window rows
lodsw
mov cx, ax ; CX = number of columns
mov ax, SEG vconfig.sgmnt
mov es, ax ; Point ES to data segment
push es:vconfig.sgmnt
pop es ; ES = video segment
mov ax, 160 ; Number of video cells/row
.REPEAT
push di ; Save ptr to start of line
push cx ; and number of columns
; Disable CGA video prior to memory move to avoid screen snow. (See the
; WinOpen and StrWrite procedures for further discussions on CGA snow.)
.IF vconfig.adapter == CGA ; If CGA adapter,
INVOKE DisableCga ; disable video
.ENDIF
rep movsw ; Copy one row to buffer
.IF vconfig.adapter == CGA ; If CGA adapter,
INVOKE EnableCga ; reenable CGA video
.ENDIF
pop cx ; Recover number of columns
pop di ; and start of line
add di, ax ; Point to start of next line
dec bx ; Decrement row counter
.UNTIL zero? ; until no rows remain
mov ah, 49h ; Request DOS Function 49h
mov es, Adr
int 21h ; Release Memory Block
ret
WinClose ENDP
;* SetCurSize - Sets cursor size.
;*
;* Shows: BIOS Interrupt - 10h, Function 1 (Set Cursor Type)
;*
;* Params: Scan1 - Starting scan line
;* Scan2 - Ending scan line
;*
;* Return: None
SetCurSize PROC,
Scan1:WORD, Scan2:WORD
mov cx, Scan2 ; CL = ending scan line
mov ch, BYTE PTR Scan1 ; CH = starting scan line
mov ah, 1 ; Function 1
int 10h ; Set Cursor Type
ret
SetCurSize ENDP
;* GetCurSize - Gets current cursor size.
;*
;* Shows: BIOS Interrupt - 10h, Function 3 (Get Cursor Position)
;*
;* Uses: vconfig - Video configuration structure (initialized
;* by calling the GetVidConfig procedure)
;*
;* Params: None
;*
;* Return: Short integer with high byte = top scan line,
;* low byte = bottom scan line
GetCurSize PROC
mov ah, 3 ; Function 3
mov bh, vconfig.dpage
int 10h ; Get Cursor Position
mov ax, cx ; Return cursor size
ret
GetCurSize ENDP
;* GetShift - Gets current shift status. Checks for extended keyboard,
;* and, if available, returns additional shift information.
;*
;* Shows: BIOS Interrupt - 16h, Functions 2 and 12h (Get Keyboard Flags)
;*
;* Params: None
;*
;* Return: Long integer
;* high word = 0 for nonextended keyboard
;* 1 for extended keyboard
;* low word has following bits set when indicated keys are pressed:
;* 0 - Right SHIFT 8 - Left CTRL
;* 1 - Left SHIFT 9 - Left ALT
;* 2 - CTRL 10 - Right CTRL
;* 3 - ALT 11 - Right ALT
;* 4 - SCROLL LOCK active 12 - SCROLL LOCK pressed
;* 5 - NUM LOCK active 13 - NUM LOCK pressed
;* 6 - CAPS LOCK active 14 - CAPS LOCK pressed
;* 7 - INSERT toggled 15 - SYS REQ pressed
GetShift PROC
sub dx, dx ; Assume nonextended keyboard
mov ah, 2 ; and use Function 2
mov es, dx ; Point ES to low memory
.IF BYTE PTR es:[496h] & 16 ; If extended keyboard installed,
inc dx ; set high word of return code
mov ah, 12h ; and use Function 12h
.ENDIF
int 16h ; Get Keyboard Flags
ret
GetShift ENDP
;* GetKeyClock - Waits for keystroke while updating time at specified location
;* on screen.
;*
;* Shows: BIOS Interrupt - 16h, Functions 0 and 10h (Read Character)
;* 16h, Functions 1 and 11h (Get Keyboard Status)
;* DOS Functions - 2Ah (Get Date)
;* 2Ch (Get Time)
;*
;* Uses: vconfig - Video configuration structure (initialized
;* by calling the GetVidConfig procedure)
;*
;* Params: Row - Screen row for clock display
;* Col - Screen column for clock display
;*
;* Return: Short integer with key scan code in high byte and ASCII
;* character code in low byte. Low byte is 0 for special
;* keys (such as the "F" keys), which don't generate characters.
.DATA
PUBLIC datestr
datestr BYTE " - - : : ", 0 ; Date/time string
.CODE
GetKeyClock PROC,
Row:WORD, Col:WORD
LOCAL service:BYTE
INVOKE GetShift ; Check for extended keyboard
mov service, 11h ; Assume Function 11h
.IF dx != 1 ; If no extended keyboard,
mov service, 1 ; use Function 1
.ENDIF
.WHILE 1
mov ah, service
int 16h ; Get Keyboard Status
.BREAK .IF !zero? ; If no key yet, update clock
; If not monochrome, color text, or black and white, skip clock update
; and poll keyboard again.
.CONTINUE .IF (vconfig.mode != 7) \
&& (vconfig.mode != 3) \
&& (vconfig.mode != 2)
; If 80-column text, get date and time from DOS before again
; polling keyboard, and display at upper right corner of screen.
mov ah, 2Ch ; Request time
int 21h ; Get Time
mov dl, dh
push dx ; Save seconds,
push cx ; minutes,
mov cl, ch ; and
push cx ; hours
mov ah, 2Ah ; Request date
int 21h ; Get Date
sub cx, 1900 ; Subtract century, CL = year
push cx ; Save year,
push dx ; day,
mov dl, dh ; and
push dx ; month
mov cx, 6
sub bx, bx
.REPEAT
pop ax ; Recover all 6 numbers in AL
aam ; Convert to unpacked BCD
xchg al, ah ; Switch bytes for word move
or ax, "00" ; Make ASCII numerals
mov WORD PTR datestr[bx], ax; Copy to string
add bx, 3 ; at every third byte
.UNTILCXZ
INVOKE StrWrite, Row, Col, ADDR datestr
.ENDW ; Loop again for keypress
mov ah, service ; 1 or 11h, depending on keybd
dec ah ; Set AH to 0 or 10h
int 16h ; Get key to remove it from
ret ; keyboard buffer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -