0

Thanks in advance for any assistance. This issue has been driving me crazy. So Ive got a little calculator application that asks for the users name, asks for 2 numbers, asks if they want to Add/Sub/Mul/Div, prints out the answer and then asks if they want to do it again. Well, everything works perfectly until I get to the part that asks if they want to do it again. When we get to this point, the system prints the question, but does not wait for a response. The code is pretty well the same for all user input, so Im incredibly confused as to what the issue is. Ive included the code below and highlighted the function that is the issue. Youll see that there are others that are pretty well exactly the same, and they have no issues. Anyway, here it is.

; "Hello World!" in 64 bit Linux NASM

global _start            ; global entry point export for ld

section .text
_start: 
    ; sys_write(stdout, message, length) 
    nop
    mov     rax, 4          ; sys_write syscall
    mov     rbx, 1          ; std_out
    mov     rcx, inputMsg  ; message address
    mov     rdx, input_L    ; message string length
    int     80h

    ; grab user input   
    mov     rax, 3          ; sys_read syscall
    mov     rbx, 0          ; std_in
    mov     rcx, userIn     ; output to username
    mov     rdx, 16         ; accept 16 bytes
    int     80h

    ; say hello 
    mov     rax, 4          ; sys_write
    mov     rbx, 1          ; std_out
    mov     rcx, helloMsg
    mov     rdx, helloMsg_L
    int     80h

    ; print users name
    mov     rax, 4
    mov     rbx, 1
    mov     rcx, userIn
    mov     rdx, 16
    int     80h

_calc:
    ; ask for first number
    mov     rax, 4
    mov     rbx, 1
    mov     rcx, numMsg1
    mov     rdx, numMsg1_L
    int     80h

    ; grab first number
    mov     rax, 3
    mov     rbx, 2
    mov     rcx, num1
    mov     rdx, 8
    int     80h

    ; ask user for second number
    mov     rax, 4
    mov     rbx, 1
    mov     rcx, numMsg2
    mov     rdx, numMsg2_L
    int     80h

    ; grab second number
    mov     rax, 3
    mov     rbx, 2
    mov     rcx, num2
    mov     rdx, 8
    int     80h

    ; ask user what function they want to do 1=add, 2=sub, 3=mul, 4=div
    mov rax, 4
    mov rbx, 1
    mov rcx, function
    mov rdx, function_L
    int 80h

    ; get what function user wants to do
    mov     rax, 3
    mov rbx, 2
    mov rcx, func
    mov rdx, 1
    int 80h

    ; go to appropriate label
    mov rax, [func]
    sub rax, '0'
    cmp rax, 1
    je  _add
    cmp rax, 2
    je  _sub
    cmp rax, 3
    je  _mul
    cmp rax, 4
    je  _div

_sum:
    ; display sum
    mov     rax, 4          ; sys_write
    mov     rbx, 1          ; std_out
    mov     rcx, sum
    mov     rdx, 16
    int     80h

    ; ask user if they want to enter more numbers
    mov rax, 4
    mov rbx, 1
    mov rcx, inMsg2
    mov rdx, inMsg2_L
    int     80h

    ;get answer
    mov rax, 3
    mov rbx, 2
    mov rcx, response
    mov rdx, 1
    int     80h

    mov rax, [response]
    sub rax, '0'
    cmp rax, 1
    je  _calc
    jmp _end

_add:
    ; add numbers
    mov     rax, [num1]     ; move first number into rax
    sub     rax, '0'        ; sub '0' to convert ascii to decimal
    mov     rbx, [num2]     ; move second number into rbx
    sub     rbx, '0'        ; sub ascii '0' to convert to decimal
    add     rax, rbx        ; add rbx to rax
    add     rax, '0'        ; add ascii '0' to convert to ascii
    mov     [sum], rax      ; move the sum to a temp variable
    jmp _sum

_sub:
    ; subtract numbers
    mov     rax, [num1]     ; move first number into rax
    sub     rax, '0'        ; sub '0' to convert ascii to decimal
    mov     rbx, [num2]     ; move second number into rbx
    sub     rbx, '0'        ; sub ascii '0' to convert to decimal
    sub     rax, rbx        ; add rbx to rax
    add     rax, '0'        ; add ascii '0' to convert to ascii
    mov     [sum], rax      ; move the sum to a temp variable
    jmp _sum

_mul:
    ; multiply numbers
    mov     rax, [num1]     ; move first number into rax
    sub     rax, '0'        ; sub '0' to convert ascii to decimal
    mov     rbx, [num2]     ; move second number into rbx
    sub     rbx, '0'        ; sub ascii '0' to convert to decimal
    imul    rax, rbx        ; multiply rbx to rax
    add     rax, '0'        ; add ascii '0' to convert to ascii
    mov     [sum], rax      ; move the sum to a temp variable
    jmp _sum

_div:
    ; devide numbers
    mov     rax, [num1]     ; move first number into rax
    sub     rax, '0'        ; sub '0' to convert ascii to decimal
    mov     rbx, [num2]     ; move second number into rbx
    sub     rbx, '0'        ; sub ascii '0' to convert to decimal
    idiv    rbx     ; divide rbx to rax
    add     rax, '0'        ; add ascii '0' to convert to ascii
    mov     [sum], rax      ; move the sum to a temp variable
    jmp     _sum

_end:
    ; sys_exit(return_code) 
    mov     rax, 1        ; sys_exit syscall
    mov     rbx, 0        ; return 0 (success)
    int     80h

section .data
    helloMsg:   db  'Hello, '       ; message and newline
    helloMsg_L:     equ     $-helloMsg           ; 
    inputMsg:   db  'Enter your name: '  ; message telling user to input name
    input_L:    equ     $-inputMsg
    numMsg1:    db  'Enter number 1: '  ; message telling user to inpt first number
    numMsg1_L:  equ     $-numMsg1
    numMsg2:    db  'Enter number 2: '  ; message telling user to input second number
    numMsg2_L:  equ     $-numMsg2
    function:   db  'Select function: ADD(1), SUB(2), MUL(3), DIV(4) '
    function_L:     equ     $-function
    inMsg2:     db  'Run again? YES(1), NO(0) '
    inMsg2_L:   equ $-inMsg2
    sumMsg:     db  'The sum is: '
    sumMsg_L:   equ $-sumMsg

section .bss
    userIn:     resb    16
    num1:       resb    8
    num2:       resb    8
    sum:        resb    16
    func:       resb    2
    response:   resb    2

So the bolded section is where the issue is, at least where I think it is. Basically it just skips over this, or seems like its skipping over it. The previous function displays the question but then doesnt wait for a response and, because we cannot enter anything, it just ends.

Thanks again for any help,

Brad.

Oh, and I hope that it turns out to be something really stupid that Ive just overlooked.. I can deal with being stupid Lol, I just want this to work.

EDIT: When I debug this with GDB, there is no issue, so unfortunately debugging is no help..

EDIT2: Just realized that it didnt actually bold that section but rather just put ** before and after.. I guess to simplify, for those that dont want to read all the code, this is the function, or system call, that seems to be not functioning correctly.

; ask user if they want to enter more numbers
    mov rax, 4
    mov rbx, 1
    mov rcx, inMsg2
    mov rdx, inMsg2_L
    int     80h

    ;get answer
    mov rax, 3
    mov rbx, 2
    mov rcx, response
    mov rdx, 1
    int     80h

    mov rax, [response]
    sub rax, '0'
    cmp rax, 1
    je  _calc
    jmp _end

and then there is this one, that does function.

; ask user what function they want to do 1=add, 2=sub, 3=mul, 4=div
    mov rax, 4
    mov rbx, 1
    mov rcx, function
    mov rdx, function_L
    int 80h

    ; get what function user wants to do
    mov     rax, 3
    mov rbx, 2
    mov rcx, func
    mov rdx, 1
    int 80h

    ; go to appropriate label
    mov rax, [func]
    sub rax, '0'
    cmp rax, 1
    je  _add
    cmp rax, 2
    je  _sub
    cmp rax, 3
    je  _mul
    cmp rax, 4
    je  _div

So again, why one works and the other doesnt escapes me at this point, and I have debugged the code, which unfortunately has not really given me any insite into what the issue is.

EDIT3:

This is what I get when I run it.

h**p@h**p-VirtualBox:~/Programming$ ./helloInput64
Enter your name: brad
Hello, brad
Enter number 1: 2
Enter number 2: 3
Select function: ADD(1), SUB(2), MUL(3), DIV(4) 1
The sum is: 5Run again? YES(1), NO(0) h**p@h**p-VirtualBox:~/Programming$

So after it prints the sum it just totally goes stupid. Prints the next string on the same line and just ends without grabbing user input..

13
  • 2
    By the way I think your code would be a lot prettier if you'd actually make your functions actual functions using call and ret instead of jmp. Commented Feb 12, 2016 at 21:26
  • 2
    @lurker I tried to tell him that about reading the one byte in the buffer and leaving the newline, but he is convinced that has nothing to do with the problem. A minimal complete example of the input issue can be reduce to 2 inputs where the first one reads a single character. I removed everyone of my comments because of his attitude. And I mentioned response, and it applies to num and num2 as well. I hope you can convince him. I was able to fix his entire program but there is no way I'm going to post it as an answer. Commented Feb 13, 2016 at 16:44
  • 1
    You said So after it prints the sum it just totally goes stupid. Prints the next string on the same line and just ends without grabbing user input... It did grab the input. It grabbed the Newline (Linefeed=LF) character that was remaining in the buffer when you did the Select function input. The leftover LF in the buffer was used as input to the next prompt. The LF character would then be the sole input on the next prompt (like you just hit ENTER for the response). You then compare the LF with 0 and 1, it doesn't match so it exits. Commented Feb 13, 2016 at 17:22
  • 1
    As an experiment, watch what happens if you change mov rcx, func mov rdx, 1 int 80h to mov rcx, func mov rdx, 2 int 80h . Then make a similar change for the code that gets response. Commented Feb 13, 2016 at 17:29
  • 1
    @MichaelPetch, Teach a man to fish. :) :p Commented Feb 19, 2016 at 20:28

1 Answer 1

1

Thank you Michael Petch for getting me on the right track. Your last comment, advising to chance mov rdx, 1 to mov rdx, 2 got me going the right way. Had to do a couple more little tweaks but its now functioning as I would expect. Since I read in 2 bytes, one of which is a linefeed (Again thank you Michael), I then just cmp against AL, which seemed to do the trick.

Thanks again.

;get answer
mov eax, 3
mov ebx, 0
mov ecx, response
mov edx, 2
int     80h

mov eax, [response]
sub al, '0'
cmp al, 1
je  _calc
jmp _end
Sign up to request clarification or add additional context in comments.

1 Comment

If you only want the first byte of input, normally you'd do movzx eax, byte [response]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.