1

我试图在汇编中编写一个函数,将一块内存设置为指定值,就像 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;
    }


4

2 回答 2

2

问题是这是在一个函数中,编译器已经弹出了一些变量。gcc 有一种引用变量的方法,我不知道 MSVC

于 2011-12-04T04:45:55.453 回答
2

被调用代码堆栈上的第一件事将是调用的返回地址。第二件事将是第一个论点。

为避免更改 ESP,并解决“弹出错误的东西”问题,请尝试“mov ecx,[esp+4]”(而不是“pop ecx”)。

于 2011-12-04T04:43:25.283 回答