Accepting/Showing 2 digit integers on Assembly using NASM - linux

I'm currently working on a Assembly project. The code works fine on adding 1 digit integer with 1 digit sum, but when I entered 2 digit integers the program will either exit or return no input.
This is my work so far:
SYS_EXIT equ 1
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
segment .data
msg1 db "Enter the first digit: ",0xA, 0xD
len1 equ $- msg1
msg2 db "Please second digit: " ,0xA, 0xD
len2 equ $- msg2
msg3 db "The sum is "
len3 equ $- msg3
segment .bss
num1 resb 255
num2 resb 255
res resb 255
section .text
global _start
_start:
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num1
mov edx, 255
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num2
mov edx, 255
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 0x80
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [res], eax
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, res
mov edx, 1
int 0x80
;move eax, SYS_EXIT
;int 0x80
exit:
mov eax, SYS_EXIT
xor ebx, ebx
int 0x80
This is my sample input:
Please enter first digit: 5
Please second digit: 2
The sum is: 7
My problem is this:
Please enter first digit: 5
Please second digit: 5
The sum is:
The sum returns 0.

Related

Reading multiple lines of input

What command / function can I use to read the second line in the input section so the 4 and 6 I know I'll have to fix the output to output two digits. I just need helping figuring out how to read the second line of input any help would be greatly appreciated.
SYS_EXIT equ 1
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
segment .data
NEWLINE db 0xa, 0xd
LENGTH equ $-NEWLINE
msg1 db "Enter a digit "
len1 equ $- msg1
msg2 db "Please enter a second digit "
len2 equ $- msg2
msg3 db "The sum is: "
len3 equ $- msg3
segment .bss
INPT resd 1
num1 resb 2
num2 resb 2
res resb 1
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num1
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, num1
mov edx, 2
int 0x80
mov eax, 0x4
mov ebx, 0x1
mov ecx, NEWLINE
mov edx, LENGTH
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num2
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, num2
mov edx, 2
int 0x80
mov eax, 0x4
mov ebx, 0x1
mov ecx, NEWLINE
mov edx, LENGTH
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 0x80
; moving the first number to eax register and second number to ebx
; and subtracting ascii '0' to convert it into a decimal number
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
; add eax and ebx
add eax, ebx
; add '0' to to convert the sum from decimal to ASCII
add eax, '0'
; storing the sum in memory location res
mov [res], eax
; print the sum
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, res
mov edx, 1
int 0x80
exit:
mov eax, SYS_EXIT
xor ebx, ebx
int 0x80
enter image description here

DIV in NASM always return 1

There are my all code:
SYS_EXIT equ 1
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
section .data
msg1 db `\xF0\x9F\x98\x8E`, " Enter the A: "
len1 equ $- msg1
msg2 db `\xF0\x9F\x98\x89`, " Than the B: "
len2 equ $- msg2
msg3 db `\xF0\x9F\x8D\xB0`, " A > B: A / B - 1 = "
len3 equ $- msg3
msg4 db `\xF0\x9F\x8D\xAA`, " A = B: -25"
len4 equ $- msg4
msg5 db `\xF0\x9F\x8D\x95`, " A < B: (B^3 - 5) / A = "
len5 equ $- msg5
section .bss
a resb 32
b resb 32
x resb 32
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, a
mov edx, 32
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, b
mov edx, 32
int 0x80
; Comparing
mov eax, [a]
sub eax, '0'
mov ecx, [b]
sub ecx, '0'
cmp eax, ecx
jg Ab ;A grate than b
je AB ;A and B are equal
jl aB ;a smoller than B
Ab:
cdq
idiv ecx
dec eax
add eax, '0'
mov [x], eax
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, x
mov edx, 32
int 0x80
jmp exit ;go to exit
AB:
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg4
mov edx, len4
int 0x80
jmp exit ;go to exit
aB:
mov eax, ecx
imul ecx
imul ecx
mov ebx, '5'
sub ebx, '0'
sub eax, ebx
mov ecx, [a]
sub ecx, '0'
idiv ecx
add eax, '0'
mov [x], eax
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg5
mov edx, len5
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, x
mov edx, 1
int 0x80
exit:
mov eax, SYS_EXIT
xor ebx, ebx
int 0x80
In 'a' and 'b' I put different number between 0 and 9 but this operation always return 1. I checked out EDX and noticed that processor subtracts ECX from EAX only one times. In EAX he write 1, and in EDX - remainder from subtraction EAX and ECX.
When I enter a = 9 and b = 4 : EAX after dividing = 1 and EDX = 5. If I enter a = 6 and b = 2 : EAX = 1, EDX = 4
What happened?
Presumably there's a newline character (0xA) after each of the digits. So you end up dividing 0xA09 by 0xA04. You could e.g. use movzx eax, byte [a] instead (and similarly for b).

Floating point exception (SIGFPE) when doing weighted average of 4 numbers

I'm creating an assembly language program with NASM on Linux. I'm trying to do a weighted average of 4 numbers where the 4th number entered has double the weighting of the others. If I use the numbers 30, 40, 50, 60, I'm calculating the weighted average as (30+40+50+60+60)/5. My code is:
SYS_EXIT equ 1
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
segment .data
msg1 db "Enter exam grade 1: ", 0xA,0xD
len1 equ $- msg1
msg2 db "Enter exam grade 2: ", 0xA,0xD
len2 equ $- msg2
msg3 db "Enter exam grade 3: ", 0xA,0xD
len3 equ $- msg3
msg4 db "Enter final exam grade (worth double: ", 0xA,0xD
len4 equ $- msg4
msg5 db "The sum is: "
len5 equ $- msg5
segment .bss
num1 resb 3
num2 resb 3
num3 resb 3
num4 resb 3
res resb 4
section .text
global main
main:
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num1
mov edx, 3
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num2
mov edx, 4
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num3
mov edx, 3
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg4
mov edx, len4
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num4
mov edx, 3
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg5
mov edx, len5
int 0x80
mov eax, [num1] ; move num1 to register eax
sub eax, '0' ; sub '0' to convert eax bl from ASCII to decimal
mov ebx, [num2] ; move num2 to register ebx
sub ebx, '0' ; sub '0' to convert ebx from ASCII to decimal
mov ecx, [num3] ; move num3 to register ecx
sub ecx, '0' ; sub '0' to convert ecx from ASCII to decimal
mov edx, [num4] ; move num4 to register edx
sub edx, '0' ; sub '0' to convert edx from ASCII to decimal
add eax, ebx ; add ebx to eax
add eax, ecx ; add ecx to eax
add eax, edx ; add edx to eax
add eax, edx ; add edx to eax again
mov bl, '5' ; sub '0' to convert bl from ASCII to decimal
sub bl, '0' ; make bl a decimal
div bl ; divide by bl
add eax, '0' ; add '0' to convert the sum from decimal to ASCII
mov [res], eax ; storing the sum in memory location res
; print the sum
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, res
mov edx, 3
int 0x80
exit:
mov eax, SYS_EXIT
xor ebx, ebx
int 0x80
I can produce this exception if I enter these numbers:
Enter exam grade 1:
30
Enter exam grade 2:
40
Enter exam grade 3:
50
Enter final exam grade (worth double:
60
The sum is: Floating point exception
What causes my program to display Floating Point Exception (SIGFPE) and how can I fix this?

Comparing 16 bit numbers in nasm produces wrong results

I have just started learning assembly. I am coding nasm in 32 bit mode. I am trying to compare 3 numbers inputted by the user and print the largest number. However, I cannot seem to correctly compare the numbers if I only reserve 16 bits for each number using resb 2. I do, however, get correct results when I reserved 32 bits for the numbers using resw 2. I cannot understand why this is the case. Here is my code:
SYS_EXIT equ 1
SYS_WRITE equ 4
SYS_READ equ 3
STD_IN equ 0
STD_OUT equ 1
segment .data
msg1 db "Enter first number",0xA
msg1_len equ $- msg1
msg2 db "Enter second number",0xA
msg2_len equ $- msg2
msg3 db "Enter third number",0xA
msg3_len equ $- msg3
msg4 db "Largest number is ",0xA
msg4_len equ $- msg4
segment .bss
num1 resb 2
num2 resb 2
num3 resb 2
res resb 2
section .text
global _start
_start:
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg1
mov edx, msg1_len
int 0x80
mov eax, SYS_READ
mov ebx, STD_IN
mov ecx, num1
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg2
mov edx, msg2_len
int 0x80
mov eax, SYS_READ
mov ebx, STD_IN
mov ecx, num2
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg3
mov edx, msg3_len
int 0x80
mov eax, SYS_READ
mov ebx, STD_IN
mov ecx, num3
mov edx, 2
int 0x80
mov ecx, [num1]
cmp ecx, [num2]
jg check_third
mov ecx, [num2]
check_third:
cmp ecx, [num3]
jg result
mov ecx, [num3]
result:
mov [res], ecx
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg4
mov edx, msg4_len
int 0x80
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, res
mov edx, 2
int 0x80
exit:
mov eax, SYS_EXIT
int 0x80
Sorry if it has a lot of repeating code. I understand why I need 2 bytes to store keyboard input when supposedly ascii characters are only 8 bits in length (Since the standard input will also read the new line character aside from the digit). However, I do not know a lot of things about how nasm works such as how it reacts when I move 16 bits of memory to a 32 bit register, how it compares 32 bit and 16 bit values (will it do signed expansion or just pad 0 before binary subtraction). I would truly appreciate it if someone can recommend me resources on the technicalities of nasm aside from explaining why I need to reserve 2 words to do the comparison.
Nasm does not keep record of the size of the data at label like some other assemblers. Suppose you enter 1, 2 and 3. Bytes stored at your labels will then be:
num1: db 0x31, 0x0A
num2: db 0x32, 0x0A
num3: db 0x33, 0x0A
When you move 32 bits of data from label num1, you are actually also moving data from num2. Because little endian machines store least significant bytes first, you get something like:
mov ecx, 0x0A320A31 ; high bytes contain num2 and low bytes contain num1
cmp ecx, 0x0A330A32 ; high bytes contain num3 and low bytes contain num2
jg check_third
mov ecx, 0x0A330A32
check_third:
cmp ecx, 0x00000A33 ; high bytes contain res and low bytes contain num3
jg result
.....
resw 2 (or resd 1) would work because reserved memory is initialized to zeros. As Frank stated in the comment, you should use cl instead of ecx because 8 bits is all you need to handle in this case.

Division in assembly program

this is my code :
section .bss ;Uninitialized data
average resb 5
num1 resb 5
num2 resb 5
num3 resb 5
section .text
global _start ; make the main function externally visible
_start:
;User prompt
mov eax, 4
mov ebx, 1
mov ecx, messaging
mov edx, lenmessaging
int 0x80
;Read and store the user input
mov eax, 3
mov ebx, 0
mov ecx, num1
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, messaging
mov edx, lenmessaging
int 0x80
;Read and store the user input
mov eax, 3
mov ebx, 0
mov ecx, num2
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, userMsg
mov edx, lenUserMsg
int 0x80
;Read and store the user input
mov eax, 3
mov ebx, 0
mov ecx, num3
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 0x80
;Output the message
mov eax, 4
mov ebx, 1
mov ecx, dispMsg
mov edx, lenDispMsg
int 0x80
; moving the first number to eax register and second number to ebx
; and subtracting ascii '0' to convert it into a decimal number
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
; add eax and ebx
add eax, ebx
mov ebx, [num3]
sub ebx, '0'
add eax, ebx
mov bl, '3'
sub bl, '0'
div bl
add eax, '0'
mov [average], eax
;Output the number entered
mov eax, 4
mov ebx, 1
mov ecx, average
mov edx, 5
int 0x80
;////////////////
mov eax, 0x1 ; system call number for exit
sub esp, 4 ; OS X (and BSD) system calls needs "extra space" on stack
int 0x80 ; make the system call
section .data ;Data segment
userMsg db 'Please enter a number: ' ;Ask the user to enter a nu
lenUserMsg equ $-userMsg ;The length of the message
dispMsg db 'The average is : '
lenDispMsg equ $-dispMsg
messaging db 'Enter another number : '
lenmessaging equ $-messaging
when I run it ,I have this error :
how can I fix it?
this program is for calculating the average of three numbers.
thanks ;)

Resources