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
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.After this:
You want:
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'sret
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 toesp
doesn't matter, because you're restoringesp
correctly near yourret
. My next guess is that the string you're passing toprintf
is lacking a null terminator... Let me see whatgas
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.the issue was that i was using
rather that
Thanks everybody for your help and sorry for wasting your time :P
Change
push printtext
topush $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, andprintf
is trying to interpret that as an address and crashing.