scrienume label让我从键盘上读取5个字符名。lista标签在一行上显示每个列表及其索引(例如:如果我写"daria"one_answers"adria",输出是"1.daria",下一行是"2.maria")。第三个标签应该让我有可能从键盘上写一个索引号,并删除具有该索引(例如:如果我按1,名称"daria"已删除,且名称"maria"获取索引1)。
这些是输入和输出的标签。
我试着在我的程序中看到我从键盘上找到索引的位置,然后在字符串中向左移动索引大于我写的索引的所有名称。我的问题是我的名字没有从名单上删除。这将从列表中删除id
的名称。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
jmp bucla
lista:
mov dx, offset nume
print_names:
push dx ; (1)
mov dx, offset numeIndex
mov ah, 09h
int 21h
inc byte ptr [numeIndex + 2] ; "1" -> "2" -> "3" ...
pop dx ; (1)
mov ah, 09h
int 21h
add dx, 5 + 1
cmp dx, numePointer ; check if the current name is the last one
jb print_names
jmp bucla ; return to main loop
sterge:
; Prompt user for index of name to delete
mov dx, offset string
mov ah, 09h
int 21h
; Read index from user
mov ah, 01h
int 21h
sub al, '0'
mov al, al
mov bx, ax;
; Verify that index is valid
cmp bx, numes
jae invalidIndex
; Shift names to the left
mov cx, numes
mov si, numePointer
add si, bx
add si, bx
add si, bx
add si, bx
add si, bx
add si, 1
mov di, si
dec bx
dec numes
shiftLoop:
cmp bx, 0
je updatePointer
mov al, [si]
mov [di], al
inc si
inc di
dec bx
jmp shiftLoop
updatePointer:
mov numePointer, di
jmp bucla
invalidIndex:
; Display error message
mov dx, offset invalid
mov ah, 09h
int 21h
jmp bucla
sterge的麻烦
sub al, '0' mov al, al mov bx, ax; cmp bx, numes jae invalidIndex
这样写,它总是跳转到invalidIndex。显然,您的names(列表中的名称)变量是单词大小的,您希望将来自用户的字节大小的响应扩展为一个完整的单词。mov al, al
不这样做,你需要mov ah, 0
(或者cbw
对于这些非常小的正数)。
对于一个解决方案,考虑如下:尽管用户将使用从1开始的索引,程序应该使用0作为第一个索引,它会简化很多事情。
sub al, '0' ; AL=[1,9]
cbw ; AX=[1,9] 1-based index
dec ax ; AX=[0,8] 0-based index
cmp ax, numes ; numes is [0,9]
jae invalidIndex
mov di, si
您正在为shiftloop设置源指针和目标指针相同的指针!这样循环所做的任何功都无关紧要!
mov si, numePointer
您没有使用nummepointer我在以前的答案中定义和使用它的方式。
这是一个指针,包含名称列表末尾的地址。
elena$maria$daria$adria$
^ ^
nume [numePointer]
shiftLoop: cmp bx, 0 je updatePointer
您正在使用BX中的索引来控制迭代的次数。每次迭代只移动一个字节,而实际上你应该移动6个字节(5 + 1),所以你的复制远远不够!
sterge解决方案假设列表中有4个名字,那么names=4:
1.elena
2.maria
3.daria
4.adria
有效的用户输入将是1,2,3和4,验证码将把它转换为范围从0到3的AL。
将这个数字乘以6将得到列表中要删除的名称的偏移量。列表中需要在内存中向下移动的部分从它上面6个字节开始。如果选择最上面的项进行删除,则该部分可能为空。我下面的代码使用rep movsb
指令,即使没有什么要复制,它也会工作得很好。
...
sub al, 49 ; AL=["1","9"] 1-based input -> AL=[0,8] 0-based index
mov ah, 6
mul ah ; -> AX = {0,6,12,18,24,30,36,42,48}
add ax, offset nume
cmp ax, numePointer
jnb invalidIndex
mov di, ax
lea si, [di + 6]
mov cx, numePointer
sub cx, si
cld
rep movsb
mov numePointer, di
dec numes
jmp bucla
...
请注意:在删除名字后,您可能会想再次使用lista。确保将numberindex重置为"1"。否则我的代码从我有一个索引问题将不能正常工作:
lista:
mov byte ptr [numeIndex + 2], "1"
...