X86汇编项目求助:删除功能异常,输入任意索引仅删最后一项
X86汇编项目删除功能修复方案
你遇到的问题是:无论输入哪个索引,程序只会删除最后一个姓名。让我们一步步分析问题并修复:
问题分析
仔细查看你的sterge(删除)代码段,发现几个关键问题:
numes变量未正确维护:在输入姓名的scrienume段中,每次添加新姓名后没有递增numes,导致这个记录姓名数量的变量始终为0,不仅逻辑不完整,还会导致无法通过姓名数量验证输入索引的有效性。- 索引有效性判断不严谨:仅通过
cmp ax, numePointer判断索引是否越界,没有结合当前实际的姓名数量,可能出现输入超过现有姓名数量的索引却未触发错误提示的情况。 - 错误提示字符串冗余:
invalid字符串中多余的0会导致打印时出现空字符,影响错误信息的正常显示。
这些问题叠加可能导致你测试时出现“删除任何索引都只删最后一个”的错觉,我们可以通过以下修复确保逻辑完全正确:
修复步骤
- 维护
numes变量:在scrienume段中,每次输入完一个姓名后添加inc numes,删除姓名时添加dec numes,正确记录姓名数量。 - 修正错误提示字符串:移除
invalid字符串中多余的0,确保错误信息正常显示。 - 增强索引有效性验证:利用
numes变量验证输入的0-based索引是否在[0, numes-1]范围内,避免无效索引的处理。 - 补充关键逻辑注释:为删除、遍历等核心步骤添加注释,方便后续维护和理解。
修改后的完整代码
.model small .stack 100h .data indexul db 2 dup (0) ; 修复:移除多余的0,确保错误信息正常显示 invalid db "Indexul introdus este invalid!",'$' string db 'Introduceti indexul numelui pe care doriti sa-l stergeti:',0,'$' punct db '.$' prompt db 'Introduceti un nume:',0,'$' list db 'Lista cu numele este:',0,'$' ; 每个姓名占6字节(5字符+$),50个双字足够存储16个姓名 nume dw 50 dup(0) numes dw 0 ; 记录当前姓名数量 numeIndex db 13, 10, 49, 46, 36 ; CR, LF, '1', '.', '$' numePointer dw 50 menu db "Alege o optiune:",13,10 db "1. Nume",13,10 db "2. Lista cu numele",13,10 db "3. Sterge un nume",13,10 db "4. Exit",13,10,'$' .code start: mov al, 0 ; 初始化数据段 mov ax, @data mov ds, ax mov numePointer, offset nume call clear_screen bucla: ; 换行 mov dl, 0dh mov ah, 2 int 21h mov dl, 0ah int 21h ; 显示菜单 call display_menu mov ah, 1 int 21h cmp al, '1' je scrienume cmp al, '2' je lista cmp al, '3' je sterge cmp al, '4' jmp exit jmp bucla scrienume: mov dx, offset prompt mov ah, 09h int 21h mov cx, 5 mov si, numePointer read_char: mov ah, 01h int 21h mov [si], al inc si loop read_char mov byte ptr [si], '$' inc si mov numePointer, si ; numePointer += 6(5字符+$) inc numes ; 修复:递增姓名数量 jmp bucla lista: mov byte ptr [numeIndex + 2], "1" mov dx, offset nume print_names: push dx ; 保存当前姓名的偏移地址 mov dx, offset numeIndex mov ah, 09h int 21h inc byte ptr [numeIndex + 2] ; 递增序号("1"->"2"->...) pop dx ; 恢复当前姓名的偏移地址 mov ah, 09h int 21h add dx, 5 + 1 ; 移动到下一个姓名(每个姓名占6字节) cmp dx, numePointer ; 检查是否遍历到最后一个姓名之后的地址 jb print_names jmp bucla ; 返回主循环 sterge: ; 提示用户输入要删除的姓名索引 mov dx, offset string mov ah, 09h int 21h ; 读取用户输入的索引字符 mov ah, 01h int 21h sub al, 49 ; 将1-based输入转换为0-based索引("1"->0, "2"->1...) ; 验证索引是否在有效范围内(0 <= 索引 < numes) cmp al, 0 jb invalidPosition mov ah, 0 cmp ax, numes jnb invalidPosition mov ah, 6 mul ah ; AX = 索引 * 6,计算待删除姓名的起始偏移 add ax, offset nume mov di, ax lea si, [di + 6] ; SI指向待删除姓名的下一个姓名起始地址 mov cx, numePointer sub cx, si ; CX = 需要移动的字节数(从SI到numePointer的长度) cld ; 设置方向标志为递增(SI和DI自增) rep movsb ; 将后面的姓名往前移动,覆盖待删除的姓名 mov numePointer, di ; 更新numePointer为新的最后一个姓名之后的地址(DI移动后的值 = numePointer -6) dec numes ; 递减姓名数量 jmp bucla invalidPosition: ; 显示错误信息 mov dx, offset invalid mov ah, 09h int 21h jmp bucla exit: ; 程序退出 mov ax, 4c00h int 21h ;--------------------------------------------- display_menu proc mov dx, offset menu mov ah, 9 int 21h ret display_menu endp clear_screen proc mov ah, 0 mov al, 3 int 10H ret clear_screen endp end start
修复说明
numes变量维护:新增了姓名数量的增减逻辑,确保程序能准确跟踪当前的姓名总数。- 索引有效性增强:通过
numes变量验证输入索引的合法性,避免处理超出范围的索引。 - 错误字符串修正:移除冗余字符,保证错误信息清晰显示。
- 逻辑注释补充:为核心操作添加注释,提升代码可读性和可维护性。
内容的提问来源于stack exchange,提问作者Mihai
相关产品推荐
相关产品推荐

