Transcript Slide
ICS51
Introductory Computer
Organization
Accessing parameters from the
stack and calling functions
Push instruction
• push REGISTER
1.
2.
Decrements (by 4) the stack pointer register (ESP)
Copies the value in REGISTER to the top of the stack
push EDI
ESP = ESP - 4
ESP
bottom of the stack
(higher address)
content of the stack and ESP before push
bottom of the stack
(higher address)
content of the stack and ESP after push
2
Pop instruction
• pop REGISTER
1.
Copies the value at the top of the stack to REGISTER
2.
Increments (by 4) the stack pointer register (ESP)
ESP
pop EDI
ESP = ESP + 4
bottom of the stack
(higher address)
content of the stack and ESP before pop
bottom of the stack
(higher address)
content of the stack and ESP after pop
3
Control flow instructions
(subroutine call/return)
• a procedure that calls another procedure: caller
• procedure that has been called: callee
main() {
…
countLowCaseChar(“Hello World”)
…
}
4
The caller should
• Before calling a procedure:
• pass parameters to the procedure: push to the stack in
reverse order (the last parameter is pushed first)
• execute call (to perform the procedure call)
• After the procedure returns:
• pop parameters from the stack (to restore the stack to its
state before call was performed)
• the return value is in EAX
5
The callee should
• At the beginning of procedure:
• access passed parameters using ESP
• When the procedure is done:
• the return value should be placed in EAX
• execute ret instruction (return to the caller)
6
Example
void main()
{
int result = 0;
__asm{
PUSH eax;
PUSH ebx;
PUSH ecx;
__declspec(naked)
int add_func(int param1)
{
__asm{
PUSH ebx;
PUSH ecx;
// 1. Access param1
MOV ebx, dword ptr[esp+12];
// 1. Pass parameter(s) to the procedure
MOV ebx, 10;
PUSH ebx;
MOV ecx, ebx;
ADD ecx, 5;
// 2. Execute call
CALL add_func;
// 2. The return value should be placed in EAX
MOV eax, ecx;
// 3. Remove parameter(s) from the stack
POP ebx;
POP ecx;
POP ebx;
// 4. EAX has the return value
MOV result, eax;
POP ecx;
POP ebx;
POP eax;
// 3. Return to the caller
RET;
}
}
}
}
7
Example (cont.)
void main()
{
int result = 0;
__asm{
ECX
ESP
EBX
ESP+4
PUSH eax;
PUSH ebx;
PUSH ecx;
EAX
ESP+8
10 (param1)
ESP
// 1. Pass parameter(s) to the procedure
MOV ebx, 10;
PUSH ebx;
ECX
ESP+4
EBX
ESP+8
EAX
ESP+12
Return Addr
ESP
10 (param1)
ESP+4
ECX
ESP+8
EBX
ESP+12
EAX
ESP+16
ECX
ESP
EBX
ESP+4
EAX
ESP+8
// 2. Execute call
CALL add_func;
// 3. Remove parameter(s) from the stack
POP ebx;
// 4. EAX has the return value
MOV result, eax;
POP ecx;
POP ebx;
POP eax;
}
}
8
Return Addr
ESP
param1
ESP+4
ECX
ESP+8
EBX
ESP+12
EAX
ESP+16
ECX
ESP
EBX
ESP+4
Return Addr
ESP+8
param1
ESP+12
ECX
ESP+16
EBX
ESP+20
EAX
ESP+24
Return Addr
ESP
param1
ESP+4
POP ecx;
POP ebx;
ECX
ESP+8
EBX
ESP+12
// 3. Return to the caller
RET;
EAX
ESP+16
param1
ESP+4
ECX
ESP+8
EBX
ESP+12
EAX
ESP+16
Example (cont.)
__declspec(naked)
int add_func(int param1)
{
__asm{
PUSH ebx;
PUSH ecx;
// 1. Access param1
MOV ebx, dword ptr[esp+12];
MOV ecx, ebx;
ADD ecx, 5;
// 2. The return value should be placed in EAX
MOV eax, ecx;
}
}
9
__declspec(naked)
• __declspec(naked) tells C compiler not to insert
prolog/epilog code:
1. function parameters are not copied from stack to the parameter
variables, and local variables are not allocated
•
have to retrieve function parameters from stack
2. registers are not saved to stack in the beginning of the function
and are not restored at the end
•
have to do it yourself
3. return statement cannot be used
•
•
you need to explicitly insert ret Assembly instruction at the end of
your function
you need to return the value by putting it in EAX
10