You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TASM汇编程序问题:填满200元素缓冲区后无法跳转至删除词输入

问题:填满200元素缓冲区后程序无法跳转至输入待删除单词环节

用TASM开发的汇编程序中,当主字符串缓冲区填满200个元素后,程序无法正常跳转到输入待删除单词的环节。以下是程序代码:

.MODEL small
.STACK 100h

.DATA
msg1 DB "Enter string: $"
msg2 DB 0Ah, 0Dh, "Enter word to delete: $"
msg3 DB 0Ah, 0Dh, "Result: $"

str1ml DB 200          ; maximum buffer length
str1l  DB 0            ; actual length of the entered string (DOS format)
str1   DB 200 dup('$') ; the characters of the string, filled with '$'

str2ml DB 200
str2l  DB 0
str2   DB 200 dup('$')

.CODE
begin:
    ; Initialize DS and ES segments
    mov ax, @data
    mov ds, ax
    mov es, ax
    xor ax, ax

    ; Print message and input the main string
    lea dx, msg1
    call strout
    lea dx, str1ml
    call strin

    ; Check if the buffer is full
    mov al, str1l
    cmp al, str1ml
    jb input_word      ; if the buffer is not full, proceed to input the word
    ; If the buffer is full, add a terminating character
    mov byte ptr [str1 + 200], '$' ; add a terminating character

input_word:
    ; Print message and input the substring (word to delete)
    lea dx, msg2
    call strout
    lea dx, str2ml
    call strin

    ; Check if the buffer is full
    mov al, str2l
    cmp al, str2ml
    jb process_input   ; if the buffer is not full, proceed to processing
    ; If the buffer is full, add a terminating character
    mov byte ptr [str2 + 199], '$' ; add a terminating character

process_input:
    ; Prepare to search for the substring in the main string
    xor cx, cx
    mov cl, str1l      ; load the length of the main string
    sub cl, str2l      ; calculate the number of possible positions for comparison
    inc cl            ; account for the last possible shift
    cld               ; clear the direction flag (forward traversal)
    lea di, str2      ; DI points to the beginning of the substring
    lea si, str1      ; SI points to the beginning of the main string
    xor ax, ax

all_string:
    ; Search for a match of the substring at the current position in the main string
    call sub_search
    inc si            ; shift one character to the right in the main string
    loop all_string   ; repeat the loop until CX is zero

    ; Move to a new line
    call nextstr

    ; Print the final result
    lea dx, msg3
    call strout
    lea dx, str1
    call strout

_end:
    mov ah, 4Ch      ; DOS function to terminate the program
    int 21h

; Procedure to move to a new line
nextstr proc
    push dx
    push ax
    mov dl, 0Dh      ; carriage return character
    mov ah, 02h
    int 21h
    mov dl, 0Ah      ; line feed character
    mov ah, 02h
    int 21h
    pop ax
    pop dx
    ret
nextstr endp

; Procedure to input a string (DOS function 0Ah)
strin proc
    mov ah, 0Ah
    int 21h
    ret
strin endp

; Procedure to output a string (DOS function 09h)
strout proc
    mov ah, 09h
    int 21h
    ret
strout endp

; Procedure to search for a substring in a string
sub_search proc
    push cx
    push di
    push si
    mov bx, si      ; save the starting address of the current comparison
    mov cl, str2l   ; set the counter to the length of the substring
    repe cmpsb      ; compare bytes while they are equal (SI and DI)
    je _eq          ; if all characters are equal, jump to deletion
    jne _neq        ; if a mismatch is found, jump to the end
_eq:
    call delete     ; call the procedure to delete the substring
    inc al
_neq:
    pop si
    pop di
    pop cx
    ret
sub_search endp

; Procedure to delete a substring
delete proc
    push bx
    push di
    push si
    mov di, bx      ; DI points to the beginning of the substring to delete
    lea si, [bx + str2l] ; SI points to the character after the substring
    mov cx, 200     ; maximum length of the string
    sub cx, bx      ; calculate the remaining length of the string
    rep movsb       ; copy the remaining part of the string
    pop si
    pop di
    pop bx
    ret
delete endp

end begin

问题分析

核心错误是缓冲区越界写入:

  • str1被定义为200 dup('$'),内存地址范围是str1到str1+199。当主字符串填满200个字符时,程序执行mov byte ptr [str1 + 200], '$',直接写入str1缓冲区外的内存区域,而该区域正好是后续变量str2ml的地址(数据段变量连续存放:str1ml→str1l→str1(200字节)→str2ml)。
  • 越界写入会将str2ml的值从200覆盖为'$'(ASCII码24),导致后续输入待删除单词时,缓冲区最大长度被错误设置为24,破坏程序流程,无法正常进入输入环节。

解决方案

  1. 修正终止符写入位置:将主字符串满缓冲区时的终止符写入str1的最后一个有效位置:
    ; 原错误代码
    ; mov byte ptr [str1 + 200], '$'
    ; 修正后
    mov byte ptr [str1 + 199], '$'
    
  2. 额外优化(可选):删除子串后更新str1l的值,避免后续循环基于错误长度执行:
    在sub_search的_eq分支中添加长度更新:
    _eq:
        call delete
        sub str1l, str2l  ; 更新主字符串实际长度
        inc al
    

内容的提问来源于stack exchange,提问作者Snow Max

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 04:50:13