I'm attempting to write a function in assembly that sets a block of memory to a specified value, much like memset(), however, when I go to get the third argument off the stack (it uses the fastcall calling convention), the register, ECX, gets some garbled value.
By putting the code into Visual Studio using inline assembly, I see that ESP is significantly changed when the function is called. The first two arguments are being put into ECX and EDX without any issue, it's just the third one that is causing trouble.
I know the code works the block of memory is filled with the correct value when I manually set the value in the register whilst debugging in VS.
I'm relatively new to assembly, so my code is probably a bit dodgy, but does anyone know how to fix this problem?
The code is below:
#ifdef __GNUC__
#define __fastcall __attribute__((fastcall)) // 'Cause I'm a M$ fanboy
#endif
void __fastcall memset(void *pDest, int iValue, int iSize)
{
__asm
{
; Assume the pointer to the memory is stored in ECX
; Assume the value is stored in EDX
; Assume the size of the block is stored on the stack
mov eax, esi ; Put ESI somewhere it won't be touched (I think)
mov esi, ecx ; Move the address of the memory into ESI
xor ecx, ecx ; Zero ECX
pop ecx ; Get the size of the block into ECX. ECX is our loop counter
memset_count:
cmp ecx, 0 ; If we are at the end of the block,
jz memset_return ; Jump to return
mov [esi], edx ; Move our value into the memory
inc esi ; Otherwise, increment out position in the memory
dec ecx ; Decrement out counter
jmp memset_count ; Start again
memset_return:
mov esi, eax ; Restore ESI
add esp, 4 ; Remove our third argument from the stack
ret
}
}
#define ret return
int main(int argc, char **argv)
{
char szText[3];
/*
__asm
{
push 3
mov edx, 65
lea ecx, szText2
call memset
}
*/
memset(&szText, 'A', 3);
ret 42;
}
The first thing on the called code's stack will be the return address for the call. The second thing will be the first argument.
To avoid changing ESP, and to fix the "popping the wrong thing" problem, try something like "mov ecx,[esp+4]" (instead of the "pop ecx").