Добавить в текстовый редактор функцию открытия файла - Assembler
Формулировка задачи:
Есть очень навороченный текстовый редактор, он умеет многое, но только не открывать файл. Помогите пожалуйста упростить по максимуму и добавить открытие из файла TASM для DOS
NAME EDIT PAGE 58,132 TITLE EDitor 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
Решение задачи: «Добавить в текстовый редактор функцию открытия файла»
textual
Листинг программы
;----------------------------------------------------------------------- ; This routine prints the marked text. If printer fails, it is cancelled. ;----------------------------------------------------------------------- PRINT PROC NEAR CMP MARK_MODE,0 ;is mark mode on? JE PRINT_RET ;if not, nothing to print MOV CX,MARK_END ;end of marked region MOV SI,MARK_START ;start of marked region SUB CX,SI ;number of bytes selected JCXZ PRINT_DONE ;if nothing to print, return DO_FF_CHAR: XOR DX,DX ;select printer 0 MOV AH,2 INT 17H ;get printer status TEST AH,10000000B ;is busy bit set? JZ PRINT_DONE TEST AH,00100000B ;is printer out of paper? JNZ PRINT_DONE PRINT_LOOP: LODSB XOR AH,AH INT 17H ;print the character ROR AH,1 ;check the time out bit JC PRINT_DONE ;if set, quit printing LOOP PRINT_LOOP MOV AL,CR ;------ [typographical error in article] ;**nop! XOR AH,0 ;[would be No-Operation] XOR AH,AH ;------ INT 17H ;finish with a CR PRINT_DONE: CALL MARK ;turn off the mark status PRINT_RET: RET PRINT ENDP ;======================================================================= ; CHARACTER STRING SEARCH and SEARCH AGAIN services; HELP screen ;======================================================================= ; from TEDPLUS ; This routine is used to search or search again for a character string. ;----------------------------------------------------------------------- FIND_STR PROC NEAR PUSH DS MOV BX,CS MOV DS,BX ASSUME DS:CSEG ;--------------------------------------- ;** now ShftF6 CMP AH,66H ;Is it shift F9 CMP AH,89 ;Is it shift-F6 (JEG) ;--------------------------------------- JE RPT_FIND MOV DH,ROWS INC DH ;Last row on the screen XOR DL,DL ;First column MOV SI,OFFSET SRCH_PROMPT CALL TTY_STRING ;Display search prompt MOV DX, OFFSET SRCH_MAX MOV AH,0AH INT 21H ;Read input string RPT_FIND: XOR DX,DX MOV DL,BYTE PTR SRCH_SIZ ADD DX,OFFSET SRCH_STR MOV DI,DX DEC DI MOV SRCH_END,DI XOR DX,DX MOV SI,CURSOR INC SI MOV SRCH_BASE,SI S_REDO: MOV DI,OFFSET SRCH_STR MOV BX,SRCH_BASE S_CYCLE: MOV AL,[DI] MOV AH,AL ;CONVERT AL TO OPPOSITE AND PUT IN AH CMP AL,'A' JB S_CMP CMP AL,'Z' JA TSTLO XOR AH,20H ;toggle letter case JMP SHORT S_CMP TSTLO: CMP AL,'a' JB S_CMP CMP AL,'z' JA S_CMP XOR AH,20H ;toggle letter case S_CMP: CMP BX,LAST_CHAR JA END_MCH CMP AL,ES:[BX] JE S_MCH CMP AH,ES:[BX] JE S_MCH CMP DI,OFFSET SRCH_STR JNE S_REDO INC BX CMP WORD PTR ES:[BX-1],CRLF ;test for EOL marker JNE S_BX1 INC DL S_BX1: JMP SHORT S_CMP S_MCH: INC BX CMP DI,OFFSET SRCH_STR JNE NO_BSE MOV SRCH_BASE,BX NO_BSE: ADD DH,DL XOR DL,DL CMP DI,SRCH_END JE YEA_MCH INC DI JMP SHORT S_CYCLE YEA_MCH: MOV SRCH_FLG,1 MOV SI,SRCH_BASE DEC SI MOV SRCH_BASE,SI MOV CURSOR,SI XOR BX,BX MOV BL,BYTE PTR SRCH_SIZ ADD BX,SI MOV SRCH_END,BX XOR DL,DL ADD DX,CURS_POSN CMP DH,ROWS JBE NEW_S XOR DX,DX NEW_S: POP DS ;ASSUME is no longer valid CALL LOCATE JMP SHORT END_MCH2 END_MCH: POP DS END_MCH2: CALL REDO_PROMPT ;redraw the prompt and the screen RET FIND_STR ENDP ;======================================================================= ; This routine displays a user help screen ;----------------------------------------------------------------------- HELP PROC NEAR PUSH DS PUSH CS POP DS ASSUME DS:CSEG ;for func-9, display message CALL CLR_SCREEN MOV DX,OFFSET HELP_SCREEN ;message is at DS:DX in CSEG MOV AH,9 ;display message INT 21H HELP_WAIT_KEY: MOV AH,1 ;wait for any key pressed INT 16H JZ HELP_WAIT_KEY MOV AH,0 INT 16H POP DS ASSUME DS:NOTHING JMP REDO_PROMPT ;redraw the prompt and the screen ;(CALL/RETurn) HELP ENDP ;======================================================================= ; This routine prompts for a filename then writes the file. The original ; file is renamed to filename.BAK. If an invalid filename is entered, the ; speaker is beeped. If the file has not been altered, the edit file is ; abandoned and control is immediately returned to DOS. ;----------------------------------------------------------------------- EXIT PROC NEAR PUSH DS ;save in case ESC key PUSH ES MOV AX,CS MOV DS,AX MOV ES,AX ASSUME DS:CSEG, ES:CSEG TEST BYTE PTR DIRTY_FILE,0FFH ;is the file altered? JNZ NEXT_LETTER ;(jump was out of range) JMP FINISHED ;file has not been altered, no save. ;----------------------- IS_BACKSPACE: CMP DI,NAME_POINTER ;at first letter? JLE NEXT_LETTER ;if yes, don't erase it MOV BYTE PTR [DI-1],0 DEC NAME_END NEXT_LETTER: MOV DH,ROWS INC DH ;last row on the screen XOR DL,DL ;first column MOV SI,OFFSET SAVE_MESS PUSH DX CALL TTY_STRING ;display a prompt POP DX ADD DL,9 ;move right 9 spaces MOV SI,NAME_POINTER CALL TTY_STRING ;display the filename XOR AH,AH ;read the next key INT 16H MOV DI,NAME_END ;this points to the last letter OR AL,AL ;is it a real character? ; JZ NEXT_LETTER ;ignore special keys JZ IS_ESCAPE ;special keys return to edit mode CMP AL,1BH ;is it ESCape? JE IS_ESCAPE ;continue with exit procedure CMP AL,CR ;is it CR? JE GOT_NAME CMP AL,08H ;is it a backspace? JE IS_BACKSPACE CMP DI,81H + 65 ;too many letters? JG NEXT_LETTER ;if yes, ignore them XOR AH,AH ;for new terminal 0 to string STOSW ;store the new letter and 0 INC NAME_END ;name is one character longer JMP NEXT_LETTER ;read another keystroke ;----------------------- IS_ESCAPE: POP ES ;get back file segment POP DS JMP REDO_PROMPT ;redraw the prompt and the screen ;(CALL/RETurn) ;return to edit mode ;----------------------- GOT_NAME: MOV DX,NAME_POINTER ;point to the filename MOV AX,4300H ;get the file attribute INT 21H ;DOS call JNC NAME_OK ;if no error, filename is OK CMP AX,3 ;was it "path not found" error? JE BAD_NAME ;if yes, filename was bad NAME_OK: MOV SI,OFFSET DOT_$$$ ;point to the ".$$$" MOV DI,OFFSET NAME_DOT_$$$ CALL CHG_EXTENSION ;add the new extension MOV DX,OFFSET NAME_DOT_$$$ ;point to temp filename MOV CX,0020H ;attribute for new file MOV AH,3CH ;function to create file INT 21H ;DOS call JNC NAME_WAS_OK ;continue if name was OK BAD_NAME: MOV AX,0E07H ;write a bell character INT 10H ;BIOS TTY service JMP NEXT_LETTER ;get another letter ;----------------------- WRITE_ERROR: MOV AH,3EH ;close the file INT 21H ;DOS call JMP BAD_NAME ;filename must be bad ;----------------------- NAME_WAS_OK: XOR DX,DX ;this is the file buffer MOV CX,LAST_CHAR ;number of chars in file MOV BX,AX ;this is the handle MOV AH,40H ;write to the file POP DS ;recover the buffer segment INT 21H ;write the buffer contents POP DS JC WRITE_ERROR ;exit on a write error CMP AX,CX ;was entire file written? JNE WRITE_ERROR ;if not, exit PUSH CS POP DS ;get the code segment MOV AH,3EH ;close the temp file INT 21H ;DOS call MOV SI,OFFSET DOT_BAK ;point to the ".BAK" MOV DI,OFFSET NAME_DOT_BAK CALL CHG_EXTENSION ;make the backup filename MOV DX,OFFSET NAME_DOT_BAK ;point to the backup name MOV AH,41H ;delete existing backup file INT 21H ;DOS call MOV DI,OFFSET NAME_DOT_BAK MOV DX,NAME_POINTER MOV AH,56H INT 21H ;DOS call MOV DI,NAME_POINTER ;point to new filename MOV DX,OFFSET NAME_DOT_$$$ ;point to temporary file MOV AH,56H ;rename temp to new file INT 21H ;DOS call, rename POP AX ;restore the stack POP AX JMP SHORT FINISHED ;(To return to DOS) EXIT ENDP ;----------------------------------------------------------------------- ; This routine prompts for a verify keystroke then exits without saving ; the file. If the file has not been altered, the edit file is abandoned ; and control is immediately returned to DOS. ;----------------------------------------------------------------------- ABORT PROC NEAR PUSH CS POP DS ASSUME DS:CSEG TEST BYTE PTR DIRTY_FILE,0FFH ;is the file altered? JZ FINISHED ;file has not been altered. MOV DH,ROWS ;last row on display INC DH ;bottom row on screen XOR DL,DL ;first column MOV SI,OFFSET VERIFY_MESS CALL TTY_STRING ;display verify message XOR AH,AH ;read the next key INT 16H ;BIOS read key routine CMP AL,CR ;is it CR? JE FINISHED OR AL,20H ;convert to lower case CMP AL,"y" ;was answer Yes? JE FINISHED ;if yes, then we're finished CALL REDO_PROMPT ;redraw the prompt and the screen PUSH ES POP DS ;set DS back to file segment RET ;return to edit mode ;----------------------- FINISHED: MOV DX,OFFSET COPYRIGHT ;----------------------- EXIT_TO_DOS: ;External entry point (DX, message) PUSH CS POP DS ;point to code segment ASSUME DS:CSEG CALL CLR_SCREEN ;clear the screen (passes DX through) MOV AH,9 ;display error/exit message DS:DX INT 21H ;DOS call MOV AX,EXIT_CODE ;Exit to DOS with exit code INT 21H ;DOS call ABORT ENDP ;======================================================================= ; This routine copies the input filename to CS:DI and changes the extension. ;----------------------------------------------------------------------- CHG_EXTENSION PROC NEAR ASSUME DS:CSEG, ES:CSEG PUSH SI MOV SI,NAME_POINTER CHG_LOOP: LODSB CMP AL,"." ;look for the extension JE FOUND_DOT OR AL,AL JZ FOUND_DOT STOSB ;copy a character JMP CHG_LOOP ;----------------------- FOUND_DOT: MOV CX,5 ;five characters in extension POP SI REP MOVSB ;move new extension in RET CHG_EXTENSION ENDP ;======================================================================= ; This routine displays the string at CS:SI at the location in DX. The ; remainder of the row is erased. Cursor is put at the end of the line. ;----------------------------------------------------------------------- TTY_STRING PROC NEAR ASSUME DS:CSEG PUSH DX CALL POSITION ;compute offset into video POP DX TTY_LOOP: LODSB ;load DS:SI to AL OR AL,AL ;at end of string yet? JZ TTY_DONE INC DL PUSH DX CALL WRITE_INVERSE ;write in inverse video POP DX JMP TTY_LOOP ;----------------------- TTY_DONE: CALL SET_CURSOR ;move cursor to end of string JMP ERASE_EOL ;erase the rest of the line ;(CALL/RETurn) TTY_STRING ENDP ;======================================================================= ; This routine clears the screen, leaves registers unaltered. ;----------------------------------------------------------------------- CLR_SCREEN PROC NEAR ASSUME DS:NOTHING PUSH AX ;save registers (for INT-24) PUSH BX PUSH CX PUSH DX ;save DX for message address MOV DL,79 ;DL = right column MOV DH,CS:ROWS ;DH = lower row INC DH ;to clear the last line on the screen MOV CX,0 ;CH = upper row, CL = left column MOV BH,CS:NORMAL ;BH is blank line attribute, 07 = normal video MOV AX,0600H ;scroll the cursor up (blank line) INT 10H XOR DX,DX ;set cursor to top left of screen CALL SET_CURSOR POP DX POP CX POP BX POP AX RET CLR_SCREEN ENDP ;======================================================================= ; This is the control break handler for MS-DOS. It ignores the break. ; TED then responds by entering a <Ctrl-C> in the file. ;----------------------------------------------------------------------- NEWINT23 PROC FAR ASSUME DS:NOTHING, ES:NOTHING MOV CS:DIRTY_BITS,1 ;to redraw the screen CLC ;tell DOS to ignore break IRET NEWINT23 ENDP ;======================================================================= ; This is the severe error handler. It homes the cursor before ; processing the error. ;----------------------------------------------------------------------- NEWINT24 PROC FAR ASSUME DS:NOTHING, ES:NOTHING PUSHF CALL CLR_SCREEN ;clear the screen and home the cursor POPF JMP CS:OLDINT24 ;(chain to old INT 24 handler) NEWINT24 ENDP ;======================================================================= ; This is the location of the character string search buffer. It occupies ; the last three bytes in the program file. The following 64-bytes are used ; for the buffer area. The third byte is also used as the program code ; check-sum compensation byte. ;----------------------------------------------------------------------- EVEN SRCH_MAX DB 66 ;42H, maximum size of buffer SRCH_SIZ DB 0 ;number of char's actually in buffer SRCH_STR DB 0 ;start of buffer block ;This is the correction byte for the check-sum test CHEK_SUM_BYT DB 0103 ;======================================================================= NAME_DOT_$$$ EQU $ +64 ;128 bytes NAME_DOT_BAK EQU $+80H +64 ;128 bytes UNDO_BUFFER EQU $+100H +64 ;256 bytes, Del key buffer LINE_BUFFER EQU $+200H +64 ;256 bytes, Delete line, EOL END_BUFFER EQU $+300H +64 +15 ;end of buffers, file segment follows ; +15 is for paragraph rounding CSEG ENDS ;----------------------------------------------------------------------- FILE_SEG SEGMENT FILE_SEG ENDS END START