Msvc Inline assembly inner function calls -
first i'd researched matter couldn't find relevant related it.
i writting c++ console program on msvc 2013 on release mode 32 bit. using inline assmebly in 1 of file , works great except when inline assembly function_1 calls function_2, when happens there intructions added function_2 , therefore stack gets damaged , program crashs. if stop using calls merely "lea ebx,[eip+5]", push ebx, jmp xxxxxx instead works fine.
so in case , little more concrete function 2 defined :
void test() { _asm{ f_01758630: // ; <= procedure start push ebp mov ebp, esp push esi push edi mov edi, [ebp + 0x0c] xor esi, esi shr edi, 0x2 test edi, edi jle f_0175866b push ebx mov ebx, [ebp + 0x08] f_01758645: mov edx, dword ptr ds : [ebx + esi * 0x4] rol edx, 0x10 mov ecx, edx mov eax, edx shr ecx, 0x8 shl eax, 0x8 xor ecx, eax shl edx, 0x8 , ecx, 0xff00ff xor ecx, edx mov dword ptr ds : [ebx + esi * 0x4], ecx inc esi cmp esi, edi jl tera_01758645 pop ebx f_0175866b : pop edi pop esi pop ebp retn//; <= procedure end } }
however when debug running program can see function implemented :
push ebx push esi push edi push ebp mov ebp,esp push esi push edi
ie msvc implemented 3 pushs, maybe related _asm{} within function insight how can fix ?
the first
push ebp mov ebp, esp push ebx push esi push edi
is automatically generated prologue of function. @ end of function epilogue:
pop ebx pop edi pop esi pop ebx pop ebp ret
your _asm
block has own prologue , epilogue, code done twice. worse, ret
inside _asm
block gets wrong return address , program crash. can avoid function prologue/epilogue declaring function naked
:
__declspec (naked) void test() { _asm { own prolog ... own epilog ret } }
this dangerous, since can forget preserve registers returned unchanged, "callee saved registers": ebx, ebp, edi, esi. in msvc inline assembly, it's easy use function arguments , local variables, isn't necessary take control on epilog , prolog.
look @ example (as close possible code):
#include <stdio.h> void function_2(unsigned* reg_ebx, unsigned reg_edi) { _asm { mov edi, reg_edi // take second argument xor esi, esi shr edi, 2 test edi, edi jle f_0175866b mov ebx, reg_ebx // take first argument f_01758645: mov edx, dword ptr ds : [ebx + esi * 0x4] rol edx, 16 mov ecx, edx mov eax, edx shr ecx, 8 shl eax, 8 xor ecx, eax shl edx, 8 , ecx, 0xff00ff xor ecx, edx mov dword ptr ds : [ebx + esi * 0x4], ecx inc esi cmp esi, edi jl f_01758645 f_0175866b : } } void function_1 () { unsigned arr[8] = {1000,2000,3000,4000,5000,6000,7000,8000}; int i; (i=0; < sizeof(arr)/sizeof(arr[0]); ++i) printf ("%08x ",arr[i]); puts (""); _asm { push length arr lea eax, arr push eax call function_2 } (i=0; < sizeof(arr)/sizeof(arr[0]); ++i) printf ("%08x ",arr[i]); puts (""); } int main ( void ) { function_1(); return 0; }
Comments
Post a Comment