该程序的目的是在切换每个字母的大小写的同时反转给定的字符串。字符串不能超过20个字符,如果输入长度超过20个字符,则程序要求用户再次输入字符串。程序在用户输入“ enter”时结束,并且在打印结束语句后结束。
为此,我有3个问题:
我试图通过调用ReadString来获取输入字符串,并且由于在输入Enter键后此过程停止,因此当我按Enter键正常完成程序时,控制台冻结结束。如何纠正我的代码以使其显示结束消息,然后正常地以返回值0结束程序?
如果输入字符串长于20个字符,则应要求用户再次输入字符串。所以我写了ja L1。 Bur由于某种原因,mov字节数,eax; cmp bytecount,20;似乎无法正确过滤情况。当行mov bytecount,eax被执行时,bytecount的值正确,但是当程序执行下一行cmp bytecount,20时,bytecount的值改变。我不知道我在做什么错。
CaseChange过程在执行时冻结,因此我猜它无限循环,但是我找不到什么条件是错误的。
.data
MaxLength = 20
prompt3 BYTE "End of program",0
buffer BYTE MaxLength DUP(0)
bytecount DWORD ?
.code
main PROC
call Clrscr
L1: mov edx, OFFSET buffer
mov ecx, SIZEOF buffer
call PromptForInput ; printing input prompt
call ReadString
mov bytecount, eax
cmp bytecount, 20 ;*** get input again if number of characters in the string is greater than 20
ja L1 ;***
call ReverseString
call CaseChange ;***
mov edx, OFFSET buffer
call WriteString ;printing the result
loop L1
mov edx, OFFSET prompt3 ;*** after input <ent> how do I print prompt3?
call WriteString
exit
main ENDP
CaseChange PROC
pushad
mov eax, OFFSET buffer
L1:
mov dl, BYTE PTR[eax]
test dl, dl
jz L3
cmp dl, 'A'
jl L3
xor dl,32
cmp dl,'z'
L2:
inc eax
jmp L1
L3:
popad
ret
CaseChange ENDP
(输入提示):猫和狗。
(输出提示):.SGOd DNA STAc
(输入提示):对于给定的限制太长了
(输入提示):
程序结束
答案 0 :(得分:1)
该手册告诉我们 ReadString :
从标准输入中读取最多包含ECX个非空字符串,当用户按下Enter键时停止。
在输入的字符之后会存储一个空字节,但是尾随回车符和换行符不会放入缓冲区。
ECX应该始终小于缓冲区大小(绝不等于缓冲区大小),因为空字节可能是存储的第(ECX + 1)个字符。
在此之后,很明显,您需要扩大缓冲区:
buffer BYTE MaxLength + 1 DUP (0)
如果您指定了ECX=MaxLength
,那么您输入的字符数不能超过 MaxLength 个字符,因此没有必要真正测试这种情况。 (*)
如果用户按 enter 键且没有前面的字符,则 ReadString 将返回EAX=0
。测试一下,然后跳至您的最终消息。
一个大错误是您写loop L1
的地方。 loop
指令与ECX
寄存器一起执行已知数量的迭代。您的程序只需要跳回顶部就没有任何条件。使用jmp L1
。
最好在逻辑上保持一致。请勿将call PromptForInput
与call ReadString
及其参数混合使用。您可以确定 PromptForInput 不会更改EDX
或ECX
吗?
L1: call PromptForInput
mov edx, OFFSET buffer
mov ecx, MaxLength
call ReadString ; -> EAX
test eax, eax
jz L2 ; Exit
call ReverseString ; Is this working fine?
call CaseChange
mov edx, OFFSET buffer
call WriteString ; Printing the result
jmp L1
L2:
mov edx, OFFSET prompt3
call WriteString ; Final message
exit
cmp dl, 'A'
jl L3
ChangeCase 过程需要遍历整个字符串,但是一旦偶然发现一个小于65的字节,您便会离开。请使用 unsigned 条件[在处理ASCII码时[ 0,255]。
xor dl,32
您实际上并没有在字符串存储器中写入任何更改。
cmp dl,'z'
您不会对此进行比较。
如果您需要保留的只是1个寄存器,请不要使用pushad
和popad
。
CaseChange PROC
push esi
mov esi, OFFSET buffer
L1:
lodsb
test al, al ; End of string ?
jz L2
or al, 32 ; If "A".."Z" Then "a".."z"
cmp al, 'a'
jb L1
cmp al, 'z'
ja L1
xor byte ptr [esi-1], 32 ; Change case IN string memory
jmp L1
L2:
pop esi
ret
CaseChange ENDP
(*)如果要强加此“字符串不能超过20个字符”错误,则定义一个更大的缓冲区,并允许 ReadString 返回超过20个字符,以便您可以跳回该程序:
buffer BYTE 99 + 1 DUP (0)
...
L1: call PromptForInput
mov edx, OFFSET buffer
mov ecx, 99
call ReadString ; -> EAX
cmp eax, 20
ja L1
test eax, eax
jz L2 ; Exit
最后的建议是通过独立测试 ReverseString 和 CaseChange 正常:
call ReverseString
;;;call CaseChange
mov edx, OFFSET buffer
call WriteString ; Printing the result
及以后
;;;call ReverseString
call CaseChange
mov edx, OFFSET buffer
call WriteString ; Printing the result
只有这样
call ReverseString
call CaseChange
mov edx, OFFSET buffer
call WriteString ; Printing the result