如何在__asm中使用变量?

cdo*_*nts 5 c++ x86 assembly inline-assembly visual-c++

我正在用VC编译器编译这个C++代码.我正在尝试使用语句调用一个带有两个WORD(aka unsigned short)参数的函数__asm,如下所示:

__declspec(naked) void __stdcall CallFunction(WORD a, WORD b)
{
    __asm {
        PUSH EBP
        MOV EBP, ESP
        PUSH a
        PUSH b
        CALL functionAddress
        LEAVE
        RETN
    }
}
Run Code Online (Sandbox Code Playgroud)

该功能functionAddress简单地输出结果a + b.然后调用CallFuncion(5, 5);打印"64351"或类似的东西.问题是在语句中使用ab变量时,__asm因为这有效:

PUSH EBP
MOV EBP, ESP
PUSH 5
PUSH 5
CALL functionAddress
LEAVE
Run Code Online (Sandbox Code Playgroud)

这是以下功能functionAddress:

void __stdcall Add(WORD a, WORD b)
{
    WORD c;
    c = a + b;
    printf("The result is %d\n", c);
}
Run Code Online (Sandbox Code Playgroud)

我怎么能以正确的方式做到这一点?所以__asm声明解释了ab价值观?

Jer*_*fin 4

由于您正在使用__declspec(naked)和设置自己的堆栈框架,因此我不相信编译器会让您通过名称来引用ab设置。使用__declspec(naked)基本上意味着您负责自己处理堆栈帧、参数等。

您可能需要有关此一般顺序的更多代码:

__asm {
    PUSH EBP
    MOV EBP, ESP 
    mov eax, [ebp+8]
    mov ebx, [ebp+12]
    push eax
    push ebx
    CALL functionAddress
    LEAVE
    RETN
}
Run Code Online (Sandbox Code Playgroud)

我已经有一段时间没有手工处理这样的事情了,所以你可能想重新检查这些偏移量,但如果我没记错的话,返回地址应该是[ebp+4]. 参数(通常)从右向左推送,因此最左边的参数应该是下一个 at [ebp+8],下一个参数应该是 at [ebp+12](请记住堆栈向下增长)。

编辑:[我应该更仔细地查看函数标题。]

您已标记CallFunction为使用__stdcall调用约定。这意味着需要清理传递给它的参数。因此,由于它接收 8 个字节的参数,因此在返回时需要从堆栈中删除 8 个字节:

    PUSH EBP
    MOV EBP, ESP
    mov eax, [ebp+8]
    mov ebx, [ebp+12]
    push eax
    push ebx
    CALL Add_f
    LEAVE
    RET 8
Run Code Online (Sandbox Code Playgroud)