Segmentation issue NASM - nasm

I'm working on conversions of c programs to NASM and I've been having issues with segmentation faults after the program runs. It will do what its supposed to do but will provide a segmentation fault message at the end of it.
The code is:
segment .data
out_less db "Z is less than 20.", 10, 0
out_greater db "Z is greater than 20.", 10, 0
out_equal db "Z is equal to 20! Yeah Z!", 10, 0
segment .bss
segment .text
global main
extern printf
ret
main:
mov eax, 10
mov ebx, 12
mov ecx, eax
add ecx, ebx ;set c (ecx reserved)
mov eax, 3
mov ebx, ecx
sub ebx, eax ;set f (ebx reserved)
mov eax, 12
mul ecx
add ecx, 10 ;(a+b*c) (ecx reserved)
mov eax, 6
mul ebx
mov eax, 3
sub eax, ebx
mov ebx, eax ;(d-e*f) (ebx reserved) reassign to ebx to keep eax open for manipulation
mov eax, ecx
div ebx
mov ecx, eax
add ecx, 1 ;(a+b*c)/(d-e*f) + 1
cmp ecx, 20
jl less
jg greater
je equal
mov eax, 0
ret
less:
push out_less
call printf
ret
jmp end
greater:
push out_greater
call printf
ret
jmp end
equal:
push out_equal
call printf
ret
jmp end
end:
mov eax, 0
ret
I'm not sure whats causing the fault because the program does actually run correctly any thoughts?
Thanks!

Update - this seems to work:
segment .data
out_less db "Z is less than 20.", 10, 0
out_greater db "Z is greater than 20.", 10, 0
out_equal db "Z is equal to 20! Yeah Z!", 10, 0
segment .bss
segment .text
global main
extern printf
main:
mov eax, 10
mov ebx, 12
mov ecx, eax
add ecx, ebx ;set c (ecx reserved)
mov eax, 3
mov ebx, ecx
sub ebx, eax ;set f (ebx reserved)
mov eax, 12
mul ecx
add ecx, 10 ;(a+b*c) (ecx reserved)
mov eax, 6
mul ebx
mov eax, 3
sub eax, ebx
mov ebx, eax ;(d-e*f) (ebx reserved) reassign to ebx to keep eax open for manipulation
mov eax, ecx
div ebx
mov ecx, eax
add ecx, 1 ;(a+b*c)/(d-e*f) + 1
cmp ecx, 20
jl less
jg greater
jmp equal
less:
push out_less
call printf
add esp,4
jmp exit
greater:
push out_greater
call printf
add esp,4
jmp exit
equal:
push out_equal
call printf
add esp,4
exit:
mov eax, 0
ret
end

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.

Printing current pid in assembly [duplicate]

I'm a novice Assembly x86 Learner, and i want to add two numbers (5+5) and print the result on the screen.
here is my code:
global _start
section .text
_start:
mov eax, 5
mov ebx, 5
add eax, ebx
push eax
mov eax, 4 ; call the write syscall
mov ebx, 1 ; STDOUT
pop ecx ; Result
mov edx, 0x1
int 0x80
; Exit
mov eax, 0x1
xor ebx, ebx
int 0x80
Correct me please
Another approach to convert an unsigned integer to a string and write it:
section .text
global _start
_start:
mov eax, 1234567890
mov ebx, 5
add eax, ebx
; Convert EAX to ASCII and store it onto the stack
sub esp, 16 ; reserve space on the stack
mov ecx, 10
mov ebx, 16
.L1:
xor edx, edx ; Don't forget it!
div ecx ; Extract the last decimal digit
or dl, 0x30 ; Convert remainder to ASCII
sub ebx, 1
mov [esp+ebx], dl ; Store remainder on the stack (reverse order)
test eax, eax ; Until there is nothing left to divide
jnz .L1
mov eax, 4 ; SYS_WRITE
lea ecx, [esp+ebx] ; Pointer to the first ASCII digit
mov edx, 16
sub edx, ebx ; Count of digits
mov ebx, 1 ; STDOUT
int 0x80 ; Call 32-bit Linux
add esp, 16 ; Restore the stack
mov eax, 1 ; SYS_EXIT
xor ebx, ebx ; Return value
int 0x80 ; Call 32-bit Linux

a problem with solving an example on nasm

x^3/2+1
if x=2 the answer it gives is 4290776301. i tried to do anything i could and i think the problem might be in ascii decoding or smth but i don't know what else i can do here.
%include "in_out.asm"
SECTION .data
msg: DB 'Вариант 6. Мой пример: f(x) = x*x*x/2 + 1.Введи, какой x я бы поставил: ', 0
pink: DB 'Ответ на пример: ', 0
SECTION .bss
x: resb 80
SECTION .text
GLOBAL _start
_start:
mov eax, msg
call sprintLF
mov ecx, x
mov edx, 80
call sread
mov eax, x
call atoi
mov ebx, [x]
mov eax, x
mul ebx
mul ebx
mov ebx, 2
xor ebx, edx
div ebx
add eax, 1
mov [x],eax
mov eax, pink
call sprint
mov eax, [x]
call iprintLF
call quit
looking forward for any help, thank you!
if x=2 the answer it gives is 4290776301
mov eax, x
mul ebx
The result can get so big because you are not starting the multiplication from the inputted number but rather from the address of the buffer x. In NASM mov eax, x loads the address of x, and mov eax, [x] loads the value stored at x.
call atoi
mov ebx, [x]
mov eax, x
atoi already leaves its result in the EAX register. You only need to copy it to the EBX register. call atoi mov ebx, eax.
mov ebx, 2
xor ebx, edx
div ebx
For the division by 2, you needed to clear the EDX register. You've accidently (typo) XORed the divider instead! And of course, dividing by 2 is better done using a shift to the right shr eax, 1.
A solution
mov eax, msg
call sprintLF
mov eax, x
call scanf
mov eax, x
call atoi ; -> EAX
mov ebx, eax ; ((X^3)/2)+1
imul ebx, eax
imul ebx, eax
shr ebx, 1
inc ebx
mov eax, pink
call sprint
mov eax, ebx
call iprintLF

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

Calling sys_read two times [Nasm, Linux]

Twice i try to read character from input, the first time "call getUserAction" works fine, but the main problem is, that the system didn't call the second read func, it just exits. Here is a little part of my code
SECTION .bss
buffer resb 1
SECTION .text
global _start
_start:
...some unuseful and commented code
call getUserAction ;reading 1 byte from console, works fine
...
jmp count
call exit
count:
...
call getUserAction; don't work, just exits from program without err
...commented code to debug
call exit
getUserAction: ;proc to read from console 1 byte
mov eax, 3
mov ebx, 0
mov ecx, buffer
mov edx, 1
int 80h
ret
Also i tried to put code from getUserAction in "count" proc, but it changes nothing.
UPD: Answer on first comment:
After the second "getUserAction":
mov eax, [buffer]
cmp eax, 'u'
je setUsersValues
cmp eax, 'e'
je callFunc
call exit
UPD2: I'm so sorry, here is all code
%define newline 10,0
%define A1 -7
%define A2 3
%define A3 2
%define A4 4
%define A5 2
SECTION .data
labInfo db "============Lab_3============",newline
labInfoLen equ $ - labInfo
mainMenu db "Choose the ex:",newline,\
" r - call count",newline,\
" t - call beep", newline,\
" y - call exit func",newline
mainMenuLen equ $ - mainMenu
funcStr db "Here func func func", newline
funcStrLen equ $ - funcStr
countPromt db "Please,choose the variant of variables value",newline,\
" u - user defined values", newline,\
" e - execerciese defined values", newline,\
"Your choise:"
promtLen equ $ - countPromt
SECTION .bss
buffer resb 1
resultValue resb 1
%macro calculateFunc 5
push eax
push edx
push ecx
mov eax, %1
mov ecx, %2
add eax, ecx
mov ecx, %3
imul ecx
mov ecx, %4
xor edx, edx
idiv ecx
mov ecx, %5
add eax, ecx
mov [resultValue], eax
pop ecx
pop edx
pop eax
%endmacro
SECTION .text
global _start
_start:
;call showPromt
push labInfo
push labInfoLen
call printStr
add esp, 8
;call showVarsList
push mainMenu
push mainMenuLen
call printStr
add esp, 8
call getUserAction
;get get get action
mov eax, [buffer]
cmp eax, 'r'
je count
cmp eax, 't'
je beep
cmp eax, 'y'
je exit
jmp _start
count:
;showFuncInfo
push funcStr
push funcStrLen
call printStr
add esp, 8
;showProposal
push countPromt
push promtLen
call printStr
add esp, 8
call getUserAction
mov eax, [buffer]
cmp eax, 'u'
je setUsersValues
cmp eax, 'e'
je callFunc
call exit
ret
setUsersValues:
nop; add some code later
ret
callFunc:
calculateFunc A1,A2,A3,A4,A5
add byte [resultValue], '0'
push resultValue
push 1
call printStr ; print Result
add esp, 8
ret
printStr:
push ebp
mov ebp, esp
mov eax, 4
mov ebx, 1
mov ecx, [ebp+12]
mov edx, [ebp+8]
int 80h
pop ebp
ret
getUserAction:
mov eax, 3
mov ebx, 0
mov ecx, buffer
mov edx, 1
int 80h
ret
beep:
nop;add some code later
ret
exit:
mov eax, 1
xor ebx, ebx
int 80h
without seeing all the code, your buffer should be at least 2 bytes. the size for both sys_read and sys_write should be 2 not 1.

Resources