memset()のように、メモリのブロックを指定された値に設定する関数をアセンブリで書き込もうとしていますが、スタックから3番目の引数を取得しようとすると(fastcall呼び出し規約を使用します)、レジスタECXは、文字化けした値を取得します。
インラインアセンブリを使用してコードをVisualStudioに配置すると、関数が呼び出されたときにESPが大幅に変更されることがわかります。最初の2つの引数は問題なくECXとEDXに入れられており、問題を引き起こしているのは3番目の引数にすぎません。
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;
}