This question already has answers here:
Why do you have to link the math library in C?
(14 answers)
Why is -lm not necessary in some cases when compiling and linking C code?
(3 answers)
Closed 6 years ago.
I am coding under GNU/Linux Debian 8.5
I have a simple program.
If I compile this with gcc prog.c it is OK!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
int main(int argc, char const *argv[]) {
float _f = 3.1415f;
floor(_f);
ceil(_f);
return 0;
}
Bud if I add pow(), it says that it cannot find pow and I need to add gcc prog.c -lm to make it right.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
int main(int argc, char const *argv[]) {
float _f = 3.1415f;
floor(_f);
ceil(_f);
pow(_f, 2);
return 0;
}
If I am right, the pow(), ceil(), floor() are all from <math.h>?
So why don't floor() and ceil() throw a compilation error, and pow() does, without -lm flag?
Technically all of them require -lm to work. All of their man pages include this line:
Link with -lm.
But yours is not a compiler error but a linker error, that is your program compiles fine, but then when linking if you don't use -lm it is unable to find the implementation of pow() but it actually finds the implementation of ceil().
That is probably because in your architecture/configuration ceil() is an inline or intrinsic function, maybe there is a simple CPU instruction to do it, so no library is necessariy. But pow() is not so you need to link libm.
UPDATE: I've just made some experiments, and with -O0 all your functions require the -lm but with -O2 only pow(). Tinkering about that I found the file /usr/include/bits/mathinline.h with the inline implementations of ceil() and floor()...
The compiler only complains about pow() and not floor() or ceil() probably because it generates inline code for floor() and ceil() and an external call for pow() which cannot be resolved at link time because you forgot the m library on the command line: -lm stands for link with libm.a.
Incidentally, since you do not store the return value of these functions, the compiler might use its intrinsic knowledge of these pure functions (conveyed in some way in <math.h>) to remove the calls altogether. It might do that for ceil() and floor() and not for pow(), which would also explain the observed behavior.
Indeed, as can be verified on http://gcc.goldbolt.org/#, with no command line options, your code compiles as:
main:
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movss .LC0(%rip), %xmm0
movss %xmm0, -4(%rbp)
cvtss2sd -4(%rbp), %xmm0
movsd .LC1(%rip), %xmm1
call pow
movl $0, %eax
leave
ret
.LC0:
.long 1078529622
.LC1:
.long 0
.long 1073741824
For some reason, the compiler generates inline code only for floor and ceil, as observed.
While with -O2 it removes everything:
main:
xorl %eax, %eax
ret
If you modify the code to store the values into global variables, library calls to floor(), ceil() and pow() are generated without optimization and the values are computed by the compiler if you optimize with -O2.
The error you get is a linking error, not a compilation error.
Floor and ceil might be in some other library, generally the compiler is not required to diagnose missing headers or libraries.
Related
This question already has answers here:
Can printf get replaced by puts automatically in a C program?
(4 answers)
Closed 8 years ago.
Kindly explain this snippet:
#include <stdio.h>
int puts(const char *str) {
fputs("Hello world!\n", stdout);
}
int main() {
printf("Goodbye\n");
}
Output : Hello world! return 13
It is compiler specific. You get this behavior with GCC. Here are some details.
since you #include <stdio.h> (actually because you are in a hosted environment) the puts is that of the C99 standard, and redefining it is undefined behavior
the GCC compiler has some optimizations to transform some printf to a sequence of faster puts. This is legal, since you have included <stdio.h> (and the C99 standard defines what printf should do in that case; GCC goes thru __builtin_printf as an intermediate step)
If you compile with -ffreestanding you won't observe that.
Your question is very close to this one; so this answer is also relevant.
I compiled the program with gcc x.c -S -o-. It gave me
[...]
main:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
movl $.LC1, (%esp)
call puts
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE1:
so indeed the printf call is replaced with puts in GCC, as they have the same semantics.
My guess would be that the compiler changes the call to printf() into a call to puts(), since there's no need for printf() due to no formatting. Also the string is terminated by a newline, which fits puts(). The compiler didn't see your scary overload of a library function coming, so it got "fooled".
I am trying to take a look at a test program my professor gave us, but I am having trouble compiling it. I am on Ubuntu 14.04. I am compiling it with
gcc -Wall test.c AssemblyFunction.S -m32 -o test
I was having problems running the code on a 64-bit machine and read that adding -Wall and -m32 will allow it to work. Doing that fixed the first problem I had, but now I am getting the error: undefined reference to `addnumbersinAssembly'.
Here is the C file
#include <stdio.h>
#include <stdlib.h>
extern int addnumbersinAssembly(int, int);
int main(void)
{
int a, b;
int res;
a = 5;
b = 6;
// Call the assembly function to add the numbers
res = addnumbersinAssembly(a,b);
printf("\nThe sum as computed in assembly is : %d", res);
return(0);
}
And here is the assembly file
.global _addnumbersinAssembly
_addnumbersinAssembly:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp), %eax
addl 12(%ebp), %eax # Add the args
movl %ebp,%esp
popl %ebp
ret
Thank you for your time. I have been trying to figure this out for hours, so I appreciate any help.
I believe that with GCC you are going to want to remove the _ in your assembler file. So these lines:
.global _addnumbersinAssembly
_addnumbersinAssembly:
Should be:
.global addnumbersinAssembly
addnumbersinAssembly:
More information on this issue can be found in this StackOverflow question/answer.
The -m32 compile parameter is needed because the assembly code you have needs to be rewritten to support some 64 bit operations. In your case it was stack operations. The -Wall isn't needed to compile but it does turn on many more warnings.
I've written this simple C code
int main()
{
int calc = 2+2;
return 0;
}
And I want to see how that looks in assembly, so I compiled it using gcc
$ gcc -S -o asm.s test.c
And the result was ~65 lines (Mac OS X 10.8.3) and I only found these to be related:
Where do I look for my 2+2 in this code?
Edit:
One part of the question hasn't been addressed.
If %rbp, %rsp, %eax are variables, what values do they attain in this case?
Almost all of the code you got is just useless stack manipulation. With optimization on (gcc -S -O2 test.c) you will get something like
main:
.LFB0:
.cfi_startproc
xorl %eax, %eax
ret
.cfi_endproc
.LFE0:
Ignore every line that starts with a dot or ends with a colon: there are only two assembly instructions:
xorl %eax, %eax
ret
and they encode return 0;. (XORing a register with itself sets it to all-bits-zero. Function return values go in register %eax per the x86 ABI.) Everything to do with your int calc = 2+2; has been discarded as unused.
If you changed your code to
int main(void) { return 2+2; }
you would instead get
movl $4, %eax
ret
where the 4 comes from the compiler doing the addition itself rather than making the generated program do it (this is called constant folding).
Perhaps more interesting is if you change the code to
int main(int argc, char **argv) { return argc + 2; }
then you get
leal 2(%rdi), %eax
ret
which is doing some real work at runtime! In the 64-bit ELF ABI, %rdi holds the first argument to the function, argc in this case. leal 2(%rdi), %eax is x86 assembly language for "%eax = %edi + 2" and it's being done this way mainly because the more familiar add instruction takes only two arguments, so you can't use it to add 2 to %rdi and put the result in %eax all in one instruction. (Ignore the difference between %rdi and %edi for now.)
The compiler determined that 2+2 = 4 and inlined it. The constant is stored in line 10 (the $4). To verify this, change the math to 2+3 and you will see $5
EDIT: as for the registers themselves, %rsp is the stack pointer, %rbp is the frame pointer, and %eax is a general register
Here is an explanation of the assembly code:
pushq %rbp
This saves a copy of the frame pointer on the stack. The function itself does not need this; it is there so that debuggers or exception handlers can find frames on the stack.
movq %rsp, %rbp
This starts a new frame by setting the frame pointer to point to the current top-of-stack. Again, the function does not need this; it is housekeeping to maintain a proper stack.
mov $4, -12(%rbp)
Here the compiler initializes calc to 4. Several things have happened here. First, the compiler evaluated 2+2 by itself and used the result, 4, in the assembly code. The arithmetic is not performed in the executing program; it was completed in the compiler. Second, calc has been assigned the location 12 bytes below the frame pointer. (This is interesting because it is also below the stack pointer. The OS X ABI for this architecture includes a “red zone” below the stack pointer that programs are permitted to use, which is unusual.) Third, the program was clearly compiled without optimization. We know that because the optimizer would recognize that this code has no effect and is useless, so it would remove it.
movl $0, -8(%rbp)
This code stores 0 in the place the compiler has set aside to prepare the return value of main.
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
This copies data from the place where the return value is prepared to a temporary handling location. This is even more useless than the previous code, reinforcing the conclusion that optimization was not used. This looks like code I would expect at a negative optimization level.
movl -4(%rbp), %eax
This moves the return value from the temporary handling location to the register in which it is returned to the caller.
popq %rbp
This restores the frame pointer, thus removing the previously-pushed frame from the stack.
ret
This puts the program out of its misery.
Your program has no observable behavior, which means that in general case the compiler might not generate any machine code for it at all, besides some minimal startup-wrapup instructions intended to ensure that zero is returned to the calling environment. At least declare your variable as volatile. Or print its value after evaluating it. Or return it from main.
Also note that in C language 2 + 2 qualifies as integral constant expression. This means that compiler is not just allowed, but actually required to know the result of that expression at compile time. Taking this into account, it would be strange to expect the compiler to evaluate 2 + 2 at run time when the final value is known at compile time (even if you completely disable optimizations).
The compiler optimized it away, it pre-computed the answer and just set the result. If you want to see the compiler do the add then you cannot let it "see" the constants you are feeding it
If you compile this code all by itself as an object (gcc -O2 -c test_add.c -o test_add.o)
then you will force the compiler to generate the add code. But the operands will be registers or on the stack.
int test_add ( int a, int b )
{
return(a+b);
}
Then if you call it from code in a separate source (gcc -O2 -c test.c -o test.o) then you will see the two operands be forced into the function.
extern int test_add ( int, int );
int test ( void )
{
return(test_add(2,2));
}
and you can disassemble both of those objects (objdump -D test.o, objdump -D test_add.o)
When you do something that simple in one file
int main ( void )
{
int a,b,c;
a=2;
b=2;
c=a+b;
return(0);
}
The compiler can optimize your code into one of a few equivalents. My example here, does nothing, the math and results have no purpose, they are not used, so they can simply be removed as dead code. Your opitmization did this
int main ( void )
{
int c;
c=4;
return(0);
}
But this is also a perfectly valid optimization of the above code
int main ( void )
{
return(0);
}
EDIT:
Where is the calc=2+2?
I believe the
movl $4,-12(%rbp)
Is the 2+2 (the answer is computed and simply placed in calc which is on the stack.
movl $0,-8(%rbp)
I assume is the 0 in your return(0);
The actual math of adding two numbers was optimized out.
I guess line 10, he optimzed since all are constants
I want to increment a TLS variable in assembly but is gives a segmentation fault in the assembly code. I don't want to let compiler change any other register or memory. Is there a way to do this without using gcc input and output syntax?
__thread unsigned val;
int main() {
val = 0;
asm("incl %gs:val");
return 0;
}
If you really really need to be able to do this for some reason, you should access a thread-local variable from assembly language by preloading its address in C, like this:
__thread unsigned val;
void incval(void)
{
unsigned *vp = &val;
asm ("incl\t%0" : "+m" (*vp));
}
This is because the code sequence required to access a thread-local variable is different for just about every OS and CPU combination supported by GCC, and also varies if you're compiling for a shared library rather than an executable (i.e. with -fPIC). The above construct allows the compiler to emit the correct code sequence for you. In cases where it is possible to access the thread-local variable without any extra instructions, the address generation will be folded into the assembly operation. By way of illustration, here is how gcc 4.7 for x86/Linux compiles the above in several different possible modes (I've stripped out a bunch of assembler directives in all cases, for clarity)...
# -S -O2 -m32 -fomit-frame-pointer
incval:
incl %gs:val#ntpoff
ret
# -S -O2 -m64
incval:
incl %fs:val#tpoff
ret
# -S -O2 -m32 -fomit-frame-pointer -fpic
incval:
pushl %ebx
call __x86.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
leal val#tlsgd(,%ebx,1), %eax
call ___tls_get_addr#PLT
incl (%eax)
popl %ebx
ret
# -S -O2 -m64 -fpic
incval:
.byte 0x66
leaq val#tlsgd(%rip), %rdi
.value 0x6666
rex64
call __tls_get_addr#PLT
incl (%rax)
ret
Do realize that all four examples would be different if I'd compiled for x86/OSX, and different yet again for x86/Windows.
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, %r8 and %r9. The stack is used to pass further arguments. It also requres that when calling functions with variable number of arguments (like printf), %rax should be set to the total number of floating-point arguments passed in the XMM registers. The right sequence to call printf() in your case is:
xorl %eax, %eax
movl $Format, %edi
movl $3, %esi
call printf
%rax should be set to 0 since 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 course printf will still examine the full content of %rdi to 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 -m32 but you should first reserve stack space for the arguments using something like subl $20, %esp and restore it after the call with addl %20, %esp, otherwise you are either overwriting the stack of main() or ret will pick the wrong return address. Here is a fully working (tested) C/asm code that compiles and run in 32-bit mode:
#include <stdio.h>
char Format[] = "Hello world, %d\n";
int main (void)
{
asm
(
// Make stack space for arguments to printf
"subl $8, %esp\n"
"movl $3, 4(%esp)\n"
"movl $Format, (%esp)\n"
"call printf\n"
// Clean-up the stack
"addl $8, %esp\n"
);
return 0;
}
$ gcc -m32 -o test.x test.c
$ ./test.x
Hello world, 3
Remark: I use \n instead 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.
Try first to look at a normal C program and see what asm it gives (you can get it by using gcc -S).
Then, identify the part of ASM which is needed for the printf call and reproduce it in your original program.
What you have here is a calling convention error.