Handout: Call+Return

advertisement

CS 322

HM

COMPILER DESIGN

HO 3.2

PSU

Handout 3, Run Time Stack for x86

(4/26/2010)

Motivation: High level programming requires logical (and physical) modularization . The key tool for logical modularization is the creation of procedures (in some languages called s ubroutines ) and functions with their associated call, parameters, and return. This handout introduces call and return for the Intel x86 architecture, AKA IA-32 architecture.

Note that we’ll use the term procedure generically to mean either procedure, function or subroutine, unless the particular meaning of one is needed, in which case that is spelled out. Let’s start with 1.) a few definitions. Then we’ll outline simple stack operations in 2.) and refine with 3.) sample x86 code sequences to accomplish these operations. We conclude with 4.) the implementation of a recursive factorial() function in x86.

1. DEFINITIONS:

Base Pointer:

A pointer, often implemented via a dedicated register, that addresses an agreed upon area in the S tack

Frame of the currently executing procedure. On the x86 architecture this is implemented via the bp register.

Binding:

Procedures may have parameters. Formal parameters express a template for each parameter, including type, name, and similar attributes. At the place of call, these formal parameters receive initial, actual values, even if this is just the address of the corresponding actual parameter to be set later during the call. This association of actual to formal parameter is referred to as binding.

Call:

Transfer of control (aka context switch ) to the operand of the call with the expectation, that after completion of the call execution will resume at the place after the call instruction.

Dynamic Link:

A location in the Stack Marker that points to the Stack Frame of the procedure which called the currently active one.

Frame Pointer:

Synonym for Base Pointer.

Pop:

Stack operation that frees data from the stack. Often, the data popped off are assigned to some other object. Other times, data are just popped because they are no longer needed, in which case only the stack space is freed. This can also be accomplished by changing the value of the stack pointer.

Push:

Stack operation that reserves temporary space on the stack. Generally, the space reserved on the stack through a push is initialized with the argument of the push operation. Other times, a push just reserves

1

HO 3.2

CS 322

HM

COMPILER DESIGN

HO 3.2

PSU space on the stack for data to be initialized at a later time. Note that on the x86 architecture a push decreases the top of stack pointer (sp value).

Return:

Transfer of control after completion of a call. Usually, this is accomplished through a return instruction . The return instruction assumes the return address to be saved in a fixed part of the stack frame , called the Stack Marker .

Return Address:

The code address to which execution will switch once the call completes that activated the current procedure

Return Value:

The value returned by a function call. If the return value is a composite data structure, then the location set aside for the function return value is generally a pointer to the actual data

Stack:

Run time data structure that grows and shrinks during program execution. It generally holds data information (parameters, locals, temps) and control information (return addresses, links). Operations that change the stack include push, pop, call, return , and the like

Stack Frame:

Run time data structure associated with an active procedure (or function). A Stack Frame is composed of the procedure parameters , the Stack Marker , local data , and space for temporary data, including saved registers . The figure below shows a schematic layout of an abstract Stack Frame . Some implementations have the stack grow toward higher, others toward lower addresses. The scheme shown here does not care; it just shows the general layout. Key points:

Stack Pointer identifies top of current stack, and also top of current Stack Frame

Stack pointer may vary often during invocation

Stack pointer changes upon call, return, push, pop, explicit assignments

Base pointer does not vary during call; AKA frame pointer

Base pointer only set up once at start of call

Base pointer changed again at return, to value of previous base pointer, dynamic link

Parameters can be addressed relative to base pointer in one direction

Locals (and temps) can be addressed relative to base pointer in the other direction

Possible to save base pointer, useful when registers are scarce, as on x86

However, this scheme is difficult, since compiler (or human programmer) must keep dynamic size of stack in mind at any moment of time of code generation; not discussed here

2

HO 3.2

CS 322

HM

COMPILER DESIGN

HO 3.2

PSU sp

Locals + Temps bp

Stack Marker

Actual Parameters

Stack Frame

Stack Marker:

Run time data structure on the stack associated with a Stack Frame . The Stack Marker holds fixed information, whose structure is known a priori. This includes the return address, the static link, and the dynamic link.

In some implementations, the Stack Marker also holds an entry for the function return value and the saved registers .

Stack Pointer:

A.k.a top of stack pointer : A pointer (typically implemented via a register) that addresses the last element allocated (pushed) on top of the stack. On the x86 architecture this is implemented via the sp register. It is also possible to have the Stack Pointer refer to the next free location (if any) on the stack in case another push operation needs stack space.

Static Link:

Address in the Stack Marker that identifies the Stack Frame of the last invocation of the procedure which lexicographically surrounds the currently executing one. This is implemented only in high level languages that allow nested scopes, such as Ada and Pascal; not needed in simpler languages like C.

Top Of Stack:

Stack location last allocated (pushed).

3

HO 3.2

CS 322

HM

COMPILER DESIGN

HO 3.2

PSU

2. SIMPLE STACK OPERATIONS ON X86 ARCHITECTURE:

Before Call:

Push actual parameter

Changes the stack

Track size of actuals pushed

In most languages the actual size is fixed; not so in C

Base pointer still points to Stack Marker of caller

After last actual parameter pushed: one flexible part of Stack Frame complete

Call:

Push instruction pointer (ip)

Note that ip points to target of call, not the instruction after call;

however, address of instruction after call must be saved as return address

This identifies the beginning of the Stack Marker

Set the instruction pointer to the address of the destination

Note that x86 architecture has 24 flavors of call instruction

Procedure Entry:

Push Base Pointer , this is the dynamic link

Set Base Pointer to value of Stack Pointer

Now the new Stack Frame is being addressed

The fixed part of stack, the Stack Marker is being built

Allocate space for local variables, if any

This establishes another area of the Stack Frame that is variable in size

Return:

Pop locals and temps off stack

This frees the second variable size area from the Stack Frame

Pop registers to be restored

Pop the top of stack value into the base pointer bp

This uses the Dynamic Link to reactivate the previous Stack Frame

Pop top of stack value into instruction pointer

This sets the ip register back to the instruction after the call

The return instruction does this

Either caller (or a suitable argument of the return instruction) frees the space allocated for actual parameters

4

HO 3.2

CS 322

HM

COMPILER DESIGN

HO 3.2

3. SAMPLE CODE SEQUENCES FOR CONTEXT SWITCH

Procedure Entry, No Locals, Save Regs push bp ; save dyn link in Stack Marker mov bp, sp push ax push bx

; establish new Frame: point to Stack Marker

; save ax if needed by callee, optional

; ditto for bx

PROCEDURE EXIT, NO LOCALS, RESTORE REGS pop bx pop ax pop bp ret args

; restore bx if was used by callee

; ditto for ax

; must find back old Stack Frame

; ip to instruction after call; free args

PROCEDURE ENTRY WITH LOCALS, NO REGS push bp mov bp, sp sub sp, 24

; save dyn link in Stack Marker

; establish new Frame: point to Stack Marker

; allocate 24 bytes uninit. space for locals

PROCEDURE EXIT WITH LOCALS, NO REGS mov sp, bp pop bp ret args

; free all locals and temps

; must find back old Stack Frame, RA on top

; ip to instruction after call; free args

PROCEDURE ENTRY WITH LOCALS, SAVE REGS push bp mov bp, sp sub sp, 24 push ax push bx

; save dyn link in Stack Marker

; establish new Frame: point to Stack Marker

; allocate 24 bytes uninit. space for locals

; save ax if needed by callee, optional

; ditto for bx

PROCEDURE EXIT WITH LOCALS, RESTORE REGS pop bx pop ax mov sp, bp pop bp ret args

; restore bx if was used by callee

; ditto for ax

; free all locals and temps

; must find back old Stack Frame, RA on top

; ip to instruction after call; free args

PSU

5

HO 3.2

CS 322

HM

COMPILER DESIGN

HO 3.2

4. RECURSIVE FACTORIAL IN X86 ASSEMBLER:

FACTORIAL IN C unsigned fact( unsigned arg )

{ // fact if ( arg <= 1 ) { return 1;

}else{ return fact( arg - 1 ) * arg;

} //end if

} //end fact

FACTORIAL IN X86 ASSEMBLER

; Source file: fact.asm

. . . penter macro push bp mov bp, sp push bx push cx push dx endm pexit macro args pop dx pop cx pop bx pop bp ret args endm

Errcode =

MAX =

4ch

9d

.model small

.stack 100h arg

.data dw 0

.code extrn uPutDec : near rfact proc

; assume argument for recursive fact( arg ) on stack

; return fact( int arg ) in ax

PSU

6

HO 3.2

CS 322

HM

COMPILER DESIGN

HO 3.2

PSU base: penter mov ax, [bp+4] ; argument sits 4 bytes b4 dyn link cmp ax, 1 ; argument > 1? jg recurse ; if so: recusive call mov ax, 1 pexit 2

; No: then result known: 0!=1!=1

; and done recurse: mov ax, [bp+4] ; need to recurse; get next arg dec ax ; but decrement first push ax call rfact

; and pass on stack

; recurse rfact mov cx, [bp+4] ; partial product in ax, * arg mul cx ; product in ax pexit 2 endp drive_r proc

; and done again_r: mov arg, 0 mov ax, 0 mov bp, sp

; initial value again cmp arg, MAX jge done_r

; ax holds argument to be factorialized :-) push ax ; argument on stack call rfact

; now ax holds factorial value call uPutDec inc arg mov ax, arg jmp again_r done_r: ret drive_r endp

7

HO 3.2

Download