Stack & Procedures
Download
Report
Transcript Stack & Procedures
Procedures and Stacks
Outline
• Stack organization
• PUSH and POP instructions
• Defining and Calling procedures
The stack
• Space used as temporary storage during the
execution of a program
• Purpose:
–
–
–
–
saving the return address when calling procedures
saving the contents of registers used in procedures
passing parameters to procedures
Allocation of memory for local variables in procedures
• A single access point. LIFO data structure
– Data is always accessed from the “top” of the stack
– Insertion is done by “pushing” data onto the top of the stack
– Deletion is done by “popping” data from the top of the stack
• Stack operations reduce the size of code by using the
stack as an implied operand
Stack layout in memory
Original SP
Direction of
increasing
memory
addresses
In use
In use
In use
In use
In use
In use
Free
Free
Free
Free
Stack grows in
direction of
decreasing
memory
addresses
SS:SP
SS
Stack layout in memory
• SS – Stack segment register desigates a segment
containing the stack
• SP – points always to the top of the stack
– SP is decreased when data is pushed. E.g. if we push a
word SP is decreased by 2
– SP is increased when data is popped. E.g. is we pop a word
SP is increased by 2
• BP points to elements in the stack
– Remember that BP is the register that you use in your
programs to access data from the stack
– It will come into play when we communicate with “C”
Push example
To
address
12FFF
Register array
AX
BX
CX
DX
6AB3
SP
0800
SS
Segment index
PUSH BX
6A
B3
03800
037FF
037FE
03000
Stack segment
Pop example
To
address
0FFFF
Register array
AX
BX
CX
DX
392F
SP
1006
SS
0000
POP BX
39
2F
01008
01007
01006
00000
Stack segment
PUSH and POP
• Instructions which access the stack
• PUSH and POP always store/load words, not bytes
• In 386 and above you can also push/pop
doublewords
• PUSH X
– X can be immediate data, 16-bit register, segment register or
2 bytes of memory
• POP X
– X can be 16-bit register, segment register except CS and
memory location
PUSHA and POPA
• “Push All” and “Pop All”
• In 286 and later it is possible to push/pop the entire
set of general purpose registers
– AX,BX,CX,DX,SP,BP,SI,DI
Using the stack
• Storage
–
–
–
–
Return address when a procedure is called
Preserve the contents of registers
Local variables required by procedures
Dynamically allocated memory
• Communication
– Parameters passed to procedures
Why preserve registers?
• In principle, Registers are global variables
• Registers can also be used as temporary storage in a
procedure
• If a procedure needs to use registers as temporary
storage and these registers contain “useful” global
variables, their contents must be preserved
• The first instructions in a procedure should save them
and the last instructions should restore them
Example: preserving registers
Take careful note of the ordering
PUSH AX
; Place AX on the stack
PUSH BX
; Place BX on the stack
PUSH CX
; Place CX on the stack
PUSH DX
; Place DX on the stack
PUSH SI
; Place SI on the stack
PUSH DI
; Place DI on the stack
; code that modifies AX,BX,CX,SI,DI
POP DI
; Restore original value
POP SI
; Restore original value
POP DX
; Restore original value
POP CX
; Restore original value
POP BX
; Restore original value
POP AX
; Restore original value
of
of
of
of
of
of
DI
SI
DX
CX
BX
AX
Calling procedures and using the stack
• call proc_name
– Pushes the instruction pointer (IP) onto the stack
– Pushes CS onto the stack if the call is to a procedure
outside the code segment
– Unconditionally jumps to the label proc_name
• ret
– Pop saved IP and, if necessary, the saved CS and restores
their values in the registers
– Causing instruction execution to resume at the instruction
after the original call
Simple Procedure example
mov ax, 10h
mov bx, 20h
mov cx, 30h
mov dx, 40h
call AddRegs ;this proc adds AX + BX + CX + DX AX
call sysExit
AddRegs:
add ax, bx
add ax, cx
add ax, dx
ret
Procedures at a glance
• Procedures can access global variables declared at the
beginning of the program
• Procedures can access global variables stored in registers
• Procedures may have parameters passed to them
– Registers holding values is a form of parameter passing
– Pushing parameters onto the stack is another form of parameter
passing (this is what “C” relies on)
• Procedures may need to preserve registers
– Unless other conventions are in place, calling code usually expects that all
registers are restored to their original values upon return from the call
• Procedures may return results to the caller in registers or write
results in memory, or leave results on the stack
Stack Guidelines
• There must be a one-to-one match between push
and pop instructions
• The first pop is matched to the last push
– E.g. Last in, first out
• Messing up the stack makes for great confusion!
• Also, Do not push/pop registers intended to store
return values. A register in which a return value is
expected (usually AX) is expected to be changed, so
do not save or restore it.
Organizing your program
• Create a block diagram or pseudocode of your
program in paper
– Control flow
– Data flow
• Break the program into logical “components” that can
be easily translated to procedures in your code
• Use descriptive names for variables
– Noun_type for types
– Nouns for variables
– Verbs for procedures
Organizing your program
• Modular program organization helps debugging
– Makes it easier to ‘isolate’ the bug to a single procedure
• All programs contain bugs!
– This is overstated…
– It really means that you shouldn’t expect your program to
work the first time you run it… Maybe not the 10th either!
– …but you shouldn’t feel bad about it either, relax and trace
the bug
– Use the debugger! Its VERY HARD to debug assembly code
without one.
Tracing bugs
• The debugging process:
– Set breakpoints in your programs and use them as
checkpoints for checking the contents of registers/memory
– Comment out code, this might help you find out whether the
commented out code contains the bug
• Comment as you go, otherwise you will quickly forget
what you expected your code to accomplish
• Use your pseudo code as comments to the right of
the assembly code implementation