Пропускает один ввод каждый раз после jmp - PullRequest
0 голосов
/ 02 июля 2018

Итак, у меня есть этот код, который должен запросить 2 числа, а затем выполнить некоторые операции с ними, и после завершения одной операции и вывода ответа он должен снова запросить 2 номера и параметр, пока пользователь не выберет параметр выходить. Но по какой-то причине, сразу после печати результата один раз, второй раз он пропускает один ввод.

segment .data

    prompt db "Please enter the first number: "
    promptLen equ $-prompt
    prompt2 db "Please enter the second number: "
    prompt2Len equ $-prompt2
    prompt3 db 10, "Your result is: "
    prompt3Len equ $-prompt3
    linefeed db 10
    menu1 db "Please chose what to do with the numbers: ", 10
    menu1Len equ $-menu1
    menu2 db "1. Add", 10
    menu2Len equ $-menu2
    menu3 db "2. Multiply", 10
    menu3Len equ $-menu3
    menu4 db "3. Divide", 10
    menu4Len equ $-menu4
    menu5 db "4. Nothing, exit.", 10
    menu5Len equ $-menu5
    menu6 db "5. Surprise me"
    menu6Len equ $-menu6
    menu7 db 10, "Selection: "
    menu7Len equ $-menu7

segment .bss

    Num1 resb 8
    Num2 resb 8
    uNum1 resd 1
    uNum2 resd 1
    choice resd 1
    uRes resd 1
    Result resb 8
    ResultLen resd 1

segment .text
    global _start

_start:
    call getNumbers
    call getMenuOption

    mov eax, [choice]
    cmp eax, 49
    je Addition
    cmp eax, 50
    je Multiply
    cmp eax, 51
    je Divide
    cmp eax, 52
    je exit
    cmp eax, 53
    je surprise

getNumbers:
    mov eax, 4
    mov ebx, 1
    mov ecx, prompt
    mov edx, promptLen
    int 80h

    mov eax, 3
    mov ebx, 0
    mov ecx, Num1
    mov edx, 8
    int 80h

    mov esi, Num1
    call dec2eax
    mov [uNum1], eax

    mov eax, 4
    mov ebx, 1
    mov ecx, prompt2
    mov edx, prompt2Len
    int 80h

    mov eax, 3
    mov ebx, 0
    mov ecx, Num2
    mov edx, 8
    int 80h

    mov esi, Num2
    call dec2eax
    mov [uNum2], eax
    ret

dec2eax:                            ; Arg ESI: ASCII-string (0x0A-terminated) with decimal digits
    xor eax,eax                     ; Result
    xor edx, edx                    ; Especially to clear the 32-bit-part of EDX

    .loop:
    mov dl, byte [esi]              ; Read digit
    cmp dl, 10                      ; End of string (SYS_READ - in certain cases not existent)?
    je .finish                      ; Yes: done
    lea eax, [eax*4+eax]            ; EAX = 5 * EAX ...
    add eax, eax                    ;   ... and EAX = 2 * EAX results in EAX = EAX * 10
    add esi, 1                      ; Increment pointer to string
    and dl, 0x0F                    ; Eliminate ASCII part of digit
    add eax, edx                    ; Add digit to result
    jmp .loop                       ; Next character

    .finish:
    ret                             ; Result: Converted unsigned integer in EAX

eax2dec:                            ; Arg EDI: Pointer to string that gets ASCII-characters
    mov ebx, 10                     ; Divisor
    xor ecx, ecx                    ; CX=0 (number of digits)

    .first_loop:
    xor edx, edx                    ; Attention: DIV applies also DX!
    div ebx                         ; DX:AX / BX = AX remainder: DX
    push dx                         ; LIFO
    inc cl                          ; Increment number of digits
    test eax, eax                   ; AX = 0?
    jnz .first_loop                 ; No: once more

    mov ebx, ecx                    ; Save strlen

    .second_loop:
    pop ax                          ; Get back pushed digit
    or al, 00110000b                ; AL to ASCII
    mov byte [edi], al              ; Save AL
    inc edi                         ; DI points to next character in string DECIMAL
    loop .second_loop               ; Until there are no digits left

    mov byte [edi], 0               ; End-of-string delimiter (ASCIZ)
    mov eax, ebx                    ; Return strlen in EAX
    ret

getMenuOption:
    mov eax, 4
    mov ebx, 1
    mov ecx, menu1
    mov edx, menu1Len
    int 80h

    mov eax, 4
    mov ebx, 1
    mov ecx, menu2
    mov edx, menu2Len
    int 80h

    mov eax, 4
    mov ebx, 1
    mov ecx, menu3
    mov edx, menu3Len
    int 80h

    mov eax, 4
    mov ebx, 1
    mov ecx, menu4
    mov edx, menu4Len
    int 80h

    mov eax, 4
    mov ebx, 1
    mov ecx, menu5
    mov edx, menu5Len
    int 80h

    mov eax, 4
    mov ebx, 1
    mov ecx, menu6
    mov edx, menu6Len
    int 80h

    mov eax, 4
    mov ebx, 1
    mov ecx, menu7
    mov edx, menu7Len
    int 80h

    mov eax, 3
    mov ebx, 0
    mov ecx, choice
    mov edx, 1
    int 80h

    ret

Addition:
    xor edx, edx
    mov eax, [uNum1]
    mov ebx, [uNum2]
    add eax, ebx
    mov [uRes], eax

    call printResult

    jmp _start

Multiply:
    xor edx, edx
    mov eax, [uNum1]
    mov ebx, [uNum2]
    mul ebx
    mov [uRes], eax

    call printResult

    jmp _start

Divide:
    xor edx, edx
    mov eax, [uNum1]
    mov ebx, [uNum2]
    div ebx
    mov [uRes], eax

    call printResult

    jmp _start

surprise:
    jmp _start

printResult:
    mov eax, [uRes]
    mov edi, Result
    call eax2dec
    mov [ResultLen], eax

    mov eax, 4
    mov ebx, 1
    mov ecx, prompt3
    mov edx, prompt3Len
    int 80h

    mov eax, 4
    mov ebx, 1
    mov ecx, Result
    mov edx, [ResultLen]
    int 80h

    mov eax, 4
    mov ebx, 1
    mov ecx, linefeed
    mov edx, 1
    int 80h

    ret

exit:
    mov eax, 1
    xor ebx, ebx
    int 80h

Я был бы очень признателен, если бы кто-то указал, что с ним не так, поскольку я очень новичок в этом языке программирования.

Редактировать: вот что происходит, когда я запускаю код.

./menu
Please enter the first number: 3
Please enter the second number: 5
Please chose what to do with the numbers:
1. Add
2. Multiply
3. Divide
4. Nothing, exit.
5. Surprise me
Selection: 1

Your result is: 8
Please enter the first number: Please enter the second number: 3
Please chose what to do with the numbers:
1. Add
2. Multiply
3. Divide
4. Nothing, exit.
5. Surprise me
Selection: 1

Your result is: 3
Please enter the first number: Please enter the second number: 3
Please chose what to do with the numbers:
1. Add
2. Multiply
3. Divide
4. Nothing, exit.
5. Surprise me
Selection: 1

Your result is: 3
Please enter the first number: Please enter the second number: ^C

Так что сразу после прохождения одного jmp назад к _start он пропускает один ввод, но если я уберу «getMenuOption» и просто заставлю его выполнять одну операцию каждый раз, когда он работает нормально.

1 Ответ

0 голосов
/ 02 июля 2018

Кажется, проблема в том, что вы читаете только один символ в конце getMenuOption. Символ новой строки, который вы вводите после выбора в меню, сохраняется в буфере ввода до вызова getNumbers, что приводит к автоматическому пустому вводу первого числа.

Простое решение - прочитать более одного символа в getMenuOption.

...