1

I writing a simple calculator in Assembly x86 with Linux system calls, everything work's great but i have a problem with displaying my calculation result. I checked my code two times and don't know what's wrong with my code.

section .data                           ;Data segment

   firstNumberMsg db 'Please give the first number: ' ;Ask the user for first number to calculate
   lenFirstNumberMsg equ $-firstNumberMsg            ;The length of the message

   secondNumberMsg db 'Please give the second number: ' ;Ask the user for second number to calculate
   lenSecondNumberMsg equ $-secondNumberMsg      ;The length of the message

   signMsg db 'Please give the calculation sign: ' ;Ask the user for calculation type
   lenSignMsg equ $-signMsg      ;The length of the message

   resultMsg db 'Result: ', 0xA, 0xD
   lenResultMsg equ $-resultMsg                 

section .bss
   first resb 5
   second resb 5
   result resb 10
   sign resb 1
    
section .text 
   global _start

exit:                   ;Exit from program
   mov eax, 1
   mov ebx, 0
   int 80h

equalsSignSum:
   ;sum system
   xor eax, eax; set result to zero
   add eax, first ; add first to result
   add eax, second ; add second to result
   mov [result], eax

   ;display result section
   mov eax, 4
   mov ebx, 1
   mov ecx, resultMsg
   mov edx, lenResultMsg
   int 80h  

   ;display the result number
   mov eax, 4
   mov ebx, 1
   mov ecx, [result]
   mov edx, 10
   int 80h

   jmp exit

_start:                ;Display the first prompt for entering a number 
   mov eax, 4
   mov ebx, 1
   mov ecx, firstNumberMsg
   mov edx, lenFirstNumberMsg
   int 80h

   ;Read stdin from user (as a first number)
   mov eax, 3
   mov ebx, 2
   mov ecx, first
   mov edx, 5          ;5 bytes (numeric, 1 for sign) of that information
   int 80h

   ;Display the second prompt for entering a number
   mov eax, 4
   mov ebx, 1
   mov ecx, secondNumberMsg
   mov edx, lenSecondNumberMsg
   int 80h

   ;Read stdin from user (as a second number)
   mov eax, 3
   mov ebx, 2
   mov ecx, second
   mov edx, 5          ;5 bytes (numeric, 1 for sign) of that information
   int 80h

   ;Display the sign prompt
   mov eax, 4
   mov ebx, 1
   mov ecx, signMsg
   mov edx, lenSignMsg
   int 80h

   ;Read stdin from user (as a sign)
   mov eax, 3
   mov ebx, 2
   mov ecx, sign
   mov edx, 1   ;1 byte of length (we need to get a character as sign)
   int 80h

   ;Calculation sign section
   mov ebx, 43      ;43 is '+' in ascii
   cmp [sign], ebx
   je equalsSignSum ;jump to this label if user entered '+' as sign
   ;else
    
   ; Exit code
   mov eax, 1
   mov ebx, 0
   int 80h

I have this code and assembling with nasm -f elf calculator.asm && ld -m elf_i386 -s -o calculator calculator.o && ./calculator

And everything dones without any errors, but when i launch my program with this input:

Please give the first number: 10
Please give the second number: 5
Please give the calculation sign: +
Result: 

The Result line don't gives me the result of this calculation, i want to get Result: 15, i get nothing. I don't know why it doesn't working.

p1oXYZ
  • 84
  • 1
  • 7
  • 4
    You forgot to convert from and to text. Also `write` needs an address not a value, so `mov ecx, [result]` is wrong. Conversely, you need to add the values but you add the addresses. Characters are 1 byte each so `cmp [sign], ebx` is wrong too. – Jester Aug 30 '20 at 10:46
  • But `cmp [sign], ebx` works, and when i insert another character for example. *, the program stops action. You don't explained where i must to "convert" from and to text. I don't know more, before i put this post – p1oXYZ Aug 30 '20 at 13:44
  • This time, i only get: ` Please give the first number: 15 Please give the second number: 5 Please give the calculation sign: + Result: �@ ` As the calculation result, after converting it with unicode/ascii converter to decimal i don't get my answer of this calculation – p1oXYZ Aug 30 '20 at 13:44
  • 1
    In programming in general, but assembly in particular, just because something works once under special conditions doesn't mean the code is correct. `cmp [sign], ebx` is comparing 4 bytes not 1. You are just lucky that the other 3 match. If you had something else in memory after `sign` those bytes could very well no longer be zero. You need to convert from text (ascii) to number before the addition and back after the addition or implement arbitrary length ascii addition. – Jester Aug 30 '20 at 14:00
  • Okay but why i always get `�@` as result whatever i give as input for numbers? i get that after changing `mov ecx, [result]` to `mov ecx, result`. I only wan't to repair the result problem. After this i repair all problems after this to get good code. – p1oXYZ Aug 30 '20 at 14:04

1 Answers1

3

When you read your first number, the value is stored into a memory location (pointed to by your label "first"). You reserved 5 bytes for it. Then, there are five more bytes for storing the second value. In a memory dump (hex), they will look like this:

first:  0804a06c: 31 30 0a 00 00
second: 0804a071: 35 0a 00 00 00

They are not numbers, but codes for the graphical symbols that represent those numbers in a writing system. The writing system depends on the console the user is running. Unicode values for numbers are the same as per the ASCII table. The hexadecimal number 31 means '1', 30 means '0' and 0a is the ASCII char for 'enter'. The same as what was typed into the console. And there are in a decimal (base10) system, while your processor works only in binary.

Your "first" variable is holding the following bytes: '1', '0', 'enter', 0, 0. The intended meaning is the decimal value 10 that is equivalent to ten units for the first position and zero single units for the second position. Similarly, the "second" variable holds five single units. The expected result should be ten units in the first position and five units in the second position. Your result value should have at least the following bytes: '1', '5'. Let's see how that look from the processor's point of view:

base10    base2
10        1010
 5        0101
 +
15        1111

What your code is currently doing is adding the number of the memory location for the first argument to the memory location of the second and then displaying the result number as if there were character codes. In the current run, it added the following hex numbers: 0804a06c + 0804a071. However, if you fix your code, you will be adding 0a3031 + 000a35 and that is not what you intended to do.

Then, in order to do any math operation on those numbers, you need first to 'convert' them in binary numbers. Here it will depend on the type of operations that you want to perform. Implementation is totally different for floating point numbers and for natural numbers (integers). The size of the operands will change also the implementation. Then, multiplication and division are slightly more complicated than addition and subtraction.

To convert from ASCII to int, you could use the 'atoi' function from an assembly library. Make your own implementation for integers first and only then go for floating point numbers.

And remember: in order to show the result, you need to convert it into the ASCII representation in order to permit the console displaying the proper graphical symbols that represent the number.

J. Pelaez
  • 86
  • 4
  • 2
    There's a canonical Q&A for converting a multi-digit ASCII string to a binary integer in a register: [NASM Assembly convert input to integer?](https://stackoverflow.com/q/19309749). And for printing (turning integers back into base-10 ASCII strings): [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) – Peter Cordes Aug 30 '20 at 20:26
  • " And there are in a decimal (base10) system". I can't quite see how this sentence fits in your text. Everything above this line is in hexadecimal notation. Maybe you could reword it and explain it more. – Sep Roland Aug 30 '20 at 20:59
  • 1
    @SepRoland: good point, it might not be clear for people who didn't already have a clear understanding. It's a hexdump of ASCII codes that represent a number as a text string of base10 digits. – Peter Cordes Aug 30 '20 at 23:09