Reputation: 9599
I'm using this code but it gives me Segmentation fault
when debugging. I'm compiling with MinGW:
#include <stdio.h>
#include <stdlib.h>
int CallMe(int a, int b)
{
printf("Called.");
return a + b;
}
int main()
{
printf("CallMe at 0x00%x\n", (unsigned int)&CallMe);
printf("Calling CallMe... ");
asm (
"movl $5, (%eax);\r\n"
"movl $4, (%ebx);\r\n"
"call 0x00401334;\r\n"
);
printf("\n");
return 0;
}
The function address is ok. Any ideas?
Thanks in advance.
Upvotes: 1
Views: 803
Reputation: 58224
First problem is the call, as @EricZ points out.
However, fixing that won't necessarily make the segfault go away. Your two moves are also causing a problem:
movl $5, (%eax)
movl $4, (%ebx)
This is moving values 5
and 4
into locations whose addresses are in %eax
and %ebx
, respectively. In this particular program, those addresses haven't been defined. If you want to pass them as parameters, you need to push them onto the stack.
pushl $5
pushl $4
call CallMe % With some compilers, this may need to be _CallMe
addl $8,%esp % assuming a 32-bit processor
Or, if the function expects them in the registers (I'm not saying it would in this case, but if...), remove the parentheses:
movl $5, %eax
movl $4, %ebx
You might want to read up on calling conventions, e.g., http://en.wikipedia.org/wiki/X86_calling_conventions.
Upvotes: 4
Reputation: 11418
This is what is really executing in your main()
function:
0x401268 <main>: push %ebp
0x401269 <main+1>: mov %esp,%ebp
0x40126b <main+3>: sub $0x8,%esp
0x40126e <main+6>: call 0x401350 <__main>
0x401273 <main+11>: add $0xfffffff8,%esp
0x401276 <main+14>: push $0x401218 <--- address of CallMe
0x40127b <main+19>: push $0x401242
0x401280 <main+24>: call 0x4013c0 <printf>
0x401285 <main+29>: add $0x10,%esp
0x401288 <main+32>: add $0xfffffff4,%esp
0x40128b <main+35>: push $0x401250
0x401290 <main+40>: call 0x4013c0 <printf>
0x401295 <main+45>: add $0x10,%esp
0x401298 <main+48>: movl $0x5,(%eax) <--- begin of your ASM block
0x40129e <main+54>: movl $0x4,(%ebx)
0x4012a4 <main+60>: call 0x8024c1 <--- eewww! wrong address
So the question is now: why a CALL 0x00401218
is assembled as CALL 0x008024C1
?
Of course, you will see also that parameters are not being passed by registers, but by pushing them into the stack.
In fact, I've got it by using this:
asm (
"pushl $5;\r\n"
"pushl $4;\r\n"
"call _CallMe;\r\n"
"addl %esp,$8;\r\n"
);
The problem I had before, about stack not bein balanced, was caused by a mistake in my code, that used addl %esp,8
instead of addl %esp,$8
. The former (tries to) add the contents of memory at address 8
to ESP
, instead of adding the constant 8
to ESP
.
If you want to collect the result of your function and save it, for example, in a variable, you can do as this:
int res;
...
...
asm (
"pushl $5;\r\n"
"pushl $4;\r\n"
"call _CallMe;\r\n"
"addl $8,%%esp;\r\n"
"movl %%eax,%0;\r\n" : "=m" (res)
);
If you really want to call the function using its address, you can do it several ways:
By putting the address in a variable, say, a void
pointer:
void *addr;
addr = (void *)CallMe;
asm (
"pushl $5;\r\n"
"pushl $4;\r\n"
"calll *%1;\r\n"
"addl $8,%%esp;\r\n"
"movl %%eax,%0;\r\n" : "=m" (res) : "m" (addr)
);
Or by putting the address to call in a register:
asm (
"pushl $5;\r\n"
"pushl $4;\r\n"
"movl $0x00401218,%%eax;\r\n"
"calll *%%eax;\r\n"
"addl $8,%%esp;\r\n"
"movl %%eax,%0;\r\n" : "=m" (res)
);
Upvotes: 2
Reputation: 14505
Generally, don't call the function by its hard-coded address. Try call the function name instead. Function name is effectively the function address.
call 0x00401334
==>
call CallMe
Upvotes: 2