【发布时间】:2015-09-30 15:53:27
【问题描述】:
首先我想说我研究了这件事,但找不到任何相关的东西。
我正在 msvc 2013 上以 32 位发布模式编写一个 c++ 控制台程序。 我在其中一个文件中使用内联汇编,它工作得很好,除非我的内联汇编函数_1调用我的函数_2,当这种情况发生时,有指令被添加到函数_2,因此堆栈被损坏并且程序崩溃。 如果我停止使用呼叫,而只是“lea ebx,[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
即 msvc 实现了 3 次推送,这可能与函数内的 _asm{} 相关,对我如何解决此问题有任何见解吗?
【问题讨论】:
-
显示函数_1。同时尝试
__declspec (naked) void test() {...}。 -
您编写程序集就像是单独编译(组装)一样,但是当成为C++函数的一部分时,编译器会在代码中添加标准函数序言和结尾,
-
谢谢大家,rkhb 给出了完美的答案,它现在可以完美运行了。几个小时以来,这一直是个问题。再次感谢。
-
@MichaelPetch 这个简单的解决方法是使用
__declspec(naked)。仅仅删除 RETN 指令是行不通的,因为[ebp + 0x0X]操作数仍然是错误的。最好的解决方法是删除 RETN 和所有与堆栈相关的代码,更改函数以声明参数并在程序集中引用这些参数。但这可能超出了原始海报所能处理的范围,因为他们只是从其他地方剪切并粘贴了一些反汇编的字节交换代码。 -
@rossridge 你是对的,我没有仔细查看代码,也没有注意到他正在引用 EBP,这当然会使他对堆栈中的内容的假设无效推。
标签: assembly call inline-assembly