如何阻止 ESP 在 __fastcall 中被损坏?

发布于 12-19 05:02 字数 1948 浏览 6 评论 0原文

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


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;
    }


如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

江心雾2024-12-26 05:02:36

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

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

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").

池木2024-12-26 05:02:36

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

The problem is the fact that this is in a function, the compiler already poped some of the variables. gcc has a way for referencing variables, I don't know about MSVC

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文