Sitelet https://github.com/Niphredil123/NASM_Addition
Skip to content

About

A NASM (x86-64) assembly program to add two integer inputs from the user, using custom ASCII-to-integer and integer-to-ASCII conversion functions.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

NASM Addition Calculator

A NASM (x86-64) assembly program to add two integer inputs from the user, using custom ASCII-to-integer and integer-to-ASCII conversion functions.

NASM Version

The program was written using the win64 version, but run using WSL (Ubuntu) and will not work on pure Windows CMD or PowerShell without modification.

Program Overview

When compiled and run, the program will prompt the user to enter a number. The number is converted from ASCII to an integer value by calling a function ascii_to_int. This is stored and a second number is requested, going through the same process. The two numbers are added and this value is converted back to an ASCII value by the function int_to_ascii before being printed to the CLI.
The ascii_to_int functions loops through each digit in an ASCII value from left to right, converting each digit to its integer value. The integer value of the digit is added to a buffer where each loop multiplies the buffer by ten so that the new digit is always added to the empty 'ones column'.
The int_to_ascii function has two loops. The first divides the integer value by ten and converts the remainder digit to an ASCII value before appending it to the buffer. In this manner the digits in the integer value are converted to ASCII digits from right to left and stored in the buffer. This leaves the digits in reverse order so the second loop in the function reverses the order of the buffer before returning to the caller.

Compiling

Requirements

  • Windows Subsystem for Linux (Ubuntu)
  • NASM (win64)
  • ld (GNU linker, available via build-essential)

Compiling

To compile and run the program using the Windows Subsystem for Linux (ubuntu) use the following commands.

nasm -f elf64 basic_addition.asm
ld -o AdditionProg basic_addition.o
./AdditionProg

Program Breakdown

Data Section

Initialised Data

  • Contains messages to be printed in the CLI.
  • equ $- sets the length of the messages.
  • 0dh, 0ah creates a newline in the terminal when printing.

Uninitialised Data

  • Reserving space for the two numbers, the total number, and a buffer for converting to and from ASCII.

Text Section

  • The program is started and prints the prompt for the first number.
  • This is read using syscall before the ascii_to_int function is called to convert the number from ASCII to an integer value.
  • The conversion is done in the EAX register, which is the bottom 32 bits of RAX. RAX is the equivalent 64-bit register in x86-64; however, EAX was used to store numbers because it is not anticipated that the numbers will require more than 32-bits within the scope of this project.
  • The number is stored in the reserved uninitialised data space num1 before the process is repeated for the second number.
  • num1 is moved back into the EAX register and num2 is then added to it, before the resultant number is moved to the reserved total space.
  • The totals message is printed before the function int_to_ascii is called to convert the integer total into ASCII.
  • The int_to_ascii function returns the length of the string in the RAX register. This is used to reserve the number of bytes needed in RDX before setting RAX to 1 for sys_write.
  • The total is printed followed by a newline.
  • The program exits.

ASCII to Integer Function

  • The function ascii_to_int: does what it says on the tin and converts the ASCII input to integers.
  • RCX and RAX are set to 0. RCX will be used as a counter while RAX will be the buffer where the results are stored.
  • The conversion is done in a loop, convert_loop:, converting each digit from left to right.
  • The loop takes the digit at the pointed to address (start of buffer address RSI + counter RCX) and uses movzx to move it to RBX, adding zeros to match the larger destination size.
  • bl is the bottom byte of RBX and contains the digit to be converted. The function checks if it is a newline, 0x0A, escaping the loop if it is, and continuing with the loop if not.
  • Remaining in the RBX register, 48 ('0') is then subtracted from the value of bl to convert from the ASCII decimal value to the matching integer value.
  • Before adding the value from the RBX register, the current value in RAX is multiplied by 10. This effectively moves the digits one place to the left, so that a digit in the 'ones column' moves to the 'tens column'.
  • The value in RBX is then added to RAX, effectively being added to the 'ones column'.
  • The counter RCX is incremented before the function loops and returns to the caller once a newline is detected.
  • The final integer value is in the EAX portion of the RAX register and will be moved to the relevant reserved data space after the function returns to the caller.

Integer to ASCII Function

  • The function int_to_ascii: converts from integer values to ASCII and is used to prepare the total for printing.
  • Prior to the function being called, the total integer value is moved into the EAX register, which is the bottom half of the RAX register.
  • RCX is set to 0 as a counter while RSI is pointed to the start of the buffer.

Convert to ASCII Loop

  • Once again, the function uses a loop for the conversion, convert_to_ascii:.
  • During each loop RDX is used as a scratch register so is cleared ready for use.
  • The RBX value is set to 10 and used to divide the integer value in RAX by 10 with the remainder being stored in RDX.
  • The remainder is whatever value was in the 'ones column' before division and is converted to an ASCII value by adding 48 ('0') before being stored in the next location in the buffer (start point RSI + counter RCX).
  • The counter is then incremented and a comparison done to see if RAX now equals 0, at which point the convert_to_ascii: loop will exit.
  • In this manner, each digit of the total integer is converted to its respective ASCII value and appended to the buffer, RSI, from right to left. This results in the number in the buffer being listed in reverse. i.e. 12345 would be listed in the buffer as 54321.
  • Thus, it is necessary to reverse the order of the digits listed in the buffer and this is done by the second loop, reverse_loop, in the int_to_ascii: function.

Reverse Loop

  • Prior to starting the loop, RDI is pointed to the last digit in the RSI buffer using the counter RCX and dec instruction.
  • Beginning the loop, there is a comparison to check that the end of the number has not been reached.
  • The loop works in from the ends of the number:
    • The first digit in the buffer (at the address of RSI) is moved to the lowest byte, al, of RAX
    • Then the last digit in the buffer(at the address of RDI) is moved to the lowest byte, bl, of RBX.
    • The digit in bl is then moved into the RSI address location, becoming the first digit in the buffer.
    • The digit in al is then moved into the RDI address location, becoming the last digit in the buffer.
    • RSI and RDI are incremented and decremented respectively so that they point to the second digit and the second to last digit.
  • The loop repeats until RSI >= RDI. i.e. the middle of the number has been reached.
  • At this point the loop exits and the function returns to caller with the ASCII number stored in the buffer
  • This looping process is illustrated below for clarity.
Loop byte 1 byte 2 byte 3 byte 4 byte 5 Explanation
Start 5 4 3 2 1 Reverse number in buffer.
RSI points to byte 1 and RDI to byte 5.
First 1 4 3 2 5 Number in buffer after first loop.
RSI now points to byte 2 and RDI to byte 4.
Second 1 2 3 4 5 Number in buffer after second loop.
RSI and RDI both point to byte 3.
Third 1 2 3 4 5 RSI = RDI so exit loop

Identified Issues

No means to check user input is numeric

The program converts a user input from ASCII to an integer. This means that any ASCII digits entered are converted to their decimal value less 48 (the offset of the numeric digits from 0). i.e. m would be read as 61 by the program instead of an error being thrown. Thus, any input will return a value, even if the input was not numeric.
Furthermore, if a user were to enter a float, the program would fail to recognise it, and as such a much larger number would be output, with the decimal point, ., being converted to 254 due to wraparound. e.g. With the current program, 1.0 would have an integer value of 2640.

About

A NASM (x86-64) assembly program to add two integer inputs from the user, using custom ASCII-to-integer and integer-to-ASCII conversion functions.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages