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

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Brad Bass
  • 361
  • 1
  • 4
  • 15
  • 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. – S.Klumpers Feb 12 '16 at 21:26
  • @Lurker, Lol yes that was a typo. Right now it just works with single digit numbers. was not really worried about getting too fancy with it right away. The issue that Im having, which I guess youre just reiterating, is that it doesnt wait for a response and just exits.. so I guess youre either just reiterating the issue or you didnt read what my issue is. Anyway, everything is working fine except for that last function and Ive stepped through it many times, so no, it doesnt have more issues than just not repeating properly. – Brad Bass Feb 12 '16 at 21:44
  • @S.Klumpers, it definitely would be prettier, but this was a super simple, super quick little project. I do appreciate the input though. – Brad Bass Feb 12 '16 at 21:46
  • I thank everyone for the input but you are all missing the actual issue Im having. Its not even grabbing user input when I ask if they want to run again. Every other time I grab user input it works fine except for this one spot and all I want to know is why. – Brad Bass Feb 13 '16 at 08:46
  • updated the code. Had to change the registers as Im on a different machine. I gave a more in depth example of what my issue is as well, in EDIT2. – Brad Bass Feb 13 '16 at 08:55
  • 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. – Michael Petch Feb 13 '16 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. – Michael Petch Feb 13 '16 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`. – Michael Petch Feb 13 '16 at 17:29
  • @MichaelPetch, Its not that I was convinced that it was something else, but rather that I was not convinced that it wasnt. I asked a couple times that if this input was the issue, then why were all the others seemingly fine.. It would have been quite easy to answer that and maybe explain why the others seemed to function fine but the response did not. As it is now, thanks to your last comment, Ive managed to correct the issue and get it running as I would expect it to. – Brad Bass Feb 16 '16 at 21:22
  • My very first comments that I actually gave (that I removed after your attitude worsened) actually pointed out the same thing. Originally I told you to change all the points in your code where you read one character and read 2. That was deleted and then I spelled out the experiment by actually telling you what lines to change. When I originally suggested the problem was with reading one character you told us "I thank everyone for the input but you are all missing the actual issue Im having. Its not even grabbing user input when I ask if they want to run again. " . – Michael Petch Feb 16 '16 at 21:40
  • We knew exactly what problem you were having. I originally took your code and within a few minutes of seeing you post your question, I had a workable solution. I usually sit on posting code dumps in the hope that the person asking a question can learn with some guidance without necessarily giving them everything on a platter. What I appreciate though is that you eventually did take my advice (and lurker's advice which is now deleted) and discovered the solution on your own. That is far more valuable. – Michael Petch Feb 16 '16 at 21:42
  • 1
    @MichaelPetch, Teach a man to fish. :) :p – Brad Bass Feb 19 '16 at 20:28
  • See [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730) re: why you should either use `syscall` with 64-bit call-numbers and registers in 64-bit code (using registers like RDX), or assemble as 32-bit and stick to 32-bit stuff when using `int 0x80`. – Peter Cordes May 04 '23 at 12:32

1 Answers1

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
Brad Bass
  • 361
  • 1
  • 4
  • 15