A program is just a set of definitions of variables and functions. A function provides a convenient way to encapsulate some computation, which can then be used without worrying about its implementation. With properly designed functions, it is possible to ignore how a job is done. Communication between the functions is by arguments and values returned by the functions. The functions can occur in any order in the source file, and the source program can be split into multiple files, so long as no functions are split apart. Here is the function power and a main program to call it: #include <iostream> int power( int base_, int n_ ); // declaration (function prototype) int main() { int i = 5; int p = power( i, 2 ); std::cout << i << '\t' << p; return 0; } // power: raise base to n-th power; n >= 0 int power( int base_, int n_ ) { int p = 1; for ( ; n_ > 0; --n_ ) { p = p * base_; } return p; } The return statement is the mechanism for returning a value from the called function to its caller. Any expression can follow return: return expression; The expression will be converted to the return type of the function if necessary. Parentheses are often used around the expression, but they are optional. In C++, all function arguments are passed by value This means that the called function is given the values of its arguments in temporary variables rather than the originals.
|
The thread of execution enters and leaves functions in your program in the same manner. On top of each function, the compiler automatically generates a set of CPU instructions called prolog, and another set of instructions called epilog, for entering and leaving a function, respectively. In prolog, the code is setting up the access to the function's local variables and parameters. The memory for local variables and parameters is allocated on the stack and is called a stack frame (please note that UNIX textbooks often use the term activation record when describing stack frames.) Although the x86 CPU doesn't explicitly specify any stack frame scheme, the design of the CPU and call/return instructions makes it easiest for operating systems to use the EBP register to hold the pointer to the stack frame. Because of this, on Intel platform, the EBP is commonly
referred to as stack frame register. Integer function parameters can
be easily accessed using positive offsets from the address stored in
the EBP register. The first parameter will always be at The epilog restores program stack to the state before function call took place, effectively freeing the memory occupied by the function's stack frame. Finally, the return address is fetched from the stack, and control of the program execution returns back to the calling function. If function has integer return type, the return value is normally passed to the caller in EAX register. Understanding program stack could be more difficult in some real-world situations. Programs built for release are compiled using optimized code options. In those builds, the compiler is capable to optimize away the stack frames of some functions. The Visual C++ compiler is aggressive when it does the optimization, and if it can use the stack frame register as a scratch register, it does so. |
|
|
|