Behavior of read syscall in Assembly (ASM) - linux

I am currently learning the ASM, I have a question about the following code (which compiles)
This code come from this tutorial.
The question is: Why do I have the same behaviour when the fd is egual to 0, 1 or 2 (corresponding to stdin, stdout and stderr), at the indicated line, and when the fd is egual to 3 or more, it does nothing (it skips the scanf).
section .data ;Data segment
userMsg db 'Please enter a number: ' ;Ask the user to enter a number
lenUserMsg equ $-userMsg ;The length of the message
dispMsg db 'You have entered: '
lenDispMsg equ $-dispMsg
section .bss ;Uninitialized data
num resb 5
section .text ;Code Segment
global _start
_start: ;User prompt
mov eax, 4
mov ebx, 1
mov ecx, userMsg
mov edx, lenUserMsg
int 80h
;Read and store the user input
mov eax, 3
mov ebx, 2 ; /!\ QUESTION IS ABOUT THIS LINE /!\
mov ecx, num
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 80h
;Output the message 'The entered number is: '
mov eax, 4
mov ebx, 1
mov ecx, dispMsg
mov edx, lenDispMsg
int 80h
;Output the number entered
mov eax, 4
mov ebx, 1
mov ecx, num
mov edx, 5
int 80h
; Exit code
mov eax, 1
mov ebx, 0
int 80h
We can compile and execute this code with the following command:
$> nasm -f elf64 test.S
$> ld test.o
$> ./a.out
Thank you,

Related

NASM unexpected output when printing

I am new have very small problem with assembly NASM in linux. I made simple program for practice that when you put in the text, it adds simple decoration in form of stars. The expected output is:
*********EXAMPLE*********
instead:
*********EXAMPLE
*********
here is the complete code of the program (long) i have use edb to check the code and check EDX register if it match the len take by the null byte check to print correct number of characters.
section .data
prompt db "Please enter a word (MAX: 10 Characters) : ", 0xa, 0xd
plen equ $ - prompt
stars times 9 db "*"
section .bss
text resb 10
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, prompt
mov edx, plen
int 0x80
mov eax, 3
mov ebx, 0
mov ecx, text
mov edx, 11
int 0x80
xor ecx, ecx
mov esi, text
mov ecx, 0
loop1:
inc ecx
cmp byte [esi + ecx], 0x00
jne loop1
push ecx
jmp printexit
printexit:
mov eax, 4
mov ebx, 1
mov ecx, stars
mov edx, 9
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, text
pop edx
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, stars
mov edx, 9
int 0x80
mov eax, 1
int 0x80

Assembly language taking input from user but displaying output

I wrote this code, it reads the data from user but did not display the output. It is written in Assembly language. I am new to Assembly language. Can somebody please help me in solving this. I shall be very thankful. Thanks in advance. Here is the code:
section .data ;Data segment
userMsg db 'Please enter a number: ' ;Ask the user to enter a number
lenUserMsg equ $-userMsg ;The length of the message
dispMsg db 'You have entered: '
lenDispMsg equ $-dispMsg
section .bss ;Uninitialized data
num resb 5
section .text ;Code Segment
global _start
_start:
;User prompt
mov eax, 4
mov ebx, 1
mov ecx, userMsg
mov edx, lenUserMsg
int 80h
;Read and store the user input
mov eax, 3
mov ebx, 2
mov ecx, num
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 80h
;Output the message 'The entered number is: '
mov eax, 4
mov ebx, 1
mov ecx, dispMsg
mov edx, lenDispMsg
int 80h
;Output the number entered
mov eax, 4
mov ebx, 1
mov ecx, num
mov edx, 5
int 80h
; Exit code
mov eax, 1
mov ebx, 0
int 80h
In typical environments, file descripter 0 stands for standard input, 1 for standard output, and 2 for standard error output.
Reading from standard error output makes no sense for me.
Try changing the program for reading
;Read and store the user input
mov eax, 3
mov ebx, 2
mov ecx, num
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 80h
to
;Read and store the user input
mov eax, 3
mov ebx, 0
mov ecx, num
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 80h
in order to have the system read some data from standard input.
section .data
out1: db 'Enter the number:'
out1l: equ $-out1
out2: db 'The number you entered was:'
out2l: equ $-out2
section .bss
input: resb 4
section .text
global _start
_start:
;for displaying the message
mov eax,4
mov ebx,1
mov ecx,out1
mov edx,out1l
int 80h
;for taking the input from the user
mov eax,3
mov ebx,0
mov ecx,input
mov edx,4
int 80h
;for displaying the message
mov eax,4
mov ebx,1
mov ecx,out2
mov edx,out2l
int 80h
;for displaying the input
mov eax,4
mov ebx,1
mov ecx,input
mov edx,4
int 80h
mov eax,1
mov ebx,100
int 80h

Writing integer to console gives Segmentation Fault

Going from high to low lever language I got to assembly. Now at the very beginning, I wrote a simple age program (I'm not clear how to get system time yet so I just used another input). I get Segmentation Fault (core dumped) after I enter the final input. Here is my code:
section .text
global _start
_start:
mov edx, lenask
mov ecx, ask
mov ebx, 1
mov eax, 4
int 0x80
mov edx, 5
mov ecx, input
mov ebx, 2
mov eax, 3
int 0x80
mov edx, lenask2
mov ecx, ask2
mov ebx, 1
mov eax, 4
int 0x80
mov edx, 5
mov ecx, input2
mov ebx, 2
mov eax, 3
int 0x80
mov eax, input2
mov ebx, input
sub eax, ebx
push eax
mov edx, lenanswer
mov ecx, answer
mov ebx, 1
mov eax, 4
int 0x80
pop eax
mov edx, 7
mov ecx, eax
mov ebx, 1
mov eax, 4
int 0x80
section .data
ask db "What is your age?"
lenask equ $-ask
ask2 db "What is today's year?"
lenask2 equ $-ask2
answer db "The age you were born was: "
lenanswer equ $-answer
section .bss
input resb 5
input2 resb 5
An example of what happens:
What is your age?45
What is today's year?2015
The age you were born was: Segmentation fault
It should have done:
What is your age?45
What is today's year?2015
The age you were born was: 1970
The problem is that int 0x80 with eax set to 4 calls the kernel's sys_write function (i.e. a write system call) which expects a pointer to a string. By providing a integer to the function call the kernel will think that the integer is a pointer to a memory location. Because 1970 is not a valid pointer it will raise a -EFAULT. To bypass this you need to code a ToString function to convert the number to a string and then pass the pointer to the converted string.
The Segmentation Fault itself is caused by not having a sys_exit call. The reason for this is that the program will continue past the end of your code (usally into a bunch of 00 00)

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 ;)

NASM Code In Linux Gives Me Segmentation Fault

I started learning how to write programs using the NASM assembly programming language. I wrote this simple program that prompts the user to enter two numbers and then adds the two operands together. I got it to compile with no errors or warnings, but when it prompts the user for the two numbers and it begins to add the two numbers it prints out segmentation fault and program ends. I know a segmentation fault is the equivalent to an access reading / writing violation exception in the Win32 world. But, because I don't know how to debug NASM code; I can't figure out what is wrong. I suspect it has to do with an invalid pointer; but I don't know. Here is the code below:
section .data
msg1: db 'Please Enter A Number: ', 0
length1: equ $ - msg1
msg2: db 'Please Enter A Second Number: ', 0
length2: equ $ - msg2
section .bss
operand1: resb 255
operand2: resb 255
answer: resb 255
section .text
global _start
_start:
; Print first message
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, length1
int 80h
; Now read value
mov eax, 3
mov ebx, 1
mov ecx, operand1
mov edx, 255
int 80h
; Print second message
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, length2
int 80h
; Now read second value
mov eax, 3
mov ebx, 1
mov ecx, operand2
mov edx, 255
int 80h
; Now add operand1 and operand2 and print answer
mov eax, 4
mov ebx, 1
xor ecx, ecx ; Make the ecx register 0
mov ecx, operand1
add ecx, operand2
mov edx, 510
int 80h
(Aside: you should be reading from STDIN_FILENO = 0, not STDOUT_FILENO = 1. Also, you're writing a NUL character and you shouldn't.)
The problem is that operand1 and operand2 are addresses to memory locations holding characters you've read. When you add them, you get a pointer to invalid memory.
You'll have to convert them to integers, add them, and convert back to a string, before you can write it out.
Value in ecx is an address of string that is to be printed when you call int 80h. Last part does not make sense
mov eax, 4
mov ebx, 1
xor ecx, ecx ; Make the ecx register 0
mov ecx, operand1
add ecx, operand2 ; **<<< invalid memory address now in ECX !!!**
mov edx, 510
int 80h
because you are adding address of string operand1 and address of string operand2 and trying to print whatever is located ant resulting address which is most likely points to nowhere.
To debug your program with gdb you can do:
nasm -f elf64 -g -l q1.lst q1.asm
gcc -o q1 q1.o
I replaced the "_start" with "main" so that gcc won't complain, and you can skip the 64 in "-f elf64" if you are building on 32 bit platform.
gdb q1
Here is an example f gdb session:
(gdb) br main
Breakpoint 1 at 0x4004d0: file q1.asm, line 20.
(gdb) r
Starting program: /home/anonymous/Projects/asm/q1
Breakpoint 1, main () at q1.asm:20
20 mov eax, 4
(gdb) n
21 mov ebx, 1
(gdb) n
22 mov ecx, msg1
(gdb) n
23 mov edx, length1
(gdb) p msg1
$1 = 1634036816
(gdb)

Resources