⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ted2.asm

📁 一个很小的用汇编写的编辑器
💻 ASM
📖 第 1 页 / 共 5 页
字号:
		REP	MOVSB		;put deleted line in buffer
		POP	ES		;get back file segment
		POP	AX

		MOV	CX,LAST_CHAR	;get the file size
		SUB	LAST_CHAR,AX	;subtract the deleted line
		MOV	SI,CURSOR	;get new cursor location
		MOV	DI,SI
		ADD	SI,AX		;SI points to end of file
		SUB	CX,SI		;length of remaining file
		JCXZ	NO_DEL_L
		REP	MOVSB		;shift remainder of file up
NO_DEL_L:
		MOV	DIRTY_BITS,3	;redraw the screen and adjust cursor
		RET
DEL_L		ENDP

;=======================================================================
; This routine undeletes a line by copying it from the line buffer into 
; the file.
;-----------------------------------------------------------------------
UDEL_L		PROC	NEAR
		CMP	LINE_FLAG,0	;is this an end of line only?
		JE	UDEL_EOL	;if yes, don't home the cursor
		CALL	HOME		;move cursor to home
UDEL_EOL:
		MOV	AX,LINE_LENGTH	;length of deleted line
		MOV	SI,OFFSET LINE_BUFFER
;**insert_str	JMP	INSERT_STRING	;(follows immediately)
		;(CALL/RETurn)
UDEL_L		ENDP

;-----------------------------------------------------------------------
; This routine inserts AX characters from CS:SI into the file.
; (This routine follows "UDEL_L")
;-----------------------------------------------------------------------
INSERT_STRING	PROC	NEAR
	;	ASSUME	DS:FILE_SEG
		PUSH	SI		;save string buffer
		MOV	SI,CS:CURSOR	;get cursor offset
		PUSH	AX		;save length of string
		PUSH	SI
		CALL	OPEN_SPACE	;make space to insert string
		POP	DI		;get back cursor position
		POP	CX		;get back string length
		POP	SI		;get back string buffer
		JC	NO_SPACE	;if no space available, exit

		PUSH	DS
		PUSH	CS
		POP	DS
		ASSUME	DS:CSEG
		REP	MOVSB		;copy characters DS:SI to ES:DI
		MOV	DIRTY_BITS,3	;redraw the screen and adjust cursor
		POP	DS
		ASSUME	DS:NOTHING
		CALL	C_IF_NEW_CRLF
NO_SPACE:
		RET
INSERT_STRING	ENDP

;=======================================================================
; VIDEO services
;=======================================================================
; This routine displays a character by writing directly to 
; the screen buffer.  To avoid screen noise (snow) on the color
; card (CGA), the horizontal retrace has to be monitored.
;-----------------------------------------------------------------------
WRITE_INVERSE	PROC	NEAR		
		ASSUME	DS:FILE_SEG, ES:FILE_SEG
		MOV	BH,CS:INVERSE	;attribute for inverse video
		JMP	SHORT WRITE_SCREEN
;-----------------------------------------------------------------------
WRITE_FIND:
		MOV	BH,CS:SRCH_CLR	;attribute for find string
;		MOV	BH,CS:INVERSE	;attribute for find string
		JMP	SHORT WRITE_SCREEN
;-----------------------------------------------------------------------
WRITE_NORMAL:
		MOV	BH,CS:NORMAL	;attribute for normal video
WRITE_SCREEN:
		MOV	BL,AL		;save the character
		PUSH	ES
		LES	DX,CS:VIDEO_STATUS_REG ;video status register
		;-------------------------------------------------------
		; HWAIT is used to "desnow" the display for the CGA.
		; If not CGA, the following instruction is modified to a 
		; JMP   SHORT WRITE_IT
		;-------------------------------------------------------
HWAIT:
		IN	AL,DX		;get video status
		ROR	AL,1		;look at horizontal retrace
		JNC	HWAIT		;wait for retrace
WRITE_IT:
		MOV	AX,BX		;get the character/attributes
		STOSW			;write the character
		POP	ES
		RET
WRITE_INVERSE	ENDP

;=======================================================================
; This routine moves the cursor to the row/column in DX.
;-----------------------------------------------------------------------
SET_CURSOR	PROC	NEAR
		XOR	BH,BH		;we're using page zero
		MOV	AH,2		;BIOS set cursor function
		INT	10H
		RET
SET_CURSOR	ENDP

;=======================================================================
; This routine computes the video buffer offset for the row/column in DX.
;-----------------------------------------------------------------------
POSITION	PROC	NEAR
		MOV	AX,CS:COLUMNS	;take columns per row
		MUL	DH		;times row number
		XOR	DH,DH
		ADD	AX,DX		;add the column number
		SHL	AX,1		;times 2 for offset
		MOV	DI,AX		;return result in DI
		RET
POSITION	ENDP

;=======================================================================
; This routine erases from the location in DX to the right edge of the screen.
;-----------------------------------------------------------------------
ERASE_EOL	PROC	NEAR
		ASSUME	DS:NOTHING
		CALL	POSITION	;find screen offset
		MOV	CX,CS:COLUMNS	;get screen size
		SUB	CL,DL		;subtract current position
		JCXZ	NO_CLEAR
ERASE_LOOP:
		MOV	AL," "		;write blanks to erase
		CALL	WRITE_NORMAL	;display it
		LOOP	ERASE_LOOP
NO_CLEAR:
		RET
ERASE_EOL	ENDP

;=======================================================================
; This routine displays the function key prompt and insert/overstrike mode 
; state.  It sets DIRTY_BITS := 3 to force redraw of the entire screen 
; and locate cursor.
;-----------------------------------------------------------------------
REDO_PROMPT	PROC	NEAR
		ASSUME	DS:NOTHING, ES:NOTHING
		PUSH	DS
		PUSH	CS
		POP	DS
		ASSUME	DS:CSEG
		MOV	DH,ROWS		;put prompt at last row
		INC	DH
		XOR	DL,DL		;and column 0
		CALL	POSITION	;convert to screen offset
		MOV	SI,OFFSET PROMPT_STRING
KEY_LOOP:
		MOV	AL,"F"		;display an "F"
		CALL	WRITE_NORMAL
		LODSB
		OR	AL,AL		;last key in prompt?
		JZ	PROMPT_DONE
		CALL	WRITE_NORMAL

		CMP	BYTE PTR CS:[SI],"0" ;is it F10?
		JNE	TEXT_LOOP
		LODSB
		CALL	WRITE_NORMAL
TEXT_LOOP:
		LODSB
		OR	AL,AL		;last letter in word?
		JNZ	WRITE_CHAR

		MOV	AL," "		;display a space
		CALL	WRITE_NORMAL
		JMP	KEY_LOOP
WRITE_CHAR:
		CALL	WRITE_INVERSE	;display the letter
		JMP	TEXT_LOOP	;do the next letter
PROMPT_DONE:
		MOV	DH,ROWS
		INC	DH		;get the last row on the screen
		MOV	DL,PROMPT_LENGTH + 9
		CALL	ERASE_EOL	;erase to the end of this row
		MOV	BL,INSERT_MODE
		XOR	BH,BH
		MOV	AL,CS:[BX + OFFSET INSERT_CODE]
	;	MOV	AL,"O"		;write an "O" (for "Overstrike")
	;	CMP	INSERT_MODE,1	;in insert mode?
	;	JB	OVERSTRIKE
	;	MOV	AL,"I"		;write an "I" (for "Insert")
	;	JE	OVERSTRIKE
	;	MOV	AL,"R"		;write an "R" (for "read-only")
OVERSTRIKE:
		DEC	DI		;backup one character position
		DEC	DI
		CALL	WRITE_NORMAL
		MOV	DIRTY_BITS,3	;now redraw the entire screen
		POP	DS
		ASSUME	DS:NOTHING
		RET
REDO_PROMPT	ENDP

;=======================================================================
; This routine displays the file buffer on the screen.
; DISPLAY_BOTTOM has been deleted to reduce the program code size.
;-----------------------------------------------------------------------
DISPLAY_SCREEN	PROC	NEAR
		ASSUME	DS:FILE_SEG, ES:FILE_SEG

                TEST    DIRTY_BITS,2    ;see if we should adjust the cursor
		JZ	DISP_CURS_OK
		MOV	SI,CURSOR	;get the new cursor offset
		MOV	DX,CURS_POSN	;also get the current row
		CALL	LOCATE		;adjust the cursor screen position
DISP_CURS_OK:

                MOV     DX,CURS_POSN
		MOV	SAVE_ROW,DH
		CALL	SET_CURSOR	;position the cursor

                TEST    DIRTY_BITS,1    ;see if we should update the screen
                JNZ     DO_UPDATE_SCREEN

                TEST    DIRTY_BITS,4    ;is the current line dirty?
                JZ      DISP_DONE       ;if not, take jump
                CALL    DISPLAY_CURRENT ;redraw the current line
                JMP     SHORT DISP_DONE

DO_UPDATE_SCREEN:
                MOV     SI,TOP_OF_SCREEN ;point to first char on screen
		XOR	DH,DH		;start at first row
;		JMP	SHORT NEXT_ROW
;		;-----------------------
;DISPLAY_BOTTOM:				;this redraws the bottom only
;		CALL	FIND_START	;find first character on this row
;		MOV	DX,CURS_POSN	;get current cursor row
NEXT_ROW:
		PUSH	DX
		CALL	DISPLAY_LINE	;display a line
		POP	DX
		;-----------------------
		; the keyboard is tested here to see if a key is waiting
		;-----------------------
		MOV	AH,1
		INT	16H
		MOV	AL,1		;for dirty_bits, update not completed
		JNZ	DISP_NOT_DONE	;jump if there is a key is waiting

		INC	DH		;move to the next row
		CMP	DH,ROWS		;at end of screen yet?
		JBE	NEXT_ROW	;do all the rows
DISP_DONE:
                MOV     AL,0
DISP_NOT_DONE:
                MOV     DIRTY_BITS,AL   ;screen is completely redone
		RET
DISPLAY_SCREEN	ENDP

;=======================================================================
; This routine displays a single line to the screen.  DH holds the 
; row number, SI has the offset into the file buffer.  Tabs are expanded.  
; Adjustment is made for side shift.
;-----------------------------------------------------------------------
DISPLAY_CURRENT	PROC	NEAR
	;	ASSUME	DS:FILE_SEG
		CALL	FIND_START
		MOV	DX,CS:CURS_POSN
DISPLAY_CURRENT ENDP
		;-----------------------
DISPLAY_LINE	PROC	NEAR		;external entry point
		XOR	DL,DL		;start at column zero
		MOV	CS:MARGIN_COUNT,DL
		MOV	CX,DX		;use CL to count the columns
		CALL	POSITION	;compute offset into video
NEXT_CHAR:
		CMP	SI,LAST_CHAR	;at end of file?
		JAE	LINE_DONE
		LODSB			;get next character, DS:SI
		CMP	AL,TAB		;is this a Tab character?
		JE	EXPAND_TAB	;if yes, expand to spaces

		CMP	SI,LAST_CHAR	;at end of file now?
		JAE	DO_PUT		;jump, can't be CR-LF pair

		CMP	WORD PTR [SI-1],CRLF ;EOL marker
		JE	FOUND_CR	;quit when a CR-LF is found
DO_PUT:
		CALL	PUT_CHAR	;put character onto screen
TAB_DONE:
		CMP	CL,CS:COLUMNSB	;at right edge of screen?
		JB	NEXT_CHAR
		;-----------------------
		; from TEDPLUS
		INC	SI
		CMP	SI,LAST_CHAR	;at end of file?
		DEC	SI
		JAE	NOT_BEYOND
		CMP	WORD PTR [SI],CRLF ;at end of line?
		;----------------------
		JE	NOT_BEYOND
DO_DIAMOND:
		DEC	DI		;backup one character
		DEC	DI
		MOV	AL,4		;show a diamond
		CALL	WRITE_INVERSE	;in inverse video
NOT_BEYOND:
		JMP	FIND_NEXT	;find start of next line
		;(CALL/RETurn)
;---------------------------------------
EXPAND_TAB:
		MOV	AL," "		;convert tab to spaces
		CALL	PUT_CHAR
		MOV	AL,MARGIN_COUNT
		ADD	AL,CL		;CL is column count
		TEST	AL,00000111B	;at even multiples of eight?
		JNZ	EXPAND_TAB	;if not, keep adding spaces
		JMP	TAB_DONE
;---------------------------------------
FOUND_CR:
		INC	SI		;past the CR-LF
LINE_DONE:
		MOV	DX,CX
		JMP	ERASE_EOL	;erase the end of the line
		;(CALL/RETurn)
		;-----------------------
DISPLAY_LINE	ENDP

;=======================================================================
; This routine displays a single character to the screen.  If the character 
; is marked, it is shown in inverse video.  Characters outside the current 
; margin are not displayed.  Characters left of the margin are skipped.
;-----------------------------------------------------------------------
PUT_CHAR	PROC	NEAR
	;	ASSUME	DS:FILE_SEG
		MOV	BL,MARGIN_COUNT	;get distance to left margin
		CMP	BL,LEFT_MARGIN	;are we inside left margin?
		JAE	IN_WINDOW	;yes, show the character
		INC	BL
		MOV	MARGIN_COUNT,BL
		RET
		;-----------------------
		; from TEDPLUS
IN_WINDOW:
		CMP	SRCH_FLG,0
		JE	CKM
		CMP	SI,SRCH_BASE
		JBE	CKM
		CMP	SI,SRCH_END
		JA	CKM
		CALL	WRITE_FIND
;**inverse	CALL	WRITE_INVERSE	;found string highlighted, inverse video
		JMP	SHORT NEXT_COL
CKM:
		;-----------------------
		CMP	SI,MARK_START	;is this character marked?
		JBE	NOT_MARKED
		CMP	SI,MARK_END
		JA	NOT_MARKED
		CALL	WRITE_INVERSE	;marked characters shown inverse
		JMP	SHORT NEXT_COL
		;-----------------------
NOT_MARKED:
		CALL	WRITE_NORMAL
NEXT_COL:
		INC	CL		;increment the column count
		RET
PUT_CHAR	ENDP

;=======================================================================
; This routine adjusts the cursor position ahead to the saved cursor column.  
; On entry DH has the cursor row.
;-----------------------------------------------------------------------
SHIFT_RIGHT	PROC	NEAR
	;	ASSUME	DS:FILE_SEG
		MOV	CL,SAVE_COLUMN	;keep the saved cursor offset
		XOR	CH,CH
		MOV	BP,CX		;keep the saved cursor position
		ADD	CL,LEFT_MARGIN	;shift into visible window
		ADC	CH,0
		XOR	DL,DL
		MOV	CURS_POSN,DX	;get cursor row/column
		JCXZ	NO_CHANGE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -