Parameter passing refers to the exchange of data between modules.
There are many ways this information can be exchanged.
- GLOBAL DATA USING COMMON BUFFER OR MEMORY
The data is stored in memory accessible to all modules.
The disadvantage of this technique is that the data may be modified by any module, which makes debugging harder. Consider the following simple program which adds two numbers together, storing the result. All data has been declared as common.
TITLE CommonData .MODEL Large .STACK 200h .DATA num1 dw 22 num2 dw 32 result dw 0 .CODE addnum proc far mov ax, [num1] mov bx, [num2] add ax, bx mov [result], ax ret addnum endp start: mov ax, @data mov ds, ax call addnum ; add num1 and num2 mov ax, 4c00h int 21h END start
- REGISTER VARIABLES
This technique involves passing and returning values using processor registers.Routines must ensure that they do not corrupt any registers other than those which
have been specified. The programmer first determines which registers will be used and which can be altered (contents destroyed).
Consider the following implementation of the previous addition program to use register variables.
TITLE CommonData .MODEL Large .STACK 200h .DATA num1 dw 22 num2 dw 32 result dw 0 .CODE addnum proc far ; accepts num1 in ax, num2 in bx, returns result in dx push ax add ax, bx mov dx, ax pop ax ret addnum endp start: mov ax, @data mov ds, ax mov ax, [num1] mov bx, [num2] call addnum ; add num1 and num2 mov [result], dx mov ax, 4c00h int 21h END start
The advantage is that only the calling module alters the data, whilst the module addnum only works on copies of the data. In this way, it is easier to track which modules affect the data variables.
Parameters may also be passed using the stack. This involves pushing the values onto the stack before the module is called. This may also involve pushing space onto the stack for a return result.The module then accesses the parameters on the stack using the appropriate addressing mode.
Upon return to the calling module, the stack space is deallocated using appropriate pop or stack pointer adjustment instructions.
There are two ways in which data may be referenced using the stack.
- Call by Value
This refers the placing of copies of the data value on the stack. Only the copy is worked with, the original remains unmodified.
- Call by Reference
This refers to the passing of the address of the variable using the stack. This address is used to access the data, thus the original data is used.
Call by value is normally used for simple data types, whilst call by reference is used for data types like arrays and records, because of the amount of memory space they occupy (and stack space is normally limited).
Consider the following program for an MC6802 processor which uses Call by Value to add two variables together.
CPU 6802 HOF MOT ORG 100H Num1: DFB 10 Num2: DFB 20 Result: DFB 0 Start: PSHA ; Make room for result on stack LDAA Num1 LDAB Num2 PSHA ; Place copy Num1 on stack PSHB ; Place copy of Num2 on stack JSR Addup PULB ; remove copy of Num2 PULA ; remove copy of Num1 PULA ; get result from Addup STAA Result Exit: BRA Exit Addup: TSX ; transfer SP into IX register PSHA ; save registers PSHB LDAA 02,X ; Get Num2 LDAB 03,X ; Get Num1 ABA ; Add Num1 and Num2 STAA 04,X ; Store on stack for return PULB ; Recover original register values PULA RTS END Start
- Call by Value
PARAMETER PASSING FOR THE 8088 PROCESSOR
ACCESSING THE STACK FRAME INSIDE A MODULE
Lets look at how a module handles the stack frame. Because each module will use the BP register to access any parameters, its first chore is to save the contents of BP.
It then transfers the address of SP into BP; BP now points to the top of the stack.
thus the first two instructions in a module will be the combination,
push bp mov bp,sp
ALLOCATION OF LOCAL STORAGE INSIDE A MODULE
Local variables are allocated on the stack using a
sub sp, n
instruction. This decrements the stack pointer by the number of bytes specified by n. For example, a module might want to use temporary storage space for an integer i, which equates to the machine code instruction
sub sp, 2
Pictorially, the stack frame looks like,
+---------+ | ihigh |<-- SP +---------+ | ilow | +---------+ | BPhigh |<-- BP +---------+ | BPlow | +---------+
The local variable i can be accessed using SS:BP – 2,
so the statement,
i = 24;
is equivalent to
mov [bp - 2], 18
Note that twenty-four decimal is eighteen hexadecimal.
DEALLOCATION OF LOCAL VARIABLES WHEN THE MODULE TERMINATES
When the module terminates, it must deallocate the space it allocated for the variable i on the stack. Referring to the above diagram, it can be seen that BP still holds the top of
the stack as it was when the module was first entered. BP has been used for two purposes,
- to access parameters relative to it
- to remember where SP was upon entry to the module
The deallocation of any local variables (in our case the variable i) will occur with the following code sequence,
mov sp, bp ;this recovers SP, deallocating i pop bp ;SP now is the same as on entry to module
THE PASSING OF PARAMETERS TO A MODULE
Consider the following module call in a high level langauge.
add_two( 10, 20 );
The language pushes parameters (the values 10 and 20) right to left, thus the sequence of statements which implement this are,
push ax ; assume ax contains 2nd parameter, ie, integer ; value 20 push cx ; assume cx contains 1st parameter, ie, integer ; value 10 call add_two
The stack frame now looks like,
+---------+ | Return |<-- SP +---------+ | address | +---------+ | 00 | ;1st parameter, integer value 10 +---------+ | 0A | +---------+ | 00 | ;2nd parameter, integer value 20 +---------+ | 14 | +---------+
Remembering that the first two statements of module add_two() are,
add_two: push bp mov bp, sp
The stack frame now looks like (after those first two instructions inside add_two)
+---------+ | BPhigh |<-- BP <-- SP +---------+ | BPlow | +---------+ | Return | +---------+ | address | +---------+ | 0A | ;1st parameter, integer value 10 +---------+ | 00 | +---------+ | 14 | ;2nd parameter, integer value 20 +---------+ | 00 | +---------+
ACCESSING OF PASSED PARAMETERS WITHIN THE CALLED MODULE
It should be clear that the passed parameters to module add_two() are accessed relative to BP, with the 1st parameter residing at [BP+4], and the 2nd parameter residing at [BP+6].
DEALLOCATION OF PASSED PARAMETERS
The two parameters passed in the call to module add_two() were pushed onto the stack frame before the module was called. Upon return from the module, they are still on the stack frame, so now they must be deallocated. The instruction which does this is,
add sp, 4
where SP is adjusted upwards four bytes (ie, past the two integers).