I'm trying to use a function in assembly, invoked from a C project. This function is supposed to call a libc function let's say printf()
, but I keep getting a segmentation fault.
In the .c file I have the declaration of the function let's say
int do_shit_in_asm()
In the .asm file I have
.extern printf
.section .data
printtext:
.ascii "test"
.section .text
.global do_shit_in_asm
.type do_shit_in_asm, @function
do_shit_in_asm:
pushl %ebp
movl %esp, %ebp
push printtext
call printf
movl %ebp, %esp
pop %ebp
ret
Any pointers comments would be appreciated.
as func.asm -o func.o
gcc prog.c func.o -o prog
Change push printtext
to push $printtext
.
As it is, you're loading a value from the address printtext
and pushing that, rather than pushing the address. Thus, you're passing 'test'
as a 32-bit number, rather than a pointer, and printf
is trying to interpret that as an address and crashing.
One of the best ways to get started with assembly language functions is to write a similar function in C, and then build it with the compiler switch that generates an assembly listing (-S
on gcc). Then you can study the output of what the compiler did, and modify as needed.
This is particularly useful if you're calling functions such as printf
which use a different calling convention (because of the variable number of arguments). Calling those functions may be quite different from calling non-varargs functions.
the issue was that i was using
pushl printtext
rather that
pushl $printtext
Thanks everybody for your help and sorry for wasting your time :P
After this:
push printtext
call printf
You want:
addl $4, %esp
Further explanation:
Because you're using x86 Linux I assume the calling convention requires the callee to cleanup the parameters. Because you pushed a pointer before calling printf
, your stack is off by 4 after that function's ret
instruction happened.
Update:
Yeah, OK, I was used to Intel syntax so I was getting the order of the arguments backward in my head. Actually the lack of the addl
back to esp
doesn't matter, because you're restoring esp
correctly near your ret
. My next guess is that the string you're passing to printf
is lacking a null terminator... Let me see what gas
does...
Update 2:
OK, gas
null terminates strings for you, so I guess my second hunch was wrong. It looks like you found the issue so the point is moot.