📄 window.asm
字号:
AND DL,DL ; Already at first col?
JZ ?vedit ; Yes, don't backup
DEC DL ; Reduce 'X' position
JMP <?vedit ; And exit
* Handle NEWLINE
?tstnl CMP AX,#'J'-$40 ; Is it newline?
JNZ ?norchr ; Yes, advance line
MOV AL,1[SI] ; Get flags
TEST AL,#$04 ; Special case?
JNZ ?advy ; Yes, don't reset 'X'
XOR DL,DL ; Reset cursor
JMP <?advy ; And goto a new line
* Normal Character, output it
?norchr CALL ?xyaddr ; Calculate address
MOV AH,[SI] ; Get video attributes
MOV ES:[BX],AX ; Write to video display
* Advance 'X' position
?advx INC DL ; Advance 'X'
CMP DL,4[SI] ; Are we over?
JB ?vedit ; No, its ok
DEC DL ; Restore it
MOV AL,1[SI] ; Get flags
TEST AL,#$01 ; Line wrap enabled?
JZ ?vedit ; No, skip it
XOR DL,DL ; Reset 'X' position
* Advance 'Y' position
?advy INC DH ; Advance 'Y' position
CMP DH,5[SI] ; are we over?
JB ?vedit ; No, Its OK
DEC DH ; Reset it
MOV AL,1[SI] ; Get flags
TEST AL,#$02 ; Screen wrap enabled?
JZ ?vedit ; No, skip it
CALL ?scroll ; Scroll window
* Restore callers environment & exit
?vedit MOV 6[SI],DX ; Resave 'X' and 'Y'
POP ES ; Restore callers ES
POP BP ; Restore callers stack frame
RET
*
* CLEAR current window: wclwin()
*
wclwin CALL ?xsetup ; Get current window
JMP <?clscr1 ; And proceed
*
* CLEAR entire window: w_clwin(window)
*
w_clwin CALL ?wsetup ; Setup video
?clscr1 XOR DX,DX ; Reset to top of screen
MOV 6[SI],DX ; Reset cursor
CALL ?updt2 ; Position cursor
XOR DX,DX ; Reset again
JMP <?clscr2 ; And proceed
*
* CLEAR to end of current window: wcleow()
*
wcleow CALL ?xsetup ; Get current window
JMP <?clscr2 ; And proceed
*
* CLEAR to END OF WINDOW: w_cleow(window)
*
w_cleow CALL ?wsetup ; Setup video
?clscr2 CALL ?cleos ; Clear to end
POP ES ; Restore ES
POP BP ; Restore caller
RET
*
* CLEAR to end of line in current: wcleol()
*
wcleol CALL ?xsetup ; Get current window
JMP <?cleol1 ; And proceed
*
* CLEAR to END OF LINE: w_cleol(window)
*
w_cleol CALL ?wsetup ; Setup video
?cleol1 CALL ?xyaddr ; Get address
MOV DI,BX ; Set up address
MOV CL,4[SI] ; Get size of line
SUB CL,DL ; Calculate remaining
XOR CH,CH ; Zero high
MOV AH,[SI] ; Get attribute
MOV AL,#' ' ; Clear to space
REP
STOSW ; Clear a line
POP ES ; REstore ES
?cleol2 POP BP ; Restore caller
RET
*
* Position the cursor in current window: wgotoxy(int x, int y)
*
wgotoxy PUSH BP ; Save callers stack frame
MOV BP,SP ; Address parameters
MOV AL,6[BP] ; Get 'X' value
MOV AH,4[BP] ; Get 'Y' value
MOV SI,W_OPEN ; Get open window
JMP <?goto1 ; And proceed
*
* Position the cursor in window: w_gotoxy(int x, int y, window)
*
w_gotoxy PUSH BP ; Save callers stack frame
MOV BP,SP ; Address parameters
MOV AL,8[BP] ; Get 'X' value
MOV AH,6[BP] ; Get 'Y' value
MOV SI,4[BP] ; Get window buffer
?goto1 CMP AL,4[SI] ; In range?
JAE ?cleol2 ; No, error
CMP AH,5[SI] ; In range
JAE ?cleol2 ; No, error
MOV 6[SI],AX ; Save values
JMP <?updt1 ; And proceed
*
* Update the cursor in current window: wgotoxy()
*
wupdatexy MOV SI,W_OPEN ; Get open window
JMP <?updt2 ; And proceed
*
* Update the cursor position: w_updatexy(window)
*
w_updatexy PUSH BP ; Save callers stack frame
MOV BP,SP ; Address parameters
MOV SI,4[BP] ; Get caller
?updt1 POP BP ; Resture caller
?updt2 MOV DX,2[SI] ; Get starting address
ADD DX,6[SI] ; Offset into window
MOV BH,W_PAGE ; Get video page
MOV AH,#$02 ; Set cursor function
INT $10 ; Call DOS
RET
*
* Check for a key from the keyboard: c = w_tstc(window)
*
w_tstc MOV AH,#$01 ; Check for key
INT $16 ; Do we have key?
JNZ w_getc ; Yes, read it
?wtst1 XOR AX,AX ; No key today
RET
*
* Check for key with cursor in current window: c = wtstc()
*
wtstc MOV AH,#$01 ; Check for key
INT $16 ; Do we have key?
JZ ?wtst1 ; No, return zero
*
* Get in cursor in current window: c = wgetc()
*
wgetc MOV SI,W_OPEN ; Get active window
JMP <?getc1 ; And proceed
*
* Get a key from the keyboard with translations: c = w_getc(window)
*
w_getc MOV BX,SP ; Address parameters
MOV SI,2[BX] ; Get window
?getc1 CALL ?updt2 ; Update the cursor position
* Call BIOS to read key
XOR AH,AH ; Function code 0 - read key
INT $16 ; Call bios
* Lookup key for special entries
MOV CL,#$80 ; Beginning function code
MOV BX,#?W_KEYS ; Address of keys array
?lokkey MOV DX,[BX] ; Get key entry
CMP AX,DX ; Does it match?
JZ ?fndkey ; We found it
ADD BX,#2 ; Skip ahead
INC CL ; Advance key code
OR DH,DL ; End of table?
JNZ ?lokkey ; Keep looking
* Translate ENTER key to newline
CMP AX,#$1C0D ; ENTER key?
JNZ ?norkey ; Yes, we have it
MOV CL,#'J'-$40 ; Newline is LINE-FEED
* Translate special keys
?fndkey MOV AL,CL ; Set return value
?norkey CBW ; Set high bits
RET
*
* Set the CURSOR OFF: wcursor_off()
*
wcursor_off EQU *
MOV CX,#$2020 ; Value for cursor off
JMP <?setc2 ; And set it
*
* Set the CURSOR to a block: wcursor_block()
*
wcursor_block EQU *
MOV CX,#$0006 ; Color block cursor
MOV DX,#$000B ; Monochrome block cursor
JMP <?setc1 ; and proceed
*
* Set the CURSOR to a LINE: wcursor_line()
*
wcursor_line EQU *
MOV CX,#$0607 ; Color line cursor
MOV DX,#$0B0C ; Monochrome line cursor
?setc1 MOV AX,W_BASE ; Get video base
CMP AX,#?MBASE ; Monochrome?
JNZ ?setc2 ; No, do it
MOV CX,DX ; Copy for later
* Set cursor to value in CX
?setc2 MOV AH,#1 ; Set cursor type
INT $10 ; Call BIOS
RET
*
* Set up addressability to video display & stack registers
* Exit: ES = video base address
* SI = window buffer address
* DX = cursor address (X/Y)
*
?wsetup POP AX ; Get return address
PUSH BP ; Save callers stack frame
MOV BP,SP ; Address parameters
MOV SI,4[BP] ; Get window buffer
?wset1 PUSH ES ; Save callers Extra segment
PUSH AX ; Replace return address
MOV ES,W_BASE ; Point to video base
MOV DX,6[SI] ; Get 'X' and 'Y' position
RET
*
* Set up addressability to currently open window
*
?xsetup POP AX ; Get return address
PUSH BP ; Save callers stack frame
MOV BP,SP ; Address parameters
MOV SI,W_OPEN ; Get open window
JMP <?wset1 ; And proceed
*
* Scroll window forward one line
*
?scroll PUSH DS ; Save data segment
PUSH DX ; Save cursor
PUSH SI ; Save SI
* First, calculate base address of window
MOV AL,3[SI] ; Get 'Y' position
MOV BL,#160 ; Size of line
MUL BL ; Calculate 'Y' offset
MOV BL,2[SI] ; Get 'X' position
XOR BH,BH ; Zero high
SHL BX,1 ; * 2 for char & attribute bytes
ADD BX,AX ; BX = character position
MOV DI,BX ; Get base window address
* Scroll one line at a time
MOV DX,4[SI] ; Get 'X' and 'Y' sizes
DEC DH ; Don't copy to last
PUSH ES ; Stack ES
POP DS ; To place in DS
?scrol1 PUSH DI ; Save DI
MOV SI,DI ; Begin with same address
ADD SI,#160 ; Offset to next line
MOV CL,DL ; Get 'X' size
XOR CH,CH ; Zero high size
REP
MOVSW ; Move one line
POP DI ; Restore it
ADD DI,#160 ; Offset to next line
DEC DH ; Reduce count
JNZ ?scrol1 ; And proceed
* Clear bottom line of screen
MOV CL,DL ; Get 'X' size
POP SI ; Restore SI
POP DX ; Restore cursor
POP DS ; Restore data segment
MOV AH,[SI] ; Get attribute
MOV AL,#' ' ; And space
REP
STOSW ; Clear it
RET
*
* Clear from cursor(DX) to end of line
*
?cleos PUSH DX ; Save cursor
?cleos1 CALL ?xyaddr ; Get address
MOV DI,BX ; Set up address
MOV CL,4[SI] ; Get size of line
SUB CL,DL ; Calculate remaining
XOR CH,CH ; Zero high
MOV AH,[SI] ; Get attribute
MOV AL,#' ' ; Clear to space
REP
STOSW ; Clear a line
XOR DL,DL ; Zero 'X'
INC DH ; Advance 'Y'
CMP DH,5[SI] ; Are we finished
JB ?cleos1 ; Keep going
POP DX ; Restore cursor
RET
*
* Calculate screen address from X/Y position (in DX)
* On exit: BX = address
*
?xyaddr PUSH AX ; Save AX
MOV AL,DH ; Get 'Y' position
ADD AL,3[SI] ; Offset from start of screen
MOV BL,#160 ; Size of physical screen
MUL BL ; Calculate 'Y' offset
MOV BL,DL ; Get 'X' position
ADD BL,2[SI] ; Offset from start of screen
XOR BH,BH ; Zero high byte
SHL BX,1 ; * 2 for char & attribute bytes
ADD BX,AX ; BX = character position
POP AX ; Restore it
RET
$EX:malloc
$EX:free
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -