Восстановление стека вызывает нарушение прав доступа - PullRequest
1 голос
/ 04 декабря 2011

Я пишу по существу эквивалентно memset () с использованием ASM.Код, который я написал, работает, за исключением того, что когда я пытаюсь восстановить стек, он вылетает с нарушением прав доступа.Я поместил код в MSVC, используя встроенную сборку, чтобы отладить его.

Проблема возникает, когда функция возвращается.Однако когда я вынимаю строку add esp, 4, код выполняется правильно, но после того, как функция main () вернулась, MSVC сообщает, что стек вокруг переменной поврежден.

Я не хочу продолжать безadd esp, 4, как я знаю, это вызовет проблемы позже.

Как мне исправить это?

int main(int argc, char **argv)
{
    char szText[3];


    /*__asm
    {
        push 3
        mov edx, 65
        lea ecx, szText
        call memset
    }*/

    memset((void*)&szText, 'A', 3);

    return 42;
}

void __declspec(naked) __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

            mov ecx, [esp+4]    ; 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          ; Clean up the stack
            ret

    }
}

Ответы [ 2 ]

3 голосов
/ 04 декабря 2011
        memset_return:
            mov esi, eax        ; Restore ESI
            add esp, 4          ; Clean up the stack
            ret

Это неправильно, вы не вычитали 4 из ESP в теле функции. Вы фактически пропустите адрес возврата, и RET извлечет аргумент из стека и перейдет к его значению. Kaboom. Исправлено:

        memset_return:
            mov esi, eax        ; Restore ESI
            ret 4

Вы также будете иметь , чтобы написать прототип функции, чтобы компилятор знал, что соглашение о вызовах для функции нестандартно. Он будет генерировать неправильный код на сайте вызова, если он не знает. Вставьте это перед основным методом:

 void  __fastcall memset(void *pDest, int iValue, int iSize);

И избегайте называть его "memset", это встроенная функция, которая также генерируется генератором кода. Он будет вызывать вашу функцию вместо стандартной. Что пойдет плохо, у стандартного совсем другая подпись. Выберите другое имя, чтобы избежать почти невозможного устранения ошибки.

1 голос
/ 04 декабря 2011

Используйте ret 4 вместо add esp, 4 / ret

...