Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly Msvc内联程序集内部函数调用_Assembly_Call_Inline Assembly - Fatal编程技术网

Assembly Msvc内联程序集内部函数调用

Assembly Msvc内联程序集内部函数调用,assembly,call,inline-assembly,Assembly,Call,Inline Assembly,首先,我想说我研究过这件事,但找不到任何与之相关的东西 我在32版的发布模式下在MSVC 2013上编写C++控制台程序。 我在其中一个文件中使用了内联assmebly,它工作得很好,除非内联汇编函数_1调用函数_2,当这种情况发生时,会有一些指令被添加到函数_2,因此堆栈会损坏,程序会崩溃。 如果我停止使用调用,而仅仅是“leaebx,[eip+5]”,那么按一下ebx,jmp xxxxxx就可以了 在我的例子中,更具体一点,函数2的定义如下: void test() { _asm{

首先,我想说我研究过这件事,但找不到任何与之相关的东西

我在32版的发布模式下在MSVC 2013上编写C++控制台程序。 我在其中一个文件中使用了内联assmebly,它工作得很好,除非内联汇编函数_1调用函数_2,当这种情况发生时,会有一些指令被添加到函数_2,因此堆栈会损坏,程序会崩溃。 如果我停止使用调用,而仅仅是“leaebx,[eip+5]”,那么按一下ebx,jmp xxxxxx就可以了

在我的例子中,更具体一点,函数2的定义如下:

    void test()
{

_asm{
f_01758630:  // ; <= Procedure Start

    PUSH EBP
            MOV EBP, ESP
            PUSH ESI
            PUSH EDI
            mov edi, [ebp + 0x0C]
            XOR ESI, ESI
            SHR EDI, 0x2
            TEST EDI, EDI
            JLE f_0175866B
            PUSH EBX
            mov ebx, [ebp + 0x08]

    f_01758645:

        MOV EDX, DWORD PTR DS : [EBX + ESI * 0x4]
            ROL EDX, 0x10
            MOV ECX, EDX
            MOV EAX, EDX
            SHR ECX, 0x8
            SHL EAX, 0x8
            XOR ECX, EAX
            SHL EDX, 0x8
            AND ECX, 0xFF00FF
            XOR ECX, EDX
            MOV DWORD PTR DS : [EBX + ESI * 0x4], ECX
            INC ESI
            CMP ESI, EDI
            JL TERA_01758645
            POP EBX

        f_0175866B :

        POP EDI
            POP ESI
            POP EBP
            RETN//; <= Procedure End
}
}
push ebx push esi push edi push ebp mov ebp,esp push esi push edi
Ie msvc实现了3次推送,这可能与函数中的_asm{}有关吗?关于如何解决这个问题,有什么见解吗?

首先

push    ebp
mov     ebp, esp
push    ebx
push    esi
push    edi
是自动生成的函数序言。本次活动的结尾是结语:

pop     ebx
pop     edi
pop     esi
pop     ebx
pop     ebp
ret
您的
\u asm
块有自己的序言和尾声,因此代码会执行两次。更糟糕的是,
\u asm
块内的
ret
返回地址错误,程序将崩溃。您可以通过将函数声明为以下内容来避免函数序言/尾声:

这是危险的,因为您可能会忘记保留要原封不动返回的寄存器,“被调用方保存的寄存器”:EBX、EBP、EDI、ESI。在MSVC内联汇编中,很容易使用函数参数和局部变量,因此不需要控制epilog和prolog

请看这个示例(尽可能靠近您的代码):

#包括
无效函数2(无符号*reg\U ebx,无符号reg\U edi)
{
_asm
{
mov edi,reg_edi//接受第二个参数
xor esi,esi
shr edi,2
测试edi,edi
jle f_0175866b
mov ebx,reg_ebx//取第一个参数
f_01758645:
mov edx,dword ptr ds:[ebx+esi*0x4]
rol edx,16岁
mov ecx,edx
mov-eax,edx
shr-ecx,8
shl eax,8
xor ecx,eax
shl edx,8
和ecx,0xff00ff
xor ecx,edx
mov dword ptr ds:[ebx+esi*0x4],ecx
公司esi
cmp esi,edi
jl f_01758645
f_0175866b:
}
}
空洞函数_1()
{
无符号arr[8]={100020003004000500060007008000};
int i;
对于(i=0;i
Show function\u 1。同时尝试<代码> .yDeScript(裸)空测试(){{}} /Case>。编写程序集就像它是单独编译(组装)的,但是当C++函数的一部分,编译器将标准函数序言和尾随添加到代码中,谢谢大家,RKHB有完美的答案,它现在工作得很完美。这个问题已经讨论了好几个小时了。再次感谢。@MichaelPetch这个简单的修复方法是使用
\uu declspec(裸体)
。仅仅删除RETN指令是行不通的,因为操作数仍然是错误的。最好的修复方法是删除RETN和所有与堆栈相关的代码,更改函数以声明参数并在程序集中引用这些参数。但这可能超出了原始海报的处理能力,因为他们刚刚从其他地方剪切并粘贴了一些反汇编的字节交换代码。@rossridge你是对的,我没有仔细查看代码,也没有注意到他引用的是EBP,这当然会使他关于如果推送其他东西,堆栈上的内容的假设失效。
__declspec (naked) void test()
{
    _asm
    {
        own prolog
        ...
        own epilog
        ret
    }
}
#include <stdio.h>

void function_2(unsigned* reg_ebx, unsigned reg_edi)
{
    _asm
    {
            mov edi, reg_edi      // take the second argument
            xor esi, esi
            shr edi, 2
            test edi, edi
            jle f_0175866b
            mov ebx, reg_ebx     // take the first argument

        f_01758645:

            mov edx, dword ptr ds : [ebx + esi * 0x4]
            rol edx, 16
            mov ecx, edx
            mov eax, edx
            shr ecx, 8
            shl eax, 8
            xor ecx, eax
            shl edx, 8
            and ecx, 0xff00ff
            xor ecx, edx
            mov dword ptr ds : [ebx + esi * 0x4], ecx
            inc esi
            cmp esi, edi
            jl f_01758645

        f_0175866b :
    }
}

void function_1 ()
{
    unsigned arr[8] = {1000,2000,3000,4000,5000,6000,7000,8000};
    int i;
    for (i=0; i < sizeof(arr)/sizeof(arr[0]); ++i) printf ("%08X ",arr[i]); puts ("");

    _asm
    {
        push LENGTH arr
        lea eax, arr
        push eax
        call function_2
    }

    for (i=0; i < sizeof(arr)/sizeof(arr[0]); ++i) printf ("%08X ",arr[i]); puts ("");
}

int main ( void )
{
    function_1();
    return 0;
}