Reputation: 13
This is my first assembly source code, I want to use scanf
function but this ELF gives a segmentation fault.
So, I tried to solve using core dump, but I couldn't.
.section .data
string:
.ascii "input yournumber : \0"
value:
.ascii "your value is %d \n\0"
scanf:
.ascii "%d"
.section .text
.globl _start
_start:
movl %esp, %ebp
subl $4, %esp
pushl $string
call printf
leal -4(%ebp), %ebx
pushl %ebx
pushl $scanf
call scanf
pushl -4(%ebp)
pushl $value
call printf
pushl $0
call exit
Upvotes: 1
Views: 454
Reputation: 364842
Instead of looking at just the core-dump, look at how you got there by starting the executable inside gdb
. Single-step instructions with si
. See the bottom of https://stackoverflow.com/tags/x86/info for more GDB tips.
You have a ton of bugs which can cause crashes, and some which definitely will.
You define a scanf
symbol, so call scanf
jumps there.
It's in the .data
section, so the page might not be executable.
Or maybe the bytes for "%d"
decode to x86 machine code that crashes, given those register values.
Use a different symbol name like scanf_fmt
for the scanf format string. Also don't forget to use .asciz
to zero-terminate the implicit-length C string.
If you statically linked this, or you tried this on MinGW or Cygwin, then libc isn't initialized because you're defining _start
instead of main
. In a dynamically-linked Linux executable, glibc uses dynamic linker hooks to get its init functions called. Even so, it's not recommended to use libc functions from _start
.
printf
or scanf
might possibly also crash because the stack is only aligned by 8 bytes, when the ABI allows it to assume 16. The stack is aligned by 16 on entry to _start
, but you only do 1 push
+ 1x sub $4, %esp
before printf.
But most Linux distros don't build 32-bit code with -msse2
, so the compiler won't use 16-byte alignment-required loads/stores to copy stuff around. (x86-64 glibc's scanf
does crash if called with an under-aligned stack.)
And you do actually call scanf
with an aligned stack; a total offset of 16 from entry to _start
, because you don't waste instructions cleaning the stack after printf
returns. That's a valid choice, as long as you're aware that you're doing it. (It deserves a comment, and / or you could use mov
instead of push
for later args to reuse those same stack slots.)
I'd suggest looking at (optimized) compiler output for a function that does what you want. e.g. on https://godbolt.org/
Upvotes: 4