Title: The Stack and Procedures
1The Stack and Procedures
2A Process in Virtual Memory
- This is how a process is placed into its virtual
addressable space - The code is placed at the lowest available
address followed then by the data - The stack (subject of this chapter) is used for
procedure calls and returns - The heap is used for dynamic memory allocation
- this is done by calling the OS at run time
(possibly via a library function like malloc() or
new in C)
(high memory)
Heap
Increasing addresses
Stack
Data
Code
(low memory)
3The Stack
- A stack of a certain size is allocated to every
process - The stack is used for procedure calls and returns
- It is also used by compilers for storing
variables and arrays - But the stack size is fixed when the program is
loaded in main memory - The stack size cannot be changed at run time
- There is always the risk of a stack overflow at
run time (if too much data are pushed onto the
stack) - If this is the case, the process is terminated
and the OS returns a stack fault message - The default stack size is normally large enough
for almost all applications but the programmer
can choose its size - With Borland we do this by providing a linker
option to the bcc32 command. Ex - bcc32 lS2000000 hello.asm
- This will allocate a stack of 2 million bytes
4The Stack (cont.)
- When the program starts to execute, ESP gets
loaded with the offset address of the top of the
stack - The top of the stack is the memory byte which
immediately follows the byte in the stack which
is located at the largest available address - The stack is said to be empty when ESP points to
the top of the stack - As we push data onto the stack the (unsigned)
value in ESP will decrease and ESP will point
deeper into the stack - The stack is said to be full when ESP points to
the bottom of the stack - The bottom of the stack is the memory byte in the
stack which is located at the smallest available
address - The PUSH instruction is used to insert (or save)
data onto the stack and the POP instruction is
use to retrieve this data - PUSH and POP can only be used with either 16-bit
or 32-bit operands (8-bits operands are not
allowed)
5The PUSH Instruction
- To push data onto the stack, we use
- PUSH source
- The source operand can be either reg, mem, imm,
(or indirect) but it must be 16-bit or 32-bit in
size. - Let S be the size (in bytes) of source (S 2 or
4). The following sequence of events will occur
upon execution of PUSH source - ESP is first decremented by S
- Then the content of source will be copied at the
location pointed by ESP
6PUSH Example
Addr 100h FFh FEh FDh FCh FBh FAh
STACK
- Suppose that the stack size is 100h and starts at
address 0. - ESP thus contains 100h when the stack is empty
(the byte at address 100h is the top of the
stack) - Check now the stack and ESP after each of these
PUSH - MOV eax,10203040h
- PUSH ax
- PUSH eax
- By default, an imm operand of PUSH is 32-bit.
This can be overridden by the PTR operator - PUSH 1 FFFFFFFFh is
- pushed
- PUSH word ptr 1
- FFFFh is pushed
- PUSH byte ptr 1 error
- PUSH qword ptr -1
- error
ESP
(Stack empty)
30h 40h 10h 20h 30h 40h
ESP
After push ax
ESP
After push eax
7The POP Instruction
- POP undoes the action of PUSH
- To pop data from the stack, we use
- POP destination
- The operand can be either reg, mem (or indirect)
but it must be 16-bit or 32-bit in size. - The operand cannot be imm
- Let S be the size (in bytes) of destination (S
2 or 4). The following sequence of events will
occur upon execution of POP destination - The word (if S2) or dword (if S4) located at
the address contained in ESP is first copied into
the destination operand - ESP is then incremented by S
8POP Example
Addr 100h FFh FEh FDh FCh FBh FAh
STACK
- Suppose that the stack is initially in the
following state - i.e. ESP contains FAh
- Here is the stack and ESP after each of these POP
- POP eax
- eax 10203040h
- POP ax ax 3040h
- POP ah error
- Note that the data remains in the stack only ESP
is changed (incremented) at each POP - Nevertheless, the stack is said to be empty when
ESP points to the top of the stack (here 100h)
ESP
After pop ax
30h 40h 10h 20h 30h 40h
ESP
After pop eax
ESP
(initially)
9Ex Saving and Restoring Registers
save registers push eax push ecx read and
print 3 chars mov ecx,3 again getch char in
eax or al,20h upper to lower case
convt. putch eax display loop again restore
registers pop ecx pop eax
- Some registers are automatically used by certain
instructions. Example - EAX is used by getch and other instructions
- ECX is used by LOOP and other instructions
- The stack provides a convenient way for saving
and restoring registers that are needed
temporarily - Notice the particular order in which PUSH and POP
are used
10Saving and Restoring Registers and Flags
- The PUSHA instruction (without operands) pushes
EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI on stack
and POPA pops the same registers in reverse
order. Example - PUSHA saves 8 registers onto the stack
- use these registers
- POPA restore initial values of registers
- PUSHF and POPF (without operands) pushes and pops
the EFLAGS register onto and from the stack.
Example - PUSHF saves EFLAGS onto the stack
- use instructions which will modify EFLAGS
- POPF restores original EFLAGS register
11Inverting the Input Line
.386 .model flat include csi2121.inc .code
main xor ecx,ecx sets count to
0 read_again getch cmp eax,0ah je display
push ax push char 16-bit inc ecx inc count
jmp read_again display jecxz exit again pop
ax pop char 16-bit putch eax loop
again exit ret end
- The stack is a last-in first-out data structure
- Items come off the stack in the reverse order
that they came in - This program uses this property to read a
sequence of characters and display them in
reverse order on the next line
12Exercise 1
- We have the following data segment
- msg DW a,b,c,d
- Suppose that, initially, ESP contains 100h. Give
the hexadecimal value contained in the mentioned
registers after executing each instruction in
this particular sequence - PUSH msg ESP
- MOV ax,esp AX
- PUSH msg2 ESP
- MOV eax,esp EAX
- PUSH dword ptr msg3 ESP
- LEA EAX,MSG
- POP word ptr eax ESP
- MOV ax,msg EAX
- POP eax EAX
- POP ax EAX
13Procedures
- A procedure is formally defined with the PROC and
ENDP directives - ProcName PROC
- ... set of instructions...
- RET
- ProcName ENDP
- To transfer control to the procedure ProcName we
do - CALL ProcName
- The RET instruction transfers control to the
instruction immediately following CALL - In fact, only CALL and RET are required. Hence, a
procedure can simply be written as - ProcName
- ... set of instructions ...
- RET
- Just like our main procedure ?
14CALL and RET
- Upon a CALL to a procedure
- ESP is decremented by 4
- The content of EIP is copied at the dword pointed
by ESP (Note the content of EIP is the offset
address of the instruction following CALL where
the procedure must return) - The offset address of the first instruction in
the called procedure is copied into EIP (this
will thus be the next instruction to execute) - Upon a RET from a procedure
- The dword pointed by ESP is copied into EIP
- ESP is incremented by 4 (the instruction pointed
by EIP is then executed)
15Illustration of CALL and RET
Called Procedure
Calling Program
ProcA PROC 006A5180h MOV eax,1 ...
RET ProcA ENDP
main ... 006A5100h call ProcA 006A5105h
inc eax ...
ESP
00
00
6A
6A
51
51
05
05
ESP
RET pops the returned address from the
stack into EIP
CALL pushes the return address onto the stack
16Exercise 2
- A program contains the following sequence of
instructions - CALL PROC1
- MOV BX,AX
- The instruction MOV BX,AX is located at the
address 0000011Ah. In addition, PROC1 starts at
address 00000456h. Finally, ESP initially
contains 00008000h. - (A) What is the content, in hexadecimal, of the
registers EIP, and ESP just after the execution
of the instruction CALL PROC1 (and just before
the execution of the 1st instruction of PROC1)? - (B) What is the double word pointed by ESP?
17Passing Arguments to Procedures
- Arguments can be passed to procedures via
- The stack this is the technique used in HLLs. We
will use this technique only in later chapters. - Registers a much faster way to pass arguments
(but very few registers are available). We will
start by using this technique. - Global variables the scope of a variable is the
.ASM file into which it is defined. Trivial to do
and extremely fast but it is contrary to modular
programming practice. - Procedures usually return their results in
- Registers either the returned value or the
address of the returned value (ex a modified
array). - Flags by modifying one or more flags, a
procedure can specify the presence or the absence
of a property.
18Using Procedures
- When a procedure returns to the caller it should
preserve the content of the registers (except
those used to return a value) - Hence, the procedure should first save the
content of the registers that it will modify and
restore them just before returning to the caller - Caution on stack usage
- ESP points to the return address when entering
the procedure. Make sure that this is the case
just before executing RET. - This also applies to the main procedure. Make
sure to push and pop an equal amount of data
before exiting with RET. - Here are examples of programs using procedures
- readstr.asm.html
- is_alpha.asm.html