to assembly language and the machine's architecture. C++ and Pascal support
indirection using pointer variables that 1) hold an address that references
2) a variable, hence the indirection. The Intel processor uses registers (Bx, Si, Di, and Bp
for 16-bit or any 32-bit) as pointers, these registers can hold an
address used for the indirection. The following three examples are identical
with variables i, an integer, and bx, a pointer to an integer.
In the diagram at right, BX holds the address of variable i.
In the following Assembler program, we can examine the offsets of the variables and determine precisely what is the contents of eBx register. The instruction
Mov eBx, Offset icopies the offset of i, which is 32-bit 00000000416 to eBx.
C++ version
#include <iostream.h>
void main ( void )
{
int i;
int *ebx;
i = 5;
ebx = &i; // Point to i
cout << *ebx; // Prints 5
}
|
Assembler version
.data
00000000 h dd 3
00000004 i dd 5
00000008 j dd 9
.code
Main Proc Near
Mov eBx, Offset i ;; Point to i, eBx=0000004
Mov eAx, [eBx] ;; Get i value indirectly
Call PutDec ;; Prints 5
Mov eAx, 0
Mov eAx, [eBx+4] ;; Get j value indirectly
Call PutDec ;; Prints 9
Push 0 ;; Stop
Call ExitProcess
Main Endp
End Main
|
Indirection to Access Parameters - By enclosing in square brackets, [], registers such as eBx, eSi, eDi and other 32-bit registers act as pointers to reference memory. Using 16-bit variables, Bx and Si can point to the data segement, Di a pointer to the extra segment, while Bp can be a pointer to the stack segment. In the above example Bx or Si could be used but not Bp since the variable i is in the data segment and Bp references the stack segment.
In the following assembly program examples, notice the use of eBp as
a pointer to access the parameters on the stack. Suppose program fragments
of:
Mov eAx, [eBp+8]adds 8 to the offset in eBp to indirectly access the stack location holding the A parameter. Because any calls made to this function would place the actual parameters at the same relative stack location, [eBp+8] will always correspond to the formal A parameter. This follows the protocol used by C++ in calling functions and passing value parameters.
| Caller | Callee |
|
|
Assembly version
Stack after Mov eBp, eSp _________ | eDx | |_________| | Flags | |_________| B | 7 | <- eBp+12 |_________| A | 9 | <- eBp+8 |_________| | Ret Addr| <- eBp+4 |_________| | Old eBp | <- eBp+0 = eSp |_________| |
Call by Value
Call by Reference
![]() |
||
|
Caller - The caller's responsibility is to:
|
Callee - The callee's responsibility is to:
|
A more complete example of call-by-value implementation is given
below using C++ calling methods.
Caller - The caller's responsibility is to:
|
Callee - The callee's responsibility is to:
|
A more complete example of call-by-reference implementation is
given below using C++ calling methods.
Entering 1) Push eBp 2) Mov eBp, eSp 3) Sub eSp, # # is the number of bytes to allocate for dynamic variables 4) Push Registers Save any registers Exiting 4) Pop Registers Restore any registers 3) Mov eSp, eBp Restore eSp which deallocates dynamic variables 2) Pop eBp 1) Ret
Dynamic Variables C++ and Assembler
int a = 5, b = 6;
void main(void) {
cout << addup(a, b);
}
|
.data a dd 5 b dd 6 .code main proc near push offset b push a call addup add eSp, 8 call PutDec push 0 call ExitProcess main endp |
int addup(int x, int &y)
{ int sum;
sum = y;
sum = sum + x;
return sum;
}
|
addup PROC NEAR push eBp mov eBp, eSp sub eSp, 4 ; int sum mov eBx, [eBp+12] ; sum = y; mov eAx, [eBx] add eAx, [eBp+8] ; sum = sum + x mov [eBp-4], eAx mov eAx, [eBp-4] ; return sum mov eSp, eBp pop eBp ret addup ENDP |
C++ version
int eAx;
#include <iostream.h>
int Factorial( int N ) {
int i;
eAx = 1;
for (i=1; i<=N; i++)
eAx = eAx * i;
return eAx;
}
void main (void) {
cout << Factorial(6);
}
|
Double Indirection - The swap function illustrates an appropriate use of reference parameters, that is when the parameter requires a side-effect. It also illustrates that call-by-reference parameters have an access cost of two indirections. To access the right-most variable B in the following example requires: