访问违反了“RET”指令(Access violation on 'ret' ins

2019-09-27 17:29发布

我有这个功能,而且大多为内联汇编。

long *toarrayl(int members, ...){
    __asm{
        push esp

        mov eax, members
        imul eax, 4
        push eax
        call malloc
        mov edx, eax
        mov edi, eax

        xor ecx, ecx
        xor esi, esi
loopx:
        cmp ecx, members
        je done
        mov esi, 4

        imul esi, ecx
        add esi, ebp
        mov eax, [esi+0xC]
        mov [edi], eax
        inc ecx
        add edi, 4
        jmp loopx
done:
        mov eax, edx
        pop esp
        ret
    }
}

而且一旦运行,我得到一个访问冲突的返回指令。

我使用VC 6,它有时意味着在上面的行至点,所以有可能在“流行ESP”。 如果你能帮助我,这将会是巨大的。 谢谢,iDomo。

Answer 1:

您不能正确地管理堆栈指针。 特别是,你要调用malloc不平衡堆栈,你pop esp结束了弹出错误值到esp 。 因此,访问冲突,当您尝试发生ret从一个无效的堆栈(CPU不能读取的返回地址)。 目前还不清楚为什么要推动和弹出esp ; 那一事无成。



Answer 2:

当你发现,你永远不应该使用指令POP ESP - 当你看到,在代码中,你知道的东西极其错误的发生。 当然,调用asseembler代码中的malloc也相当糟糕的事情 - 你有例如忘记检查,如果它返回NULL,所以你可能会崩溃。 坚持你的汇编程序之外 - 和检查NULL,它更容易调试“的第54行中的文件mycode.c中无法分配内存”比“某处在汇编中,我们得到了一个

下面是一些改进的意见,应该加快你的循环了一下:

long *toarrayl(int members, ...){
    __asm{
        mov eax, members
        imul eax, 4
        push eax
        call malloc
        add esp, 4
        mov edx, eax
        mov edi, eax

        mov ecx, members
        lea esi, [ebp+0xc]
loopx:
        mov eax, [esi]
        mov [edi], eax
        add edi, 4
        add esi, 4
        dec ecx
        jnz loopx
        mov lret, eax
        ret
    }
}

改进:乘以四的每一个回路删除。 只是增加esi代替。 使用递减的ECX,而不是increament,并与循环前成员加载它。 这使得在循环只是一个跳跃,而不是两个的使用。 从EDX删除reduntant动,EAX。 直接使用EAX。



Answer 3:

我已经想通了我自己的答案。

对于那些谁都有过这样的相同,或相似的问题:

实际的例外是用户代码后存在的,当VC ++自动弹出/恢复寄存器进入状态被称为函数之前。 由于调用malloc当我错过对准堆栈指针,有从堆栈坡平当访问冲突。 我没能看到这个编辑器,因为它不是我的代码,因此它只是显示为最后我在功能代码。

为了解决这个问题,只需添加你打的电话后ADD ESP,(对以前调用参数的大小)。

固定的代码:

long *toarrayl(int members, ...){
    __asm{
        mov eax, members
        imul eax, 4
        push eax
        call malloc
        add esp, 4
        mov edx, eax
        mov edi, eax

        xor ecx, ecx
        xor esi, esi
loopx:
        cmp ecx, members
        je done
        mov esi, 4

        imul esi, ecx
        add esi, ebp
        mov eax, [esi+0xC]
        mov [edi], eax
        inc ecx
        add edi, 4
        jmp loopx
done:
        mov eax, edx
        ret
    }
    //return (long*)0;
}

优化的代码:

long *toarrayl(int members, ...){
    __asm{
        mov eax, members
        shl eax, 2
        push eax
        call malloc
        add esp, 4
        ;cmp eax, 0
        ;je _error
        mov edi, eax
        mov ecx, members
        lea esi, [ebp+0xC]
loopx:
        mov edx, [esi]
        mov [edi], edx
        add edi, 4
        add esi, 4
        dec ecx
        jnz loopx
    }
}


文章来源: Access violation on 'ret' instruction