100 likes | 231 Views
ICS51 Introductory Computer Organization. Accessing parameters from the stack and calling functions. Push instruction. • push REGISTER Decrements (by 4) the stack pointer register ( ESP ) Copies the value in REGISTER to the top of the stack. push EDI. ESP = ESP - 4. bottom of the stack.
E N D
ICS51Introductory Computer Organization Accessing parameters from the stack and calling functions
Push instruction • push REGISTER • Decrements (by 4) the stack pointer register (ESP) • Copies the value in REGISTER to the top of the stack pushEDI ESP = ESP - 4 bottom of the stack (higher address) content of the stack and ESP after push
Pop instruction • popREGISTER • Copies the value at the top of the stack to REGISTER • Increments (by 4) the stack pointer register (ESP) ESP pop EDI bottom of the stack (higher address) content of the stack and ESP before pop
Control flow instructions(subroutine call/return) • a procedure that calls another procedure: caller • procedure that has been called: callee main() { … countLowCaseChar(“Hello World”) … }
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
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)
Example __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; POP ecx; POP ebx; // 3. Return to the caller RET; } } void main() { int result = 0; __asm{ PUSH eax; PUSH ebx; PUSH ecx; // 1. Pass parameter(s) to the procedure MOV ebx, 10; PUSH ebx; // 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; } }
Example (cont.) void main() { int result = 0; __asm{ PUSH eax; PUSH ebx; PUSH ecx; // 1. Pass parameter(s) to the procedure MOV ebx, 10; PUSH ebx; // 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; } }
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; POP ecx; POP ebx; // 3. Return to the caller RET; } }
__declspec(naked) • __declspec(naked)tells C compiler not to insert prolog/epilog code: • function parameters are not copied from stack to the parameter variables, and local variables are not allocated • have to retrieve function parameters from stack • registers are not saved to stack in the beginning of the function and are not restored at the end • have to do it yourself • return statement cannot be used • you need to explicitly insert retAssembly instruction at the end of your function • you need to return the value by putting it in EAX