Я пытаюсь написать функцию в ассемблере, которая устанавливает блок памяти в указанное значение, очень похоже на memset (), однако, когда я собираюсь получить третий аргумент из стека (он использует соглашение о вызовах fastcall ), регистр ECX получает искаженное значение.
Поместив код в Visual Studio с использованием встроенной сборки, я вижу, что ESP значительно изменяется при вызове функции.
Первые два аргумента вводятся в ECX и EDX без каких-либо проблем, только третий вызывает проблемы.
Я знаю, что код работает, блок памяти заполняется правильным значением, когда я вручную устанавливаю значение в регистр во время отладки в VS.
Я относительно новичок в сборке, поэтому мой код, вероятно, немного хитрый, но кто-нибудь знает, как решить эту проблему?
Код ниже:
#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;
}