ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

33
ICS312 Set 12 Subroutines: Passing Arguments Using the Stack

description

The calling routine used in MAIN3 can be either: To use CALL by Value : PUSH X PUSH Y CALL SUB1 To use CALL by Reference : PUSH OFFSET X PUSH OFFSET Y CALL SUB1

Transcript of ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Page 1: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

ICS312 Set 12

Subroutines: Passing Arguments Using the Stack

Page 2: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Passing Arguments via the Stack

Arguments to a subroutine are pushed onto the stack.

The subroutine accesses the arguments from the stack using the Base Pointer (BP) and indirect addressing.

Arguments can be passed by value (their values are pushed onto the stack, or by reference (their offsets are pushed onto the stack).

Page 3: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

The calling routine used in MAIN3 can be either:

To use CALL by Value: PUSH X PUSH Y CALL SUB1

To use CALL by Reference: PUSH OFFSET X PUSH OFFSET Y CALL SUB1

Page 4: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Call by Value Using the Stack

Suppose that X and Y are defined in the MAIN file:

    X DW ...    Y DW ...

To call a subroutine CALC to evaluate X - 2Y using call by value:

Page 5: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

TITLE MAIN3 (main3.asm) EXTRN CALC: NEAR .MODEL SMALL .STACK 100H .DATA X DW 30 Y DW 40 .CODE MAIN3 PROC     MOV AX, @DATA     MOV DS, AX PUSH Y ; call by value PUSH X CALL CALC ; the answer should be returned in AX MOV AX,4C00H     INT 21H MAIN3 ENDP     END MAIN3

Page 6: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Pay close attention to the following slide

(and the one so indicated a few slides on).

These are the methods used by all commercial compilers

You are expected to know these methods off by heart! You’ll be asked to supply them both in a quiz and in the midterm.

Page 7: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Call by Value Using the Stack(Cont.)

TITLE CALC (CALC.ASM - a separate file) PUBLIC CALC .MODEL SMALL .CODE CALC PROC NEAR ;evaluates X - 2Y with result in AX PUSH BP          ;save BP     MOV BP,SP        ;BP points to stack top ; push any registers to be used in the subroutine and ; restored before returning from the subroutine here     MOV AX,[BP+4]   ;AX has X     SUB AX,[BP+6]   ;AX = X - Y SUB AX,[BP+6] ;AX = X - 2Y ; pop any registers that were saved in the subroutine here     POP BP          ;restore BP     RET 4           ;pop IP and add 4 bytes to SP CALC ENDP     END

Page 8: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Call by Value Using the Stack(Cont.)

Stack Representation for NEAR Call by Value in this version of the program:

Instruction      Stack Contents     SP          BP (at the end of this code)

PUSH Y (Arg1)   Y SP -=2     [BP+6] = offset of Y on stack PUSH X (Arg2)   X               SP -=2     [BP+4] = offset of X on stackCALL CALC        Ret Address         SP -=2     [BP+2] = RETADDR (IP)PUSH BP          BP                 SP -=2     [BP] = original contents of BPMOV BP, SP BP = SPpush regs regs SP -=2/each reg

Page 9: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Call by Value Using the Stack(Cont.)

The purpose of using the BP in this way is because it gives a standard way to retrieve arguments from the stack that is not affected by pushing any additional registers or other values within the subroutine.

Note: if BP is used for indirect addressing, it is assumed to be referring to an offset in the stack segment (SS). Any other register used for indirect addressing is assumed to be an offset in the data segment (DS).

Page 10: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

TITLE CALC (CALC.ASM - a separate file) PUBLIC CALC .MODEL SMALL .CODE CALC PROC NEAR ;evaluates X - 2Y with result in AX PUSH BP          ;save BP     MOV BP,SP        ;BP points to stack top ; push any registers to be used in the subroutine     MOV AX, [BP+4]   ;AX has X     SUB AX, [BP+6]   ;AX = X - Y SUB AX, [BP+6] ;AX = X - 2Y ; pop any registers that were saved in the subroutine     POP BP          ;restore BP     RET 4           ;pop IP and add 4 bytes to SP CALC ENDP     END

Page 11: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

NOTEC assumes that (1) the calling program will fix the stack after the return from a subroutine (2) arguments will be passed using call by value (3) arguments are pushed in reverse order, as shown above.

Different compilers use different calling conventions.

Page 12: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Call by Reference Using the Stack

Here is another version to demonstrate passing arguments by reference on the stack.

TITLE MAIN3 (main3.asm) EXTRN SUB2: NEAR .MODEL SMALL .STACK 100H .DATA X DW 30 Y DW 40

Page 13: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

.CODE MAIN3 PROC     MOV AX,@DATA     MOV DS,AX PUSH OFFSET Y ;using call by reference PUSH OFFSET X ;using call by reference CALL CALC ; answer should be in AX MOV AX,4C00H     INT 21H MAIN3 ENDP     END MAIN3

Page 14: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

The following slide (and its continuation) is the other method (call by reference) used by commercial compilers

and which you are expected to know off by heart!

Page 15: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Call by Reference Using the Stack TITLE SUB2 (sub2.asm - a separate file) PUBLIC SUB2 .MODEL SMALL .CODE SUB2 PROC NEAR ;evaluates X - 2Y, with result in AX PUSH BP          ;save BP (and DEC SP)     MOV BP,SP        ;BP pts to stack top ; push any registers to be used in the subroutine and ; restored before returning from the subroutine here

Page 16: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

MOV BX, [BP+4]   ;BX has address of X (not its value) MOV AX, [BX] ;AX has the value of X     MOV BX, [BP+6]   ;BX has address of Y SUB AX, [BX] ;AX = X - Y SUB AX, [BX] ;AX = X - 2Y

;pop any registers that were saved in the subroutine here     POP BP          ;restore BP     RET 4           ;pop IP and add 4 bytes to SP SUB2 ENDP     END

Page 17: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Stack Representation for call by reference example

Instruction    Stack contents     SP          BP (at end of this code)PUSH AX          Y address     SP -=2      [BP+6]= Y addressPUSH AX          X address     SP -=2      [BP+4]= X addressCALL ADDNOS      IP                SP -=2      [BP+2] = return addr. offsetPUSH BP          BP                SP -=2      [BP] = orig. contents of BP MOV BP, SP BP = SP PUSH regs        regs         SP -=2/reg 

Page 18: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Example on storing a result in an argument

Call SUB(X, Y, Z), Result is to set Z = Y – X

Main Program . . PUSH OFFSET X PUSH OFFSET Y PUSH OFFSET Z CALL SUB . .

Page 19: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Example on storing a result in an argument (Cont.1)

Title SUB3 .Model Small .586 PUBLIC SUB

.CODESUB PROC NEAR PUSH BP ;Save BP MOV BP, SP PUSH DX ;Save DX PUSH BX ;Save BX MOV BX, [BP+6] ;BX = OFFSET of ADDRESS of Y MOV DX, [BX] ;DX = Y MOV BX, [BP+8] ;BX = OFFSET of ADDRESS of X SUB DX, [BX] ;DX = Y – X

Page 20: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Example on storing a result in an argument (Cont.2)

; to store DX in Z MOV BX, [BP+4] ; puts offset of Z into BX MOV [BX], DX

POP BX ; restore original value of BX POP DX POP BP RET 6SUB ENDP END

Page 21: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

FIXING UP THE STACKIf the subroutine is to fix up the stack, then

it should end up with: RET 2*no. of arguments

e.g. if there are 3 arguments, then it should end up with: RET 6

If the calling program is to fix up the stack, then the subroutine should end up with: RETand, assuming that the subroutine is SUB1, the calling program should contain the code: call sub1 add sp, 6 (i.e. 2*no. of arguments)

Page 22: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

ILLUSTRATION OF A RECURSIVE PROCEDURE

A procedure to evaluate factorial(n)

if n = 1 return 1else return n*factorial(n-1)

Page 23: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

factorial proc nearpush bpmov bp,spcmp word ptr [bp+4], 1jg contmov ax, 1jmp endup

cont: mov bx, [bp+4]dec bxpush bxcall factorial

Page 24: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

imul word ptr [bp+4]endup:

pop bp ret 2

factorial endp end

Page 25: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

An Example of a Recursive Procedure

Employed in Cryptography

Definition. The GCD (greatest common denominator) of two numbers a, b is the largest number that divides both a and b.  

25

Page 26: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

  Euler’s Extended Algorithm.

For given a, b to find: (a) the GCD d of a, b (b) numbers x and y (positive, negative or zero) such that xa + yb = d

(Euler’s original algorithm is just part (a) ) 26

Page 27: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

If a = b, then obviously the GCD of (a,b) is a, and we have a*1 + b*0 = a

Otherwise, proceed as follows:

Page 28: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Define E(a,b) as a function whose value is the triple (x, y, d) such that d is the GCD of a, b and xa + yb = d. E(a,b) can then be evaluated using the following recursive algorithm:

Function E(a, b) where a > b If b = 0 then return (1, 0, a), else evaluate q, r such that a = qb + r and 0 ≤ r < b. Evaluate E(b, r), let result be (X, Y, D) Return (Y, X – qY, D)End function

28

Page 29: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

EXAMPLE. To find the GCD d of 75 and 30, and, further to find x, y such that 75x + 30y = d.E(75, 30) = (x1, y1, d) to be filled in later75 = 2*30 + 15 (so q1 = 2)E(30, 15) = (x2, y2, d) to be filled in later30 = 2*15 + 0 (so q2 = 2)E(15, 0) = (x3, y3, d) = (1, 0, 15). So d = 15.

Now x2 =y3=0 and y2 = x3 – q2y3 = 1and x1 =y2=1 and y1 = x2 – q1y2 = -2So d = 15 and 1*75 + (-2)*30 = 15

29

Page 30: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

PROOF THAT THE ALGORITHM WORKS (optional) First of all note that since a = qb + r, any number that divides both b and r must also

divide a (so it divides both a and b). And since r = a – qb, any number that divides both a and

b must also divide r (so it divides both b and r). Thus the largest number that divides both b

and r must also be the largest number that divides both a and b

i.e. the GCD of a,b = GCD of b,r

Page 31: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

The case where b = 0 obviously returns the correct result, since 1*a + 0*0 = a, and a is the GCD of a and 0.

If b > 0, and q, r, X, Y, D are as defined in the algorithm, then Xb + Yr = D where D is the GCD of b,r and hence also of a,b Since r = a - qb, this provides Xb + Y(a-qb) = DGiving Ya + (X-qY)b = D

31

Page 32: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Finally note that the algorithm terminates, because the second argument decreases in each successive recursive call. So the sequence of iterations must end up with one in which the second argument is zero

32

Page 33: ICS312 Set 12 Subroutines: Passing Arguments Using the Stack.

Textbook Reading (Jones): Chapter 13  Procedures and High-Level Languages