Author Topic: NASM Assembly - Help on getting function to work correctly  (Read 5773 times)

Offline VGB1526

  • Jr. Member
  • *
  • Posts: 2
NASM Assembly - Help on getting function to work correctly
« on: March 10, 2020, 12:49:10 AM »
Hello, I'm new on assembly and am having problems with a program I am trying to create. The program is supposed to accept 3 inputs from the user which include an arithmetic operation and 2 numbers. The program should then pass the three values and display the answer with a message. I am having trouble getting the program to jump properly as it would display the 2 numbers being used for all the operations and then abruptly end the program instead of just showing the operation the user picked and asking the user if they would like to do another one. Does anyone know how I can solve this problem? Thanks!

Here is the code:
Code: [Select]
%include "CPsub64.inc"

global main, sum, minus, multi, divi ;entry point for assembly

section .text
  main:
  mov rcx, 1
  mov rdi, 1

loop2:

;display
  mov rax, 1
  mov rsi, message
  mov rdx, length
  syscall

;take input
  mov rdx, 255
  mov rcx, userInput1
  mov rbx, 0
  mov rax, 3
  int 80h

;display
  mov rax, 1
  mov rsi, message1
  mov rdx, length1
  syscall

;take input
  mov rdx, 255
  mov rcx, userInput2
  mov rbx, 0
  mov rax, 3
  int 80h

;convert to number
  mov rdx, userInput2
  mov rcx, 255
  call ParseInteger64
  mov r8, rax

;display
  mov rax, 1
  mov rsi, message2
  mov rdx, length2
  syscall

;take input
  mov rdx, 255
  mov rcx, userInput3
  mov rbx, 0
  mov rax, 3
  int 80h

;convert to number
  mov rdx, userInput3
  mov rcx, 255
  call ParseInteger64
  mov r9, rax


;save registers
  push rax
  mov r10, r8
  push r8

  push r9
  call sum

  push rax
  mov r10, r8
  push r8

  push r9
  call minus

  push rax
  mov r10, r8
  push r8

  push r9
  call multi

  push rax
  mov r10, r8
  push r8

  push r9
  call divi


;Set up operator
  mov rsi, 0
  mov rsi, [userInput1]
  push rsi
  cmp sil, '+'
  je add

  mov rsi, 0
  mov rsi, [userInput1]
 
  cmp sil, '-'

  mov rsi, 0
  mov rsi, [userInput1]
 
  cmp sil, '*'

  mov rsi, 0
  mov rsi, [userInput1]
 
  cmp sil, '/'




; jump if addition
  cmp sil, '+'

; jump if subtraction
  cmp sil, '-'
push rsi
  je subtract
 
; jump if multiplication
  cmp sil, '*'
push rsi
  je multiply
 
; jump if division
  cmp sil, '/'
push rsi
  je divide
 

;add
add:

add rsp, 24

;exit
  mov rax, 60
  xor rdi, rdi
  syscall

sum:
;prologue
  push rbp
  mov rbp, rsp

  push rbx

 


  mov r10, r8
  add r10, r9

;display
  mov rax, r8
  call WriteInt
  syscall

;display
  mov rax, 1
  mov rsi, messageadd
  mov rdx, lengthadd
  syscall

;display
  mov rax, r9
  call WriteInt
  syscall

;display
  mov rax, 1
  mov rsi, messageeq
  mov rdx, lengtheq
  syscall

;display answer
  mov rbx, [rbp + 16]
  mov rax, [rbp + 24]
  add rax, rbx
  call WriteInt

;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall




;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall

;display
  mov rax, 1
  mov rsi, messageanswer
  mov rdx, lengthanswer
  syscall

;display answer
  mov rax, r10
  call WriteInt

;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall

;prepare return to main
  pop rbx
  pop rbp
  ret

  jmp loop



;subtract
subtract:

add rsp, 24

;exit
  mov rax, 60
  xor rdi, rdi
  syscall

minus:
;prologue
  push rbp
  mov rbp, rsp

  push rbx

  mov r10, r8
  sub r10, r9

;display
  mov rax, r8
  call WriteInt
  syscall

;display
  mov rax, 1
  mov rsi, messagesub
  mov rdx, lengthsub
  syscall

;display
  mov rax, r9
  call WriteInt
  syscall

;display
  mov rax, 1
  mov rsi, messageeq
  mov rdx, lengtheq
  syscall

;display answer
  mov rax, r10
  call WriteInt

;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall

;display
  mov rax, 1
  mov rsi, messageanswer
  mov rdx, lengthanswer
  syscall

;display answer
  mov rbx, [rbp + 16]
  mov rax, [rbp + 24]
  sub rax, rbx
  call WriteInt

;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall

;prepare return to main
  pop rbx
  pop rbp
  ret
  jmp loop



;multiply
multiply:

add rsp, 24

;exit
  mov rax, 60
  xor rdi, rdi
  syscall

multi:
;prologue
  push rbp
  mov rbp, rsp

  push rbx

  mov rax, r8
  mov rax, r9
  mul rax
   
;display
  mov rax, r8
  call WriteInt
  syscall

;display
  mov rax, 1
  mov rsi, messagemul
  mov rdx, lengthmul
  syscall

;display
  mov rax, r9
  call WriteInt
  syscall

;display
  mov rax, 1
  mov rsi, messageeq
  mov rdx, lengtheq
  syscall

;display answer
  mov rax, r8
  mov rsi, r9
  mul rsi
  call WriteInt

;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall

;display
  mov rax, 1
  mov rsi, messageanswer
  mov rdx, lengthanswer
  syscall

;display answer
  mov rbx, [rbp + 16]
  mov rax, [rbp + 24]
  mul rbx
  call WriteInt

;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall

;prepare return to main
  pop rbx
  pop rbp
  ret
  jmp loop



;divide
divide:

add rsp, 24

;exit
  mov rax, 60
  xor rdi, rdi
  syscall

divi:
;prologue
  push rbp
  mov rbp, rsp

  push rbx

  mov rdx, 0
  mov rax, r8
  mov rax, r9
  div rax
 
;display
  mov rax, r8
  call WriteInt
  syscall

;display
  mov rax, 1
  mov rsi, messagediv
  mov rdx, lengthdiv
  syscall

;display
  mov rax, r9
  call WriteInt
  syscall

;display
  mov rax, 1
  mov rsi, messageeq
  mov rdx, lengtheq
  syscall

;display answer
  mov rdx, 0
  mov rax, r8
  mov rsi, r9
  div rsi
  call WriteInt

;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall

;display
  mov rax, 1
  mov rsi, messageanswer
  mov rdx, lengthanswer
  syscall

;display answer
  mov rbx, [rbp + 16]
  mov rax, [rbp + 24]
  mov rdx, 0
  div rbx
  call WriteInt

;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall

;prepare return to main
  pop rbx
  pop rbp
  ret
  jmp loop


loop:


;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall


;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall

;display
  mov rax, 1
  mov rsi, message3
  mov rdx, length3
  syscall

;take input
  mov rdx, 255
  mov rcx, userInput4
  mov rbx, 0
  mov rax, 3
  int 80h

  mov rsi, 0
  mov rsi, [userInput4]
  cmp sil, 'y'

;jump if answer is yes
  cmp sil, 'y'
  je loop2

;blank
  mov rax, 1
  mov rsi, blank1
  mov rdx, lengthblank
  syscall

;exit
  mov rax, 60
  xor rdi, rdi
  syscall



section .data
;addition message
  message: db "Enter the arithmetic operator (+ - * /):",0,0ah
  length: equ ($-message)

  message1: db "Please enter the 1st number",0,0ah
  length1: equ ($-message1)

  message2: db "Please enter the 2nd number",0,0ah
  length2: equ ($-message2)

  messageadd: db " + ",0
  lengthadd: equ ($-messageadd)

  messagesub: db " - ",0
  lengthsub: equ ($-messagesub)

  messagemul: db " * ",0
  lengthmul: equ ($-messagemul)

  messagediv: db " / ",0
  lengthdiv: equ ($-messagediv)

  messageeq: db " = ",0
  lengtheq: equ ($-messageeq)

  messageanswer: db "The answer is: ",0
  lengthanswer: equ ($-messageanswer)

  message3: db "Would you like to perform another operation? [y = yes / n = no]",0,0ah
  length3: equ ($-message3)

  blank1: db " ",0,0ah
  lengthblank: equ ($-blank1)


;user inputs
section .bss
userInput1: resb 255
userInput2: resb 255
userInput3: resb 255
userInput4: resb 255

Offline vitsoft

  • Jr. Member
  • *
  • Posts: 17
  • Country: cz
    • About me
Re: NASM Assembly - Help on getting function to work correctly
« Reply #1 on: March 14, 2020, 08:47:15 PM »
My recommendation: Do not use int 0x80 in 64bit program.
Get rid of nonsence dead code such as
Code: [Select]
  mov rsi, 0
  mov rsi, [userInput1]
  cmp sil, '-'
  mov rsi, 0
  mov rsi, [userInput1]
Create callable subprocedures for repeatedly used functions.
Make sure they work and only then incrementally extend your program with more functions.
Code: [Select]
Display: ; This subrocedure displays RDX bytes of text adressed with RSI.
   MOV RAX,1 ; sys_write(RDI=descriptor,RSI=text_address,RDX=text_size)
   MOV RDI,1 ; STDOUT_FILENO
   SYSCALL
   RET

TakeInput: ; This subprocedure reads max. RDX characters from keyboard to the address RSI.
   MOV RAX,0 ; sys_read(RDI=descriptor,RSI=buffer_address,RDX=buffer_size)
   MOV RDI,0 ; STDIN_FILENO
   SYSCALL
   RET

main: ; Program entry point.
  LEA RSI,[message]
  MOV RDX,length
  CALL Display
  LEA RSI,[userInput1]
  MOV RDX,255
  CALL TakeInput
... and so on
  CALL Exit