TASM汇编宏打印异常:输入字符串后程序阻塞问题求助
Let's break down why your assembly program is hanging when you press Enter, and fix the issues step by step.
1. Critical: Missing Input Buffer for INT 21H AH=0AH
The biggest problem here is how you're using the DOS buffered input function (AH=0AH). This function requires you to pass a pre-defined input buffer via the DX register—your code skips this entirely, so the system writes input data to a random memory location. This corrupts your program's data or code, leading to the hang.
Fix: Add an Input Buffer
First, add a properly structured input buffer to your DATA segment. The buffer needs three parts:
- A byte defining the maximum number of characters to accept
- A byte that DOS will fill with the actual number of characters entered (excluding the Enter key)
- Space to store the input characters
DATA SEGMENT PARA PUBLIC 'DATA' MSG1 DB 0DH, 0AH, 'PLEASE INPUT YOUR STRING', '$' MSG2 DB 0DH, 0AH, 'THE SUM IS', '$' NEWLINE DB 0DH, 0AH, '$' ; Add input buffer here INPUT_BUFFER DB 255 ; Max characters we can accept (adjust as needed) DB ? ; DOS will write actual input length here DB 255 DUP(0) ; Storage for input characters TOTAL DB ? DATA ENDS
Then, point DX to this buffer before calling INT 21H AH=0AH:
WRITE MSG1 WRITE NEWLINE LEA DX, INPUT_BUFFER ; Set DX to point to our input buffer MOV AH, 0AH INT 21H ; Read input correctly now
2. Incorrect Loop Counter & String Pointer
Your current code uses MOV CL, BYTE PTR DS:[0001] to get the input length, which points to a random byte in your DATA segment (the second byte of MSG1, which is 0AH—a newline character). That's why your loop runs incorrectly, contributing to the hang.
Fix: Use the Input Buffer's Length Field
Update your loop setup to use the actual input length from the buffer, and start reading from the first input character:
MOV CL, INPUT_BUFFER+1 ; Get actual number of characters entered MOV SI, OFFSET INPUT_BUFFER+2 ; Start at the first input character (skip buffer metadata) MOV DX, 0 ; Initialize sum to 0 MOV BL, 2 ; For even/odd check
3. Minor Logic Cleanup (Optional)
Your SUM procedure works, but it's redundant to re-read the ASCII character and convert it again (you already did SUB AL, 30H in the main loop). You can simplify this by handling the addition directly in the main loop to avoid procedure call overhead:
L: XOR AX, AX MOV AL, BYTE PTR [SI] CMP AL, 20H ; Check for space JE SPACE SUB AL, 30H ; Convert ASCII to digit TEST AL, 1 ; Faster even/odd check than DIV BL JNZ SPACE ADD DL, AL ; Add even digit to sum directly SPACE: INC SI LOOP L
4. Fix Sum Output (Current Code Prints Non-ASCII Values)
Right now, WRITE2 TOTAL outputs the numeric sum directly (e.g., if the sum is 10, TOTAL holds 0AH), which DOS interprets as a control character (newline) instead of the string "10".
Fix: Convert Numeric Sum to ASCII
Add a procedure to convert a byte-sized number to its readable ASCII string representation:
PRINT_NUM PROC ; Input: DL = numeric sum (0-255) ; Output: Prints the sum as ASCII characters PUSH AX PUSH BX PUSH CX MOV CX, 0 MOV BX, 10 ; Split number into individual digits NEXT_DIGIT: XOR AX, AX MOV AL, DL DIV BX ADD AH, 30H ; Convert remainder to ASCII PUSH AX INC CX MOV DL, AL CMP AL, 0 JNE NEXT_DIGIT ; Print digits in reverse order PRINT_LOOP: POP AX MOV DL, AH MOV AH, 02H INT 21H LOOP PRINT_LOOP POP CX POP BX POP AX RET PRINT_NUM ENDP
Then replace WRITE2 TOTAL with:
WRITE MSG2 MOV DL, TOTAL CALL PRINT_NUM
Full Fixed Code
Here's the complete corrected code with all fixes applied:
DATA SEGMENT PARA PUBLIC 'DATA' MSG1 DB 0DH, 0AH, 'PLEASE INPUT YOUR STRING', '$' MSG2 DB 0DH, 0AH, 'THE SUM IS', '$' NEWLINE DB 0DH, 0AH, '$' INPUT_BUFFER DB 255 DB ? DB 255 DUP(0) TOTAL DB ? DATA ENDS WRITE MACRO MSG MOV AH, 09H LEA DX, MSG INT 21H ENDM CODE SEGMENT PARA PUBLIC 'CODE' ASSUME CS:CODE, DS:DATA START PROC FAR PUSH DS XOR AX,AX PUSH AX MOV AX,DATA MOV DS,AX WRITE MSG1 WRITE NEWLINE LEA DX, INPUT_BUFFER MOV AH,0AH INT 21H ;READ INPUT MOV CL, INPUT_BUFFER+1 MOV SI, OFFSET INPUT_BUFFER+2 MOV DX,0 MOV BL,2 L: XOR AX, AX MOV AL, BYTE PTR [SI] CMP AL, 20H JE SPACE SUB AL,30H TEST AL,1 JNZ SPACE ADD DL,AL SPACE: INC SI LOOP L MOV TOTAL,DL WRITE MSG2 MOV DL, TOTAL CALL PRINT_NUM MOV AH,4CH INT 21H RET START ENDP PRINT_NUM PROC PUSH AX PUSH BX PUSH CX MOV CX,0 MOV BX,10 NEXT_DIGIT: XOR AX,AX MOV AL,DL DIV BX ADD AH,30H PUSH AX INC CX MOV DL,AL CMP AL,0 JNE NEXT_DIGIT PRINT_LOOP: POP AX MOV DL,AH MOV AH,02H INT 21H LOOP PRINT_LOOP POP CX POP BX POP AX RET PRINT_NUM ENDP CODE ENDS END START
This should resolve the hang and correctly calculate and display the sum of even digits in your input string.
内容的提问来源于stack exchange,提问作者Andrei Brașoveanu

