📄 ted2.asm
字号:
NAME TED
PAGE 58,132
TITLE TED -- the Tiny EDitor
;=======================================================================
; TED.ASM -- The Tiny EDitor.
; PC Magazine * Tom Kihlken * 11/15/88
;
; See the article "The tiniest editor you'll ever need" by Tom Kihlken,
; in the November 15, 1988 issue of PC Magazine for more detail than is
; presented here. Portions of this text are excerpted from that article.
; The source listing, itself, was copied directly from that article and
; altered as appropriate to add comments or change or improve the program.
; The use of self-modifying code for "NO_DESNOW" is discussed in the article.
; SEGment register usage have been cleaned up to reduce the size of the code.
;
; TED follows normal text conventions: pressing the <Enter> key actually
; adds two characters, Carriage-return (ASCII 13) and Line-feed (ASCII 10),
; also known as a "hard carriage return". The <Tab> key inserts the ASCII 9
; tab character, and advances the screen cursor to the next column that is
; an even multiple of eight. The <Backspace> key deletes the character to
; its immediate left ("destructive" backspace) and combines two lines if it
; is pressed while in the first column. The Backspace code (Ctrl-H) may be
; entered in the file as a control code. TED2 allows the ASCII codes for
; Carriage-Return (Ctrl-M) and Line-feed (Ctrl-J) to independently be entered
; into the file as control codes. Because of this, TED2 rigidly enforces
; a convention that once the <Ctrl-M><Ctrl-J> pair is formed it becomes an
; End-of-line marker, and may not be separated again.
;
; Like DOS, TED lets you enter any character (except <Nul>, value 00) by
; holding down the Alt key, typing the decimal value of its ASCII code on
; the numeric keypad, then releasing Alt. This gives you access both to
; nonprinting codes below ASCII 32 and to the upper-order (ASCII 128 to 255)
; characters in the extended IBM set. TED2 allows the <Nul> code to be
; entered by pressing the <Shft-F1> key.
;
; NOTE: Unassigned keyboard codes are treated as no-operations.
;
; The TED Keypad commands are:
; Key Description
; Up Arrow Moves cursor up one row
; Down Arrow Moves cursor down one row
; Left Arrow Moves cursor left one column
; Right Arrow Moves cursor right one column
; PgUp Moves text window up one page
; PgDn Moves text window down one page
;>Home Moves cursor to start of row (if at home, next up)
;>End Moves cursor to end of row (if at end, next end down)
; Ins Toggles insert/overstrike mode
; Del Deletes character (right) at cursor (saved in UnDo)
; Backspace Deletes character (left) at cursor (not saved in UnDo)
; Ctrl-PgUp Moves to top of file
;>Ctrl-Home Moves to top of file (alias)
; Ctrl-PgDn Moves to bottom of file
;>Ctrl-End Moves to bottom of file (alias)
; Ctrl-Right Arrow Moves text window right eight columns
; Ctrl-Left Arrow Moves text window left eight columns
;
; Alt-S Search Search for (case insensitive) character string
; Alt-A Search Again Search again for string
; Alt-D Del EOL Deletes from cursor to the end of line
;
; The TED Editing Functions are:
; Key Function Operation
; F1 Help Help screen
; ShftF1 <Nul> Enters the <Nul> code (value 00) in the file
; F2 Exit Save changes and exit (creates a .BAK file)
; ShftF2 Quit Exit without saving changes
; F3 Print Prints the marked text
; F4 Mark Toggles mark state on/off
; F5 Cut Moves marked text to paste buffer
; ShftF5 Paste Inserts contents of paste buffer (64K char's max)
; F6 Search Search for (case insensitive) character string
; ShftF6 Search Again Search again for string
; F7 UnDo Replaces recently DELeted characters (256 char's max)
; F8 Del EOL Deletes from cursor to the end of line
; ShftF8 Del L Deletes the current line (MultiEdit)
; F9 Del L Deletes the current line
; F10 Udel L Inserts the last deleted line (256 char's max)
;
; In addition to the 64K Text buffer (where the edit file is maintained),
; there are three other important buffers, as indicated above.
; 1.) The paste buffer is a 64K character buffer used for MARK/CUT/PASTE of
; sections of the file.
; 2.) The line buffer is a 256 character buffer used to save the last
; deleted line of text (used with F8, F9 and F10).
; 3.) The UnDo buffer is a 256 character buffer used to save the just
; deleted characters at the current cursor location. It works with
; the "DEL" key, but only the last character with the "Backspace" key.
; It also saves overwritten characters in the Overstrike mode.
; Deletions are restored with "F7" UnDo.
;
; NOTE: There is a severe subroutine nesting violation in the TED key scan
; routine. BAD_KEY from within the keyboard scanning loop is a junp to
; read next key. The BAD_KEY subroutine calls through the DISPATCH_TABLE
; do not have a corresponding return to equalize the stack. This was
; partially compensated for by making the stack humongous. TED 1.0 as
; published in PC Magazine could eventually overflow the stack and crash the
; system. TED2 has corrected this problem by making a stub subroutine for
; the DISPATCH_TABLE BAD_KEY subroutine CALLs.
;
; TED was modified by James E. Galbraith, Dec 18, 1988.
; The changes are of several types. Compatability with other editors.
; Correction of errors and questionable code. Reordering of program modules
; to make it easier to follow the listing. Addition of meaningful comments.
; These modifications include:
; Change F2 "UnDo" to "Exit" (for BSE compatibility).
; Change F7 "Exit" to "UnDo".
; Make CTRL-HOME alias to CTRL-PGUP, to home the cursor (for BSE).
; Make CTRL-END alias to CTRL-PGDN, cursor to end of file (for BSE).
; JMP instructions outside modules instead of CALL/RETurn are commentd.
; Assignment of DS was sometimes ambiguous.
;
; Modified by James E. Galbraith, June 1989.
; The changes are in two groups. Those taken from TEDPLUS (apparently also
; written by Tom Kihlken), which was acquired from a bulletin board service,
; and my own changes.
; Add SEARCH and SEARCH AGAIN as F6 and Shft-F6, from TEDPLUS.
; Delete CPM style Ctrl-Z End-of-file code, from TEDPLUS.
; "Enter any key code" from TEDPLUS was included, but not like TEDPLUS
; End-of-line was changed to CR-LF as in TEDPLUS. CR or LF codes may be
; entered separately.
; My own changes are:
; Close the source file if it has been opened. This was not done by TED.
; Add a HELP screen as <F1>, move QUIT to <Shft-F2>.
; Fix the SEARCH inverse video to turn off when any key is pressed.
; Add DOS version check, needs version 2.0 or higher to run.
; Add a program checksum test for verification of file integrity.
; Add <Alt-S> as alias for <F6> SEARCH (usage in BSE editor).
; Add <Alt-A> as alias for <Shft-F6> SEARCH AGAIN (usage in BSE editor).
; Add <Alt-D> as alias for <Shft-F8>, Delete to end of line.
; Add <Shft-F8> as alias for <F9>, Delete Line (for future expansion).
; If the file has not been altered, don't prompt for save or quit.
; On QUIT, accept a CR as confirmation of intention to abandon file.
; Add <Shft-F1> as key to enter the <Nul> character, 00.
; If a CR and LF code are made to be ajacent, they become an EOL marker,
; and may not then be separated. This can occur in several ways that
; all include entering the codes <Crtl-M> and <Ctrl-J>.
; A key entry will interrupt a screen update that is in progress.
;
; Assemble the TED2.ASM source file to TED2.COM by using the MASM.EXE assembler,
; the linker LINK.EXE, and the file conversion utility EXE2BIN.EXE, as follows:
; The checksum byte can be obtained with TEST.BAT (included with TED2.ASM).
;
; MASM TED2;
; LINK TED2;
; EXE2BIN TED2 TED2.COM
;-----------------------------------------------------------------------
CSEG SEGMENT
ASSUME CS:CSEG, DS:CSEG, ES:CSEG
ORG 0100H
START:
JMP BEGIN
;-----------------------------------------------------------------------
; Local data area in CSEG.
;-----------------------------------------------------------------------
; ASCII character values used in the program.
TAB EQU 9
CR EQU 13
LF EQU 10
CRLF EQU 0A0DH
; Character strings and data
COPYRIGHT DB "TED 1.0 (C) 1988 Ziff Communications Co.,"
DB "PC Magazine, 11/15/88, by Tom Kihlken"
DB CR,LF,"TED 2.1, 9/12/89, by James E. Galbraith"
DB CR,LF,"$"
;(JEG)
HELP_SCREEN DB 9,9,'TED - the Tiny EDitor (any key to edit)',CR
DB LF,LF,9,'F1 - Help',9,9,9,'Shft-F1 - <NUL> char'
DB CR,LF,9,'F2 - Exit and save',9,9,'Shft-F2 - Quit'
DB CR,LF,9,'F3 - Print marked',9,9,'Shft-F3 - Form-feed'
DB CR,LF,9,'F4 - Mark toggle'
DB CR,LF,9,'F5 - Cut marked',9,9,9,'Shft-F5 - Paste'
DB CR,LF,9,'F6 - String search',9,9,'Shft-F6 - '
DB 'Search again'
DB CR,LF,9,'F7 - Undo <Del> or Ovr'
DB CR,LF,9,'F8 - Delete to EOL' ;** ,9,9,'Shft-F8 - '
;** DB 'Delete Line'
DB CR,LF,9,'F9 - Delete Line'
DB CR,LF,9,'F10 - Un-Delete line',LF
DB CR,LF,9,'Ctrl-L/R arrow - Move window'
DB CR,LF,9,'Ctrl-Home - to top'
DB CR,LF,9,'Ctrl-End - to EOF',LF
DB CR,LF,9,'Esc - From Exit'
DB CR,LF,'$',7,1AH
;from JEG and TEDPLUS
PROMPT_STRING DB "1Help",0 ;F1
DB "2Exit",0 ;F2
DB "3Print",0 ;F3
DB "4Mark",0 ;F4
DB "5Cut",0 ;F5
DB "6Search",0 ;F6
DB "7UnDo",0 ;F7
DB "8Del EOL",0 ;F8
DB "9Del L",0 ;F9
DB "10Udel L",0,0 ;F10
PROMPT_LENGTH = $ - OFFSET PROMPT_STRING
FILE_TOO_BIG DB "File too big$"
READ_ERR_MESS DB "Read error$"
MEMORY_ERROR DB "Not enough memory$"
;(JEG)
CHEK_SUM_MESS DB "TED altered$"
DOS_2_MESS DB "Needs DOS 2.0$"
VERIFY_MESS DB "Lose Changes (Y)?",0
SAVE_MESS DB "Save as: ",0
DOT_$$$ DB ".$$$",0
DOT_BAK DB ".BAK",0
;from TEDPLUS, string search
SRCH_PROMPT DB "SEARCH> ",0
;SRCH_MAX DB 66 ;(moved to file end to reduce file size)
;SRCH_SIZ DB 0
;SRCH_STR DB 66 DUP (0)
SRCH_FLG DB 0 ;0=normal, 1=search successful (inverse)
SRCH_END DW 0
SRCH_BASE DW 0
SRCH_CLR DB 0F0H ;244
DIRTY_BITS DB 03H ;1=update screen, 2=cursor 4=cur. line
DIRTY_FILE DB 0 ;0=file not altered, FF=file altered
NORMAL DB 07H ;video attribute bits
INVERSE DB 70H ;video (inverse)
LEFT_MARGIN DB 0 ;column number of screen left margin
MARGIN_COUNT DB 0
INSERT_MODE DB 01H ;1=INSert, 0=Overstrike, 2or3=Read Only
INSERT_CODE DB 'OIRR' ;indexed code for display screen
MARK_MODE DB 0 ;toggle, FF=MARK is on.
ROWS DB 23 ;Rows available on display screen
SAVE_COLUMN DB 0
SAVE_ROW DB 0
LINE_FLAG DB 0
EVEN ;"word align" (for 16-bit bus accesses)
NAME_POINTER DW 81H ;offset of command tail in PSP
NAME_END DW 81H ;end of tail
VIDEO_STATUS_REG LABEL DWORD ;(alias for use by LES instruction)
STATUS_REG DW 0 ;video status register offset
VIDEO_SEG DW 0B000H ;video segment, Mono=0B000, other 0B800
LINE_LENGTH DW 0 ;number of bytes in current line
UNDO_LENGTH DW 0 ;number of DELeted bytes in UnDo buffer
CURS_POSN DW 0 ;Cursor, Hi is row, Low is column
MARK_START DW 0FFFFH ;MARK text for CUT/PASTE or Print
MARK_END DW 0
MARK_HOME DW 0
TOP_OF_SCREEN DW 0 ;address in text file of Top-of-screen
CURSOR DW 0 ;address in text file of cursor
LAST_CHAR DW 0 ;address of last character in file.
COLUMNSB LABEL BYTE ;alias BYTE definition
COLUMNS DW 0
PASTE_SEG DW 0 ;segment address of PASTE buffer
PASTE_SIZE DW 0 ;size of block in PASTE buffer
PAGE_PROC DW 0 ;pointer used by PGUP and PGDN
EXIT_CODE DW 4C00H ;DOS INT 21H, Func 4CH, exit with code
OLDINT24 DD 0 ;pointer to DOS critical error handler
DISPATCH_BASE EQU 59 ;initial offset for a PASCAL type CASE list
DISPATCH_TABLE DW HELP ;59;F1, Help screen (common usage)
DW EXIT ;60;F2, Save changes and exit (from BSE)
DW PRINT ;61;F3, Print the marked text
DW MARK ;62;F4, Toggle mark state on/off
DW CUT ;63;F5, Move marked text to buffer
DW FIND_STR ;64;F6, Search for text string
DW UNDO ;65;F7, Replace recently deleted chars
DW DEL_EOL ;66;F8, Delete from cursor to EOL
DW DEL_L ;67;F9, Delete the current line
DW UDEL_L ;68;F10, Insert the last deleted line
DW BAD_KEY ;69;(NumLock)
DW BAD_KEY ;70;(ScrollLock)
DW HOME_KEY ;71;Home/7
DW UP ;72;Up/8
DW PGUP ;73;PgUp/9
DW BAD_KEY ;74;(-)
DW LEFT ;75;Left/4
DW BAD_KEY ;76;(5)
DW RIGHT ;77;Right/6
DW BAD_KEY ;78;(+)
DW END_KEY ;79;End/1
DW DOWN ;80;Down/2
DW PGDN ;81;PgDn/3
DW INSERT ;82;Ins/3
DW DEL_CHAR ;83;Del/.
DW NUL_CHAR ;84;Shft-F1 -- Add NUL character to file
DW ABORT ;85;Shft-F2 -- Quit and abandon changes
DW PRINT_FF ;86;Shft-F3 -- Print a form-feed character
DW BAD_KEY ;87;Shft-F4
DW PASTE ;88;Shft-F5 -- Insert contents of Paste buffer
DW FIND_STR ;89;Shft-F6 -- Search again for string
DW BAD_KEY ;90;Shft-F7
DW DEL_L ;91;Shft-F8 -- Delete line (Multi-Edit)
DISPATCH_END EQU 92
;--------------------------------
; gap in keyboard scan code assignments
;--------------------------------
DISP_CURS_BASE EQU 115
DW SH_LEFT ;115;Ctrl-Left arrow
DW SH_RIGHT ;116;Ctrl-Right arrow
DW BOTTOM ;117;Ctrl-End
DW CTRL_PGDN ;118;Ctrl-PgDn
DW TOP ;119;Ctrl-Home
DISP_CURS_END EQU 120
;** DW CTRL_PGUP ;132;Ctrl-PgUp
;---------------------------------
; The following constant is a machine instruction that removes the CGA desnow
; delay. It is inserted into the code for EGA, VGA, and mono displays.
; See the article in PC-Magazine for further discussion.
NO_DESNOW = (OFFSET WRITE_IT - OFFSET HWAIT - 2) * 256 + 0EBH ;opcode JMP SHORT
;=======================================================================
; We start by initialize the display, then allocate memory for the file
; and paste segments. Parse the command line for the filename, if one was
; input, read in the file. Finally set the INT 23 and 24 vectors.
;-----------------------------------------------------------------------
BEGIN:
MOV AH,30H ;get DOS version (JEG new)
INT 21H
CMP AL,2
JAE DOS_2_UP
MOV EXIT_CODE,0 ;is DOS version 1, exit with function 0.
MOV DX,OFFSET DOS_2_MESS ;message "Needs DOS 2.0"
;**short JMP EXIT_TO_DOS
JMP SHORT EXIT_22_DOS ;(saves a byte)
;-----------------------
DOS_2_UP:
;JEG new -- program code checksum test
MOV SI,100H ;start of program file.
MOV SP,SI ;set stack pointer to top of PSP.
MOV CX,OFFSET CHEK_SUM_BYT - 0100H ;size of program file.
MOV AL,CHEK_SUM_BYT ;load checksum correction factor byte.
CHKSUM_LOOP: ADD AL,[SI] ;add all program code bytes together.
INC SI
LOOP CHKSUM_LOOP
CMP AL,0 ;is program checksum zero?
JZ CHEKSUM_IS_OK ;yes, continue with program
NEG AL ;make error into correction factor.
MOV BYTE PTR EXIT_CODE,AL ;save errorlevel code for exit.
MOV DX,OFFSET CHEK_SUM_MESS ;message "TED altered".
;**short JMP EXIT_TO_DOS ;error message and exit to DOS
;EXIT_22_DOS: JMP SHORT EXIT_2_DOS ;error message and exit to DOS
EXIT_22_DOS: JMP EXIT_2_DOS ;error message and exit to DOS
;-----------------------
CHEKSUM_IS_OK:
XOR AX,AX
MOV DS,AX ;zero DS
ASSUME DS:NOTHING
MOV BL,10H
MOV AH,12H ;get EGA info
INT 10H
CMP BL,10H ;did BL change?
JE NOT_EGA ;if not, no EGA in system
TEST BYTE PTR DS:[0487H],8 ;is EGA active?
JNZ NOT_EGA
MOV WORD PTR CS:HWAIT,NO_DESNOW ;get rid of desnow
MOV AX,DS:[0484H] ;get number of rows
DEC AL ;last row is for prompt line
MOV CS:[ROWS],AL ;save the number of rows
NOT_EGA:
MOV AX,DS:[044AH] ;get number of columns
MOV CS:COLUMNS,AX ;and store it
MOV AX,DS:[0463H] ;address of display card
ADD AX,6 ;add six to get status port
PUSH CS
POP DS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -