简体   繁体   中英

Loop/Input Logic Flow Issue (NASM x86 Assembly)

I have a program below that tries to take input from the user and repeat that same string until the user enters it again. (It's a personal learning project)

However, I am having some severe diffuculty in getting it to perform correctly. In a past thread here , you can see the input, pun intended, that other users have provided on this problem.

%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

Example output would yield:

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

And that goes on forever until is ^C it to death. Any ideas on the problem?

Thanks.

instruct leaves two items on the stack, which are consumed by checker the first time round the loop. But they are not replaced for the case where you go round the loop again. This is the most fundamental problem in your code (there may be others).

You could find this by running with a debugger and watching the stack pointer esp ; but it can be seen just by looking at the code -- if you take everything out except for the stack manipulation and branches, you can clearly see that the checker -> loop -> back to checker path pops three items but only pushes one:

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

There are better ways to keep long-lived variables than trying to shuffle them around on the stack like this with push and pop .

  1. Keep them in a data section (the .bss you already have would be suitable) instead of on the stack.

  2. Allocate some space on the stack, and load/store them there directly. eg sub esp, 8 to reserve two 32-bit words, then access [esp] and [esp+4] . (The stack should be aligned to a 32-bit boundary, so always reserve a multiple of 4 bytes.) Remember to add esp, 8 when you've finished using it.

(These are essentially the equivalent of what a C compiler would do for global (or static ) variables, and local variables, respectively.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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