I want to test inline asm capabilty on gcc.
So, I type and compile following code on ubuntu 12.04 64-bit
but system shows ”segmentation fault” on screen when it runs.
I don’t have any idea what causes the problem.
#include <stdio.h>
char Format[]="Hello world %d\n";
int main()
{
asm
(
"movl $3,4(%esp);"
"movl $Format,(%esp);"
"call printf;"
);
return 0;
}
Thank you guys for helping me a program newbie.
I use Code::blocks as IDE to write this code. I had tried to use 64-bit registers such like %rdx, but logs of Build messages shows ” Error: bad register name `%rdx’ ” when compiling the code. I think this means the gcc invoked by Code::blocks is 32-bit version, hence it can’t recognize those registers.
I modify the code to reserve the stack space
#include <stdio.h>
char Format[]="Hello world %d\n";
int main()
{
asm
(
"subl $8,%esp;" //I don't know $4, $8, $12, $16, $20 which is correct
//but I had tried them all but results are still ''segmentation fault."
"movl $3,4(%esp);"
"movl $Format,(%esp);"
"call printf;"
"movl %ebp,%esp;"
);
return 0;
}
and even use -m32 as compiler option, but it still shows ”segmentation fault “.
thanks again for who helps.
System V ABI for x64 mandates that the first six integer/pointer arguments to a function should go in registers
%rdi,%rsi,%rdx,%rcx,%r8and%r9. The stack is used to pass further arguments. It also requres that when calling functions with variable number of arguments (likeprintf),%raxshould be set to the total number of floating-point arguments passed in theXMMregisters. The right sequence to callprintf()in your case is:%raxshould be set to0since no floating-point arguments are being passed. This code also uses the fact that VA of initialised data usually lies somewhere in the first 4 GiB and thus shorter 32-bit instructions are used. Of courseprintfwill still examine the full content of%rdito determine where the format string is located in memory.Your code uses the 32-bit calling convention and should theoretically work if cross-compiled as 32-bit with
-m32but you should first reserve stack space for the arguments using something likesubl $20, %espand restore it after the call withaddl %20, %esp, otherwise you are either overwriting the stack ofmain()orretwill pick the wrong return address. Here is a fully working (tested) C/asm code that compiles and run in 32-bit mode:Remark: I use
\ninstead of;at the end of each assembly line only to improve the readability of the compiler assembly output – it is irrelevant to the correctness of the code.