Download presentation
Presentation is loading. Please wait.
1
Accessing parameters from the stack and calling functions
2
2 Outline 1. STACK architecture - STACK Memory - PUSH and POP 2. Procedure Call - Caller and Called Functions - CALL and RET 3. Parameter Passing - In Caller Function ^ Push Parameters from right-most to left ^ CALL CALLED_FUNC ^ Continue processing in Caller Function - In CALLED_FUNC ^ Save Registers that may be used ^ POP parameters ^ Do processing ^ Keep the result at EAX ^ Restore saved registers ^ RET
3
3 Stack Manipulation Instructions Hardware supported stack in memory Stack grows down - i.e. stack grows from high address to low address Stack manipulation instructions are used to: – place parameters on the stack before calling a procedure – save register values inside a procedure – reserve space for temporary variable inside a procedure
4
4 Memory Each byte has a unique address in Memory All pointers are 32 bits long byte ptr[eax] word ptr[eax+4] dword ptr[eax+ebx*2] mov eax,X (X is address of variable!) mov ebx, 0x00000004 Memory X X+1 X+2 X+3 X+4 X+5 X+6 X+7 X+8.
5
5 Push instruction push REGISTER 1.Decrements (by 4) the stack pointer register (ESP) 2.Copies the value in REGISTER to the top of the stack push EDI bottom of the stack (higher address) ESP = ESP - 4 content of the stack and ESP after push
6
6 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) pop EDI bottom of the stack (higher address) ESP content of the stack and ESP before pop
7
7 Control flow instructions (subroutine call/return) call my_procedure 1.Pushes the current code location (the value of IP register) onto the stack 2.Performs an unconditional jump to the code location indicated by ”my_procedure” ret 1.Pops the code location off the stack 2.Puts it to IP (instruction pointer) register (thus performing unconditional jump to the retrieved location) how are parameters passed to the procedure? –Using the stack, last parameter is stored first on the stack how to return value? –Using EAX, put the value to be returned into the EAX register
8
8 a procedure that calls another procedure: caller procedure that has been called: callee
9
9 The caller should: Before calling a procedure: push to the stack: ECX, EDX <– caller-saved registers 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: the return value is in EAX remove parameters from the stack (to restore the stack to its state before call was performed) pop from the stack: EDX, ECX (Note the reverse order)
10
10 The callee should : At the beginning of procedure: push to the stack: EBX, EDI, ESI, EBP (if you are going to use particular register) <– callee-saved registers When the procedure is done: the return value should be placed in EAX pop from the stack: EBP, ESI, EDI, EBX (in the reverse order) execute ret instruction (return to the caller)
11
11 Example 1 Saving registers used inside the function on the stack Restoring the saved registers from the stack How parameters are passed on the stack –Pushed on the stack from right to left –The return address of the procedure is also on the stack!! Accessing parameters –When inside the “firstpass” function, the stack looks like the table in the up right corner (on the next page) –To access the a location on the stack, use an instruction like mov REG, dword ptr[ESP+OFFSET] The “ret” instruction Return value in the “eax” register
12
12 int main(void) { int arr[] = {0,1,2,3,4}; int sum = firstpass(arr,5); printf(" The sum is = %d\n",sum); return 0; } __declspec(naked) int firstpass (int *arr, int len) { __asm { /* Save the registers that may be modified by the called function*/ push ecx push edx /* put the parameters on the stack for the add2nums function */ push edx // edx contains length push ecx // ecx contains array mov edx, dword ptr[esp + 24] /* load the len parameter from the stack */ mov ecx, dword ptr[esp + 20]/* load the arr parameter from the stack */ call add2nums /* pop the parameters of the stack after the call – to restore the stack*/ pop ecx pop edx /* restore the registers from the stack*/ pop edx pop ecx ret }
13
13 Note: __declspec(naked) before the declaration of the function Tells C compiler not to insert prolog/epilog code That means that: –function parameters are not copied from stack to the parameter variables; 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 ret Assembly instruction at the end of your function you need to return the value by putting it in EAX
14
14 __declspec(naked) int add2nums(int *array, int length) { __asm { /* Save the registers used in this function to the stack Do not save eax */ /* need not to push ebx, esi, ebp because we are not going to use those */ push edi xor eax,eax xor edi,edi /* this accesses the "array" parameter on the stack */ mov ebx, dword ptr[esp + 8] /* load the "length" parameter from the stack */ mov edx, dword ptr[esp + 12] loop1: cmp edx,edi je all_done /* copies i-th element or an array */ mov ecx, dword ptr[ebx+4*edi] /* the value returned by this function is put in eax */ add eax,ecx inc edi jmp loop1 all_done: /* restore the saved registers from the stack */ pop edi ret }
15
15 Example 2 void main() { int result = 0; __asm{ // 1. Push register values to the stack PUSH eax; PUSH ebx; PUSH ecx; MOV ebx, 10; // 2. Pass parameter(s) to the procedure PUSH ebx; // 3. Execute call CALL add_func; // 4. Remove parameter(s) from the stack POP ebx; // 5. EAX has the return value MOV result, eax; // 6. Pop register values in reverse order POP ecx; POP ebx; POP eax; } __declspec(naked) int add_func(int param1) { __asm{ // 1. Push register values to the stack to save PUSH ebx; PUSH ecx; // 2. Access param1 MOV ebx, dword ptr[esp+12]; MOV ecx, ebx; ADD ecx, 5; // 3. The return value should be placed in EAX MOV eax, ecx; // 4. Pop the register values from the stack POP ecx; POP ebx; // 5. Return to the caller RET; }
16
16 Example 2 void main() { int result = 0; __asm{ // 1. Push register values to the stack PUSH eax; PUSH ebx; PUSH ecx; MOV ebx, 10; // 2. Pass parameter(s) to the procedure PUSH ebx; // 3. Execute call CALL add_func; // 4. Remove parameter(s) from the stack POP ebx; // 5. EAX has the return value MOV result, eax; // 6. Pop register values in reverse order POP ecx; POP ebx; POP eax; } ECXESP EBXESP+4 EAXESP+8 param1ESP ECXESP+4 EBXESP+8 EAXESP+12 Return AddrESP param1ESP+4 ECXESP+8 EBXESP+12 EAXESP+16 ECXESP EBXESP+4 EAXESP+8
17
17 Return AddrESP param1ESP+4 ECXESP+8 EBXESP+12 EAXESP+16 __declspec(naked) int add_func(int param1) { __asm{ // 1. Push register values to the stack to save PUSH ebx; PUSH ecx; // 2. Access param1 MOV ebx, dword ptr[esp+12]; MOV ecx, ebx; ADD ecx, 5; // 3. The return value should be placed in EAX MOV eax, ecx; // 4. Pop the register values from the stack POP ecx; POP ebx; // 5. Return to the caller RET; } ECXESP EBXESP+4 Return AddrESP+8 param1ESP+12 ECXESP+16 EBXESP+20 EAXESP+24 Return AddrESP param1ESP+4 ECXESP+8 EBXESP+12 EAXESP+16 param1ESP+4 ECXESP+8 EBXESP+12 EAXESP+16
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.