Implementation Basics
To call a function, you need an address or an interrupt number. The address is loaded into the program counter register, and execution is carried forward. Some processors allow "Software interrupts" in which the program executes special instructions that cause software interruptions. This is the basis for performing functions.
Additional Information - Relative Addresses
There are two common forms of executable files: Absolute addressing and relative (or independent position code, PIC). In absolute addressing, functions are located on hard-coded addresses. Functions will not move. Commonly used in embedded systems.
In the relative addressing model, addresses refer to a value in the Program Counter register. For example, your function may have a length of 1024 bytes, so the compiler will generate a relative branch instruction of 1024 bytes (away).
Operating Systems and Moving Goals
Many operating systems download programs in different places for each call. This means that your executable file may start at address 1000, and next time at 127654. There is no guarantee on these operating systems that the executable will be launched in the same place every time.
Execution in your program
Performing functions inside your program is very simple. The compiler decides where all the functions will be located, and determines how to perform them; use absolute addressing, pic or mix.
Executing functions in another executable file
In view of the foregoing, problems arise with the performance of functions in another program:
- Location of function in external executable file
- Determining if an executable is active
- Call protocol for executable file
Most executables do not contain information about where their functions are located, so you need to know where it is. You also need to know if the function is absolute addressing or PIC. You will also need to know if the function is in memory when you need it, or if the OS downloaded this function to the hard drive.
You need to know the location of the function. However, the location does not make sense if the OS did not load the executable file. Before you call a function in another executable, you will need to know if it is present in memory when the call is made.
Finally, you need to know the protocol used for the external function. For example, are the values passed by a register? Are they on the stack? Are they passed by pointer (address)?
Solution: shared libraries
Operating systems (OSs) have evolved to provide dynamic function sharing. These functions exist in dynamically linked libraries (DLLs) or a shared library (.SOs). Your program tells the OS to load the library into memory, and then you tell the OS to execute the function by giving it the name of the function.
The caveat is that the desired function should be in the library. If the executable does not use the shared library or the function you need is not in the library, your mission is more complicated.