How can i compare the user input with some constant 1, 2 like a switch case in assembly (NASM)? - linux

In the question below, i saw how to do a compare between user input and some option specified by the programmer.
Calculator in Assembly Language - Linux x86 & NASM - Division
But in my case isn't work.
Here is the peace of my code.
section .data
msgTes db 'NEW ELEMENT'
msgTes_len equ $-msgTes
section .bss
opt resb 2
.
.
.
new_element: ; option one is a new element
push ebp
mov ebp, esp
mov eax, 4
mov ebx, 1
mov ecx, msgTes
mov edx, msgTes_len
int 80h
pop ebp
ret
read_option:
push ebp
mov ebp, esp
mov eax, 3 ; reading the option
mov ebx, 0
mov ecx, opt
mov edx, 2
int 80h
mov ah, [opt] ; which option the user entered?
sub ah, '0'
cmp ah, 1
je new_element
pop ebp
ret
There is a menu with the options, but is irrelevant for the question.
Why the message "NEW ELEMENT" isn't printed?

Related

Learning assembly. how to make code faster

I started to learn assembly some days ago and i write my first ever piece of code using user input, string functions, passing arguments by stack or by register etc...
I have some questions. Do you have some advices to make my code faster. For example, in my atoi function, i know that imul is time consuming. Maybe, there are enormous mistakes but as far as i know, many things to improve for sure. So my main question is : are there fatal errors in this first code and my second is : any type to refactoring code with faster instructions
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
%macro printm 2
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, %1
mov edx, %2
int 0x80
%endmacro
%macro prolog 0
push ebp,
mov ebp, esp
%endmacro
%macro epilog 0
mov esp, ebp
pop ebp
%endmacro
section .text
global _start
_start:
; first check if our strlen proc works
push dword msgbegin
call strlen
add esp, byte 4
cmp eax, lenbegin
je .suite ; it works, we continue
; exiting prog if the len computed in rax != lenbegin
mov eax, 1
int 0x80
.suite:
; check if strcpy works printing res (msgbegin -> srcdst)
push dword lenbegin
push dword msgbegin
push dword strdst
call strcpy
add esp, byte 12
push dword lenbegin
push dword strdst
call print
add esp, byte 8
; first input
printm msgbinp1, leninp1
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num1
mov edx, 2
int 0x80
printm msgbinp2, leninp2
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num2
mov edx, 2
int 0x80
printm msgbinp3, leninp3
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, bignum
mov edx, 4
int 0x80
mov edx, bignum
call atoi
cmp eax, 123
je .success ; exit if bignum != 123
mov eax, 1
int 0x80
.success:
; need to strip line feed from bignum
printm bignum, 4
printm msgoutp, lenoutp
; now we compute the sum
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [sum], eax
printm msgres, lenres
; we print it
printm sum, 1
; exiting the programm
mov eax, 1
int 0x80
print:
push ebp
mov ebp, esp
mov eax, 4
mov ebx, 1
mov ecx, [ebp + 8]
mov edx, [ebp + 12]
int 0x80
mov esp, ebp
pop ebp
ret
strcpy:
push ebp
mov ebp, esp
mov ecx, [ebp + 16]
mov esi, [ebp + 12]
mov edi, [ebp + 8]
rep movsb
mov esp, ebp
pop ebp
ret
strlen:
push ebp
mov ebp, esp
push edi
push ecx
mov edi, [ebp + 8]
sub ecx, ecx
sub al, al
not ecx
cld
repne scasb
not ecx
lea eax, [ecx] ; keep null term in size
pop ecx
pop edi
mov esp, ebp
pop ebp
ret
atoi:
xor eax, eax ; zero a "result so far"
.top:
movzx ecx, byte [edx] ; get a character
inc edx ; ready for next one
cmp ecx, '0' ; valid?
jb .done
cmp ecx, '9'
ja .done
sub ecx, '0' ; "convert" character to number
imul eax, 10 ; multiply "result so far" by ten
add eax, ecx ; add in current digit
jmp .top ; until done
.done:
ret
section .data
msgbegin db "hello everyone !", 0xa, 0
lenbegin equ $ - msgbegin
msgbinp1 db "Enter a digit : ", 0xa, 0
leninp1 equ $ - msgbinp1
msgbinp2 db "Enter second digit : ", 0xa, 0
leninp2 equ $ - msgbinp2
msgbinp3 db "Enter third digit : ", 0xa, 0
leninp3 equ $ - msgbinp3
msgoutp db "is equal to 123 !", 0xa, 0
lenoutp equ $ - msgoutp
msgres db "sum of x and y is ", 0xa, 0
lenres equ $ - msgres
strdst times lenbegin db 0
segment .bss
sum resb 1
num1 resb 2
num2 resb 2
bignum resd 4
Thanks you. I started reading the doc but i'm not sure that i understood key concepts.

Program to reverse an inputted chain of characters

I need to make a program that lets the user enter a string character by character and then print it in reverse. space means end of input (space should be entered by user.)
section .bss
c : resb 1
section .text
global _start
_start :
mov ecx, 0
mov edx, 0
saisie :
push ecx
push edx
mov eax,3
mov ebx,0
mov ecx,c
mov edx,1
int 80h
mov ecx,[c] ; put the entered value in ecx
cmp ecx,32 ; compare ecx with space.
je espace ;
pop edx
inc edx
pop ecx
jmp saisie
espace :
pop edx
cmp edx,0 ; if counter is 0 we exit if not we print what's in stack.
je fin
mov eax,4
mov ebx,1
pop ecx
int 80h
dec edx
jmp espace
fin :
mov eax, 1
mov ebx, 0
int 80h
When I enter characters and space at the end, the program just exits without error like it has done its job.
Can anyone explain this behavior and how I can correct it?

Getting digit instead of Ascii in nasm assembly intel x86

I'm trying to learn the basics of assembly but can't get across on how to display results stored in memory.
section .data
num1 db 1,2,3,4,5
num2 db 1,2,3,4,5
output: db 'The dot product is "'
outputLen1 : equ $-output
output2: db '" in Hex!', 10
output2Len : equ $-output2
section .bss
dotProd resw 1 ; store dot product in here
section .text
global _start
_start:
mov eax, 0
mov ecx, 5
mov edi, 0
mov esi, 0
looper: mov ax, [edi + num1]
mov dx, [esi + num2]
mul dx
add [dotProd], ax
cmp cx, 1
je printOutput
inc edi
inc esi
dec cx
jmp looper ; go back to looper
printOutput:
mov eax,4 ; The system call for write (sys_write)
mov ebx,1 ; File descriptor 1 - standard output
mov ecx, output ;
mov edx, outputLen1 ;
int 80h ; Call the kernel
mov eax, 4
mov ebx, 1
mov ecx, dotProd,
mov edx, 1
int 80h
mov eax, 4
mov ebx, 1
mov ecx, output2,
mov edx, output2Len
int 80h
jmp done
done:
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return code of 0 (no error)
int 80h
What I'm trying to do is get the dot product of the two list of numbers and display it on the screen. However, I keep getting random letters which I believe are hex representations of the real decimal value. How can I convert it to decimal? The current value display is 7, which should is the equivalent ASCII char for 55, which in this case is the dot product of both list of numbers.
esi and edi must be increased such that it points to next element of array.(in this particular example, only one of them is sufficient).
declare mun1 andnum2 as dd, instead of db (see here).
Also, you have to have method for printing number.(see this and this).
Below is a complete code which uses printf.
;file_name:test.asm
;assemble and link with:
;nasm -f elf test.asm && gcc -m32 -o test test.o
extern printf
%macro push_reg 0
push eax
push ebx
push ecx
push edx
%endmacro
%macro pop_reg 0
pop edx
pop ecx
pop ebx
pop eax
%endmacro
section .data
num1: dd 1,2,3,4,5
num2: dd 1,2,3,4,5
msg: db "Dot product is %d",10,0
section .bss
dotProd resd 1 ; store dot product in here
section .text
global main
main:
mov eax, 0
mov ecx, 5
mov edx, 0
mov esi, 0
mov dword[dotProd], 0h
looper: mov eax, dword[esi + num1]
mov edx, dword[esi + num2]
mul edx
add [dotProd], eax
cmp cx, 1
je printOutput
add esi,4
dec cx
jmp looper ; go back to looper
printOutput:
push_reg
push dword[dotProd]
push dword msg
call printf
add esp,8
pop_reg
jmp done
done:
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return code of 0 (no error)
int 80h

Why can't I print the user input data in NASM assembly?

I am trying to verify the length of user input in this example (NASM):
section .bss
user_input resb 10
section .text
push ebp
mov ebp, esp
mov eax, 3 ;sys_read
mov ebx, 0 ;stdin
mov ecx, user_input
mov edx, 10
int 80h
cmp eax, 10
jg overflow
jmp done
overflow:
.
.
.
done:
mov eax, 1
int 80h
Why isn't this working?
Since your buffer is 10 bytes and you put the length into edx, the return can never be greater than 10 and you jump to label done: and exit.
There's nothing in the code you've shown that prints anything out.

Loop/Input Logic Flow Issue (NASM x86 Assembly)

I have a program below that tries to take input from the user and repeat that same string until the user enters it again. (It's a personal learning project)
However, I am having some severe diffuculty in getting it to perform correctly. In a past thread here, you can see the input, pun intended, that other users have provided on this problem.
%include "system.inc"
section .data
greet: db 'Hello!', 0Ah, 'Please enter a word or character:', 0Ah
greetL: equ $-greet ;length of string
inform: db 'I will now repeat this until you type it back to me.', 0Ah
informL: equ $-inform
finish: db 'Good bye!', 0Ah
finishL: equ $-finish
newline: db 0Ah
newlineL: equ $-newline
section .bss
input: resb 40 ;first input buffer
check: resb 40 ;second input buffer
section .text
global _start
_start:
greeting:
mov eax, 4
mov ebx, 1
mov ecx, greet
mov edx, greetL
sys.write
getword:
mov eax, 3
mov ebx, 0
mov ecx, input
mov edx, 40
sys.read
sub eax, 1 ;remove the newline
push eax ;store length for later
instruct:
mov eax, 4
mov ebx, 1
mov ecx, inform
mov edx, informL
sys.write
pop edx ;pop length into edx
mov ecx, edx ;copy into ecx
push ecx ;store ecx again (needed multiple times)
mov eax, 4
mov ebx, 1
mov ecx, input
sys.write
mov eax, 4 ;print newline
mov ebx, 1
mov ecx, newline
mov edx, newlineL
sys.write
mov eax, 3 ;get the user's word
mov ebx, 0
mov ecx, check
mov edx, 40
sys.read
sub eax, 1
push eax
xor eax, eax
checker:
pop ecx ;length of check
pop ebx ;length of input
mov edx, ebx ;copy
cmp ebx, ecx ;see if input was the same as before
jne loop ;if not the same go to input again
mov ebx, check
mov ecx, input
secondcheck:
mov dl, [ebx]
cmp dl, [ecx]
jne loop
inc ebx
inc ecx
dec eax
jnz secondcheck
jmp done
loop:
pop edx
mov ecx, edx
push ecx
mov eax, 4
mov ebx, 1
mov ecx, check
sys.write ;repeat the word
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, newlineL
sys.write
mov eax, 3 ;replace new input with old
mov ebx, 0
mov ecx, check
mov edx, 40
sys.read
jmp checker
done:
mov eax, 1
mov ebx, 0
sys.exit
Example output would yield:
Hello!
Please enter a word or character:
INPUT: Nick
I will now repeat this until you type it back to me.
Nick
INPUT: Nick
N
INPUT: Nick
INPUT: Nick
And that goes on forever until is ^C it to death. Any ideas on the problem?
Thanks.
instruct leaves two items on the stack, which are consumed by checker the first time round the loop. But they are not replaced for the case where you go round the loop again. This is the most fundamental problem in your code (there may be others).
You could find this by running with a debugger and watching the stack pointer esp; but it can be seen just by looking at the code -- if you take everything out except for the stack manipulation and branches, you can clearly see that the checker -> loop -> back to checker path pops three items but only pushes one:
greeting:
...
getword:
...
push eax ;store length for later
instruct:
...
pop edx ;pop length into edx
...
push ecx ;store ecx again (needed multiple times)
...
push eax
checker:
pop ecx ;length of check
pop ebx ;length of input
...
jne loop ;if not the same go to input again
...
secondcheck:
...
jne loop
...
jnz secondcheck
jmp done
loop:
pop edx
...
push ecx
...
jmp checker
done:
...
There are better ways to keep long-lived variables than trying to shuffle them around on the stack like this with push and pop.
Keep them in a data section (the .bss you already have would be suitable) instead of on the stack.
Allocate some space on the stack, and load/store them there directly. e.g. sub esp, 8 to reserve two 32-bit words, then access [esp] and [esp+4]. (The stack should be aligned to a 32-bit boundary, so always reserve a multiple of 4 bytes.) Remember to add esp, 8 when you've finished using it.
(These are essentially the equivalent of what a C compiler would do for global (or static) variables, and local variables, respectively.)

Resources