我有一个程序,试图从用户那里获取输入并重复相同的字符串,直到用户再次输入。 (这是个人学习项目)
然而,我正在努力使其正确执行。在过去的帖子here中,您可以看到其他用户就此问题提供的输入,双关语。
%include "system.inc"
section .data
greet: db 'Hello!', 0Ah, 'Please enter a word or character:', 0Ah
greetL: equ $-greet ;length of string
inform: db 'I will now repeat this until you type it back to me.', 0Ah
informL: equ $-inform
finish: db 'Good bye!', 0Ah
finishL: equ $-finish
newline: db 0Ah
newlineL: equ $-newline
section .bss
input: resb 40 ;first input buffer
check: resb 40 ;second input buffer
section .text
global _start
_start:
greeting:
mov eax, 4
mov ebx, 1
mov ecx, greet
mov edx, greetL
sys.write
getword:
mov eax, 3
mov ebx, 0
mov ecx, input
mov edx, 40
sys.read
sub eax, 1 ;remove the newline
push eax ;store length for later
instruct:
mov eax, 4
mov ebx, 1
mov ecx, inform
mov edx, informL
sys.write
pop edx ;pop length into edx
mov ecx, edx ;copy into ecx
push ecx ;store ecx again (needed multiple times)
mov eax, 4
mov ebx, 1
mov ecx, input
sys.write
mov eax, 4 ;print newline
mov ebx, 1
mov ecx, newline
mov edx, newlineL
sys.write
mov eax, 3 ;get the user's word
mov ebx, 0
mov ecx, check
mov edx, 40
sys.read
sub eax, 1
push eax
xor eax, eax
checker:
pop ecx ;length of check
pop ebx ;length of input
mov edx, ebx ;copy
cmp ebx, ecx ;see if input was the same as before
jne loop ;if not the same go to input again
mov ebx, check
mov ecx, input
secondcheck:
mov dl, [ebx]
cmp dl, [ecx]
jne loop
inc ebx
inc ecx
dec eax
jnz secondcheck
jmp done
loop:
pop edx
mov ecx, edx
push ecx
mov eax, 4
mov ebx, 1
mov ecx, check
sys.write ;repeat the word
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, newlineL
sys.write
mov eax, 3 ;replace new input with old
mov ebx, 0
mov ecx, check
mov edx, 40
sys.read
jmp checker
done:
mov eax, 1
mov ebx, 0
sys.exit
示例输出将产生:
Hello!
Please enter a word or character:
INPUT: Nick
I will now repeat this until you type it back to me.
Nick
INPUT: Nick
N
INPUT: Nick
INPUT: Nick
这种情况一直持续到它死亡为止。关于这个问题的任何想法?
感谢。
答案 0 :(得分:1)
instruct
在堆栈上留下两个项目,第一次循环时由checker
消耗。但是,对于再次绕过循环的情况,它们不会被替换。这是代码中最基本的问题(可能还有其他问题)。
你可以通过运行调试器并观察堆栈指针esp
来找到它;但只是通过查看代码就可以看出 - 如果除了堆栈操作和分支之外你已经把所有东西都拿出来了,你可以清楚地看到checker
- > loop
- >返回checker
路径弹出三个项目,但只推送一个:
greeting:
...
getword:
...
push eax ;store length for later
instruct:
...
pop edx ;pop length into edx
...
push ecx ;store ecx again (needed multiple times)
...
push eax
checker:
pop ecx ;length of check
pop ebx ;length of input
...
jne loop ;if not the same go to input again
...
secondcheck:
...
jne loop
...
jnz secondcheck
jmp done
loop:
pop edx
...
push ecx
...
jmp checker
done:
...
有更好的方法可以保留长期存在的变量,而不是像push
和pop
一样在堆栈中将它们混乱。
将它们保存在数据部分(您已经拥有的.bss
适合)而不是堆栈中。
在堆栈上分配一些空间,并直接在那里加载/存储它们。例如sub esp, 8
要保留两个32位字,然后访问[esp]
和[esp+4]
。 (堆栈应与32位边界对齐,因此请始终保留4个字节的倍数。)完成使用后,请记得add esp, 8
。
(这些基本上相当于C编译器将分别对全局(或static
)变量和局部变量执行的操作。)