[openbeos] Re: compiling, running, etc.

  • From: "Daniel Reinhold" <danielr@xxxxxxxxxxxxx>
  • To: openbeos@xxxxxxxxxxxxx
  • Date: Thu, 08 Aug 2002 04:32:52 CDT

>     Well, I've completed algorithmic problem solving I and II in C++, 
a SCHEME 
>class, an assembly language class using a Motorola 68HC11 to make, 
among other 
>things, a graphics card.  I've written C++ code to interface with 
custom made 
>USB devices, as well as created the drivers for those devices in 
Windows.  I 
>have a pretty good idea about programming.  Maybe you are 
misunderstanding my 
>question.

I sure hope that I'm misunderstanding something (PLEASE, PLEASE!)

Omigosh.. I really should just let this thread die a natural and 
deserved death. But I have to admit, after reading your reply, my 
initial annoyance and exasperation has to turned to humorous disbelief. 
I don't know whether to laugh out loud or cry. But I think I will make 
one last attempt to try explain some things (why, I don't know...)


>
>>Clay... while I'm glad that you are interested in helping with the 
>>project, you are a very confused puppy about a lot of basic 
programming 
>>concepts:
>
>>a) you don't need to use "low-level" instructions or code in assembly 
>>to get object code. You get object code from the compiler. Write a C 
or 
>>C++ program and them compile it -- voila, you have object code.
>     But someone has to write the object code for the compiler to know 
what to 
>do with the source code. 

Wrong.
Nobody has to "write" the object code for the compiler. It does that 
for you. That's its purpose. YOU write the functionality that you want 
in the source language and the compiler "generates" the machine code. 
Now you don't necessarily *have* to use a compiler: if you have an 
amazing memory (and are from another planet), then you could study the 
machine code specs for your specific machine and enter the binary code 
directly yourself with a hex editor. Most of us would rather write in 
C, C++ etc. and have the compiler generate this stuff for us.

>You can't have functions and classes just calling 
>other functions and classes to infinity.

Why not?
Here's a simple case:
int a() { return a(); }
Well... maybe you are right. I mean, it doesn't really keep calling to 
"infinity". At some point, the stack is exhausted and your program doth 
halt.


  At some point, the most basic 
>functions (say ioctl()) have to have actual "hand-written" object 
files so that 
>a compiler can have a "degenerative case".

No they don't -- most basic functions are written in C or C++ or some 
other high level language. We have several implementations of ioctl() 
(as an example), in the CVS tree that you could look at. But at least 
your point of confusion is becoming clearer to me.

What you are doing is totally mixing up the concepts of compile time 
and run time. The compiler doesn't run anything -- it just reads text 
files and (based on a set of rules) generates binary files. There is no 
"calling" going on (at least not the calls in your program). Only at 
run time, when the previously compiled object code is loaded into 
memory, do calls actually occur. And every call along the way is 
machine code that is executing (it has to be).

This has nothing to do with the compiler itself or how it "knows" what 
code to generate. It "knows" what to generate because all source code 
can be broken down into a collection of primitive operations. The 
"primitives" for the compiler are the instructions that are native to 
the CPU of the computer you are running.

Compilers don't give a diddly poop whether function A's run-time call 
to function B, etc. will finally bottom out somewhere or results in a 
recursive loop. All it cares about is whether your syntax is correct. 
If it is, it generates the corresponding machine code instruction for 
each statement.

A compiler is a translator that, in effect, contains a sophisticated 
dictionary. Think about translating from English to German, for 
example. If you have a dictionary that lists all English words and the 
corresponding German words for each, you could translate any piece of 
English text into German (well, real translation is more involved, but 
we'll skip that).

Well, you have a C compiler for your Intel PC, for example. It 
understands C syntax and knows how to break down all your source code 
files into a series of statements and expressions. It also knows the 
complete set of machine instructions available for the x86 
architecture. So it simply goes thru your expressions and statements 
one-by-one, writing out equivalent machine code instructions to disk. 
Actually, it's more involved than that, but we'll skip that too. The 
source language (C) is finite and the target language (x86 machine 
code) is finite. No matter how big and/or complex your program is, it 
can always be broken down into a long list of basic expressions and 
statements for which there are machine code equivalents.

>
>>That's what compilers are for -- they allow us to avoid having to 
write 
>>machine specific code.
>     How do you think a compiler knows how to turn source code into 
assembly?

Most compilers don't generate assembly (which then requires invoking an 
assembler to generate the machine code), but instead generate the 
machine code directly. Gcc has a switch (as do most) that allows you to 
output an assembly listing -- this just makes the machine code easier 
to read and understand by humans. Spend some time reading the assembly 
output for your programs and you'll get a good idea of what the 
compiler is doing.

>
>>For your work, you 
>>should never need worry about this. You just write code in C or C++ 
and 
>>the compiler will take care of the machine code for you.
>     If my classes/functions just call other classes and functions, 
then THOSE 
>class and functions have to be defined in assembly, or the functions 
and 
>classes _they_ call wall have to be written in assembly.  Somewhere 
down the 
>hierarchy, everything has to get to source code.
>
>>b) libraries don't have to be "objectified".. they aleady are. That's 
>>essentially what libraries are -- collections of object code.
>     Okay, that makes sense and is basically what I was wanting 
confirmation 
>of.  But who is going to do all of this library writing in ASM?

Nobody is writing in ASM. Not on this project anyway. Every line of 
code in assembly language is specific to a particular machine 
architecture. This is different than using high-level languages. For 
example:
int main() { printf ("hello world\n"); }
is a machine independent program. It will compile and run on just about 
any computer in existence (any with a C compiler). Now write that same 
program in assembly and you have a program that can only be compiled 
(assembled actually) and run on your particular type of machine (e.g. 
x86). We don't want to write platform specific code. So we don't (well, 
there are just a couple of places in the kernel where it can't be 
avoided -- these are "ghetto-ized" into /arch directories)


>
>>They also include a little bit of information about the calling 
interface of 
>the 
>>functions within the library. But mostly, a library is just a big 
list 
>>of pre-compiled object code.
>     That's exactly what I wanted to hear. :)
>
>>c) you asked in another email about the trail of calls, and doesn't 
it 
>>lead to assembly (or object code) at some point? No, every call in a 
>>trail of calls is already object (machine) code or it wouldn't be 
>>running.
>     I think you are contradicting yourself now..or maybe 
misunderstanding what 
>I asked.  Above, you just _stated_ that libraries _are_ object code.  
That 
>means that when the compiler is crunching away, it eventually breaks 
all 
>commands like "myBNetEndPoint->Receive(blah, foo, x);" into assembly.    
No, 
>this command is not machine code; and it's not "running"..it's just 
getting 
>compiled.  I think there is some kind of huge confusion between how we 
are 
>explaining this.

Code that is calling other functions (or being called) is running. 
Period. Quit bringing up the compiler when talking about running code. 
The compiler is totally out of the picture by the time the code is 
actually executing.

>
>>Computers don't run  C or C++, they run machine code.
>     That's entirely my point!
>
>>That's why you use a compiler to generate it for you.
>     But a compiler can't know what to do with
>ifstream din;
>din.open('pr0n_clip_12');
>     Unless the ".c" for iofstream.h is already object code; or uses 
functions 
>and classes that are themselves already linked to an object code file.  
You 
>talk a compiler is some sort of intelligent entity that can just 
convert source 
>code to machine code without specificiations (ie object code files).

Oh for goodness sake! Compiling is not running. It's possible for 
source code to compile which can't be run at all. For example, it may 
fail to link. The snippet above will compile so long as the header file 
with the given definitions can be found. It won't link (and 
consequently can't be run) unless the linker finds the object code for 
the "ifstream::open()" function. That open() function is just some C++ 
code that was compiled earlier by someone else and placed into a 
library (unless the source was distributed, then you could compile the 
library yourself).


>
>Clay
>


Ok, Clay. That was my last brave attempt to clarify the situation. You 
will really only understand this stuff completely by tracking down and 
reading some good material on compilers, linkers, object code, 
libraries, etc. Good luck, fearless young lad!

Other related posts: