TASM汇编程序无法正常读取文本文件,启动后直接退出求排查
Let's break down why your program exits immediately and fix the issues step by step:
1. Critical: File Opening Failure with No Feedback
The most likely reason your program exits right away is that it can't locate the_message.txt—either the file doesn't exist in the same directory as your executable, or there's a path mismatch. When DOS interrupt int 21h function 3Dh (open file) fails, it sets the carry flag (CF), and your code jumps straight to exit without any error message. You have no way to tell this is happening!
2. Unnecessary (and Risky) lds Instructions
You're using lds dx, point_fname and lds dx, point_buffer to load pointers, but this is redundant and could break your data segment (DS) setup. Since you already set DS to your .data segment with mov ax,@data / mov ds,ax, you can directly use mov dx, offset filename and mov dx, offset string to get the correct offsets in the data segment.
3. Flawed Input Selection Logic
In the ask section, after checking if input is 1 (ASCII 31h), you immediately jump to decrypt2 for any other input. This means if the user enters 2 (the intended decrypt option) or any random character, it will try to run the decrypt2 routine, which will fail if count isn't 2, leading to a confusing experience.
4. Unintended Flow in Error Cases
Your notAllowed section has a commented-out jmp exit, which means after showing the error, the program will fall through to exit anyway. It's better to let the user try again instead of exiting abruptly.
Fixed Code
Here's the corrected version with all issues addressed:
JUMPS .model small .data handle dw 0 filename db 'the_message.txt',0 string db 200 dup (" ") errorMes db 0ah,0dh,'Error: File operation failed!','$' invalidInput db 0ah,0dh,'Invalid input! Type 1 or 2.','$' mes db 0ah,0dh,'Type 1 to crypt, type 2 to decrypt!','$' mes1 db 0ah,0dh,'Crypted one time ','$' mes2 db 0ah,0dh,'Crypted two times ','$' mes3 db 0ah,0dh,'Decrypted','$' count db 0 .stack 256 .code main: mov ax,@data mov ds,ax ; Open file (read-only mode) mov al,0 mov dx,offset filename mov ah,3dh int 21h jc file_error ; Show error if open fails mov [handle],ax ; Read up to 200 bytes from file mov bx,[handle] mov cx,200 mov dx,offset string mov ah,3fh int 21h jc file_error mov bp,ax ; Store number of bytes actually read ; Close file mov ah,3eh int 21h jc file_error ask: ; Show operation prompt mov ah,09h lea dx,mes int 21h ; Get user input (echoed to screen) mov ah,01h int 21h ; Validate input cmp al,31h ; Check for '1' (crypt) je crypt1 cmp al,32h ; Check for '2' (decrypt) je decrypt_branch ; Handle invalid input mov ah,09h lea dx,invalidInput int 21h jmp ask crypt1: cmp count,0 jg crypt2 ; Perform first encryption (add 1 to each byte) mov cx,bp mov si,0 go1: add string[si],1 inc si loop go1 inc count ; Show status message mov ah,09h lea dx,mes1 int 21h jmp show crypt2: cmp count,1 jg notAllowed ; Perform second encryption (add 2 to each byte) mov cx,bp mov si,0 go2: add string[si],2 inc si loop go2 inc count ; Show status message mov ah,09h lea dx,mes2 int 21h jmp show decrypt_branch: ; Route decrypt request based on current encryption count cmp count,2 je decrypt2 cmp count,1 je decrypt1 jmp notAllowed decrypt2: ; Reverse second encryption (subtract 2 from each byte) mov cx,bp mov si,0 goDecr2: sub string[si],2 inc si loop goDecr2 dec count ; Show status message mov ah,09h lea dx,mes3 int 21h jmp show decrypt1: ; Reverse first encryption (subtract 1 from each byte) mov cx,bp mov si,0 goDecr1: sub string[si],1 inc si loop goDecr1 dec count ; Show status message mov ah,09h lea dx,mes3 int 21h jmp show show: ; Display modified string to screen mov cx,bp mov si,0 show_loop: mov ah,02h mov dl,string[si] int 21h inc si loop show_loop ; Add new line after output mov ah,02h mov dl,0ah int 21h mov dl,0dh int 21h jmp ask ; Return to prompt for more operations notAllowed: ; Show invalid operation error mov ah,09h lea dx,errorMes int 21h jmp ask ; Let user try again file_error: ; Show file operation failure error mov ah,09h lea dx,errorMes int 21h jmp exit exit: ; Terminate program mov ax,4c00h int 21h end main
Key Fixes Explained:
- Added file error feedback: If any file operation fails, it shows a clear message before exiting.
- Removed redundant
ldsinstructions to keepDScorrectly pointed to the data segment. - Fixed input validation: Now it properly checks for both
1and2, and loops back to the prompt for invalid inputs. - Added a
decrypt_branchto route decrypt requests based on the current encryption count. - Made the
showroutine loop back to the prompt, so users can perform multiple encryption/decryption cycles. - Explicit jumps in error cases to avoid unintended program flow.
内容的提问来源于stack exchange,提问作者S. Werner

