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"或类似的东西.问题是在语句中使用a和b变量时,__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声明解释了a和b价值观?
由于您正在使用__declspec(naked)和设置自己的堆栈框架,因此我不相信编译器会让您通过名称来引用a和b设置。使用__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)