How do I get a full assembly code from c file?

2020-04-21 00:20发布

问题:

I'm currently trying to figure out the way to produce equivalent assembly code from corresponding c source file. (pardon me for not being able to speak English fluently, I'm new to English.)

I've been using C language for several years, but have little experience to assembly language.

I was able to output the assembly code using S option in gcc. However, the resulted assembly code contained call instruction which in turn makes a jump to another functions like _exp . This is not what I wanted, I needed a fully functional assembly code in a single file, with no dependency to other codes.

Is it possible to achieve what I'm looking for? I would much be appreciated to get an answer!

EDIT: To better describe the problem, I'm showing you my code here:

#include <math.h>
float sigmoid(float i){
    return 1/(1+exp(-i));
}

And yes, it is embarrassingly short, I should have provided it at the first time I opened this question. I would also like to add that the platform I am currently working on is Windows 10 64bit, the compiler I'm using is cl.exe from MSbuild. Once again, thanks in advanced!

Edit 2: I now see that I didn't clearly describe what I wanted. I'm sorry for that. Anyway, my initial objective was to see, at a lowest level possible, how computers calculate mathematical functions. The level where I decided to observe the calculation process is assembly code, and the mathematical function I've chosen was sigmoid defined as above.

回答1:

_exp is the standard math library function double exp(double); apparently you're on a platform that prepends a leading underscore to C symbol names.

Given a .s that calls some library functions, build it the same way you would a .c file that calls library functions:

gcc foo.S -o foo  -lm

You'll get a dynamic executable by default.


But if you really want all the code in one file with no external dependencies, you can link your .c into a static executable and disassemble that.

gcc -O3 -march=native foo.c -o foo -static -lm
objdump -drwC -Mintel foo > foo.s

There's no guarantee that the _exp implementation in libm.a (static library) is identical to the one you'd get in libm.so or libm.dll or whatever, because it's a different file. This is especially true for a function like memcpy where dynamic-linker tricks are often used to select an optimal version (for your CPU) at run-time.



回答2:

It is not possible in general, there are exceptions sure, I could craft one so that means other folks can too, but it isnt an interesting program.

Normally your C program, your main() entry point is only a percentage of the code. There is a bootstrap that contains the actual entry point for the operating system to launch your program, this does some things that prepare your virtual memory space so that your program can run. Zeros .bss and other such things. that is often and or should be written in assembly language (otherwise you get a chicken and egg problem) but not an assembly language file you will see unless you go find the sources for the C library, you will often get an object as part of the toolchain along with other compiler libraries, etc.

Then if you make any C calls or create code that results in a compiler library call (perform a divide on a platform that doesnt support divide, perform floating point on a platform that doesnt have floating point, etc) that is another object that came from some other C or assembly that is part of the library or compiler sources and is not something you will see during the compile/assemble/link (the chain in toolchain) process.

So except for specifically crafted trivial programs or specifically crafted tools for this purpose (for specific likely baremetal platforms), you will not see your whole program turn into one big assembly source file before it gets assembled then linked.

If not baremetal then there is of course the operating system layer which you certainly would not get to see as part of your source code, ultimately the C library calls that need the system will have a place where they do that, all compiled to object/lib before you use them, and the assembly sources for the operating system side is part of some other source and build process somewhere else.