反转和更改给定字符串 x86 程序集的大小写
Reversing and changing case of a given string x86 assembly
这个程序的objective是在转换每个字母的大小写的同时反转给定的字符串。字符串不能超过 20 个字符,如果输入超过 20 个字符,程序会要求用户重新输入字符串。当用户输入 'enter' 并打印结束句后程序结束。
实现这个我有 3 个问题:
我尝试使用调用 ReadString 获取输入字符串,并且由于此过程在给出回车键时停止,所以当我按回车键正常完成程序时,控制台冻结结束。我如何更正我的代码以使其打印结束消息,然后使用 return 值 0 正常结束程序?
如果输入的字符串超过20个字符,需要用户重新输入。所以我写了ja L1。 Bur 由于某种原因,mov bytecount,eax; cmp字节数,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
(输入提示):对于给定的限制来说太长了
(输入提示):
节目结束
手册告诉我们 ReadString:
Reads a string of up to ECX non-null characters from standard input, stopping when the user presses the Enter key.
A null byte is stored following the characters input, but the trailing carriage return and line feed characters are not placed into the buffer.
ECX should always be smaller than the buffer size (never equal to the buffer size) because the null byte could be the (ECX+1)th character stored.
接下来可以清楚地看到您需要扩大缓冲区:
buffer BYTE MaxLength + 1 DUP (0)
如果您指定了 ECX=MaxLength
,那么您无法获得超过 MaxLength 个字符的输入,因此没有真正需要测试这种情况。 (*)
如果用户按下没有前导字符的 enter 键,则 ReadString 将 return 与 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
(*) 如果你想强加这个 "String cannot be longer than 20 characters" 错误然后定义一个更大的缓冲区并允许 ReadString 到 return 超过 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
这个程序的objective是在转换每个字母的大小写的同时反转给定的字符串。字符串不能超过 20 个字符,如果输入超过 20 个字符,程序会要求用户重新输入字符串。当用户输入 'enter' 并打印结束句后程序结束。
实现这个我有 3 个问题:
我尝试使用调用 ReadString 获取输入字符串,并且由于此过程在给出回车键时停止,所以当我按回车键正常完成程序时,控制台冻结结束。我如何更正我的代码以使其打印结束消息,然后使用 return 值 0 正常结束程序?
如果输入的字符串超过20个字符,需要用户重新输入。所以我写了ja L1。 Bur 由于某种原因,mov bytecount,eax; cmp字节数,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
(输入提示):对于给定的限制来说太长了
(输入提示):
节目结束
手册告诉我们 ReadString:
Reads a string of up to ECX non-null characters from standard input, stopping when the user presses the Enter key.
A null byte is stored following the characters input, but the trailing carriage return and line feed characters are not placed into the buffer.
ECX should always be smaller than the buffer size (never equal to the buffer size) because the null byte could be the (ECX+1)th character stored.
接下来可以清楚地看到您需要扩大缓冲区:
buffer BYTE MaxLength + 1 DUP (0)
如果您指定了 ECX=MaxLength
,那么您无法获得超过 MaxLength 个字符的输入,因此没有真正需要测试这种情况。 (*)
如果用户按下没有前导字符的 enter 键,则 ReadString 将 return 与 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
(*) 如果你想强加这个 "String cannot be longer than 20 characters" 错误然后定义一个更大的缓冲区并允许 ReadString 到 return 超过 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