繁体   English   中英

循环/输入逻辑流程问题(NASM x86汇编)

[英]Loop/Input Logic Flow Issue (NASM x86 Assembly)

我在下面有一个程序试图从用户那里获取输入并重复相同的字符串,直到用户再次输入它。 (这是个人学习项目)

但是,我在使其正确执行方面有一些严重的困难。 此处的过去帖子中,您可以看到其他用户就此问题提供的输入,双关语。

%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

这种情况一直持续到它死亡为止。 关于这个问题的任何想法?

谢谢。

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:
    ...

有更好的方法可以保留长期存在的变量,而不是像使用pushpop那样在堆栈中将它们pop

  1. 将它们保存在数据部分(您已经拥有的.bss将是合适的)而不是堆栈中。

  2. 在堆栈上分配一些空间,并直接在那里加载/存储它们。 例如sub esp, 8保留两个32位字,然后访问[esp][esp+4] (堆栈应该与32位边界对齐,因此始终保留4个字节的倍数。)记住在使用完毕后add esp, 8

(这些基本上相当于C编译器将分别对全局(或static )变量和局部变量执行的操作。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM