比“添加esp,4”更小的指令

时间:2010-01-10 20:09:14

标签: optimization assembly x86

我再次。

我的程序中有很多“添加esp,4”,我正在尝试减小它的大小。是否有任何较小的指令可以取代“add esp,4”?

8 个答案:

答案 0 :(得分:5)

pop edx  

或者你不介意破坏的任何其他整数寄存器。

This is what modern compilers actually do(clang,有时是gcc),因为它通常是性能以及现代CPU上代码大小的最佳选择。

add esp,4之后的call会强制CPU的堆栈引擎在执行实际add之前插入堆栈同步uop。如果您在下一次push / pop / call / ret之前没有直接修改使用ESP,除了堆栈指令(例如作为寻址模式的一部分),那么您使用pop保存了一个uop。

如果最近运行了任何其他堆栈指令,堆栈内存的缓存行将在缓存中变得很热(使负载变得便宜)。

答案 1 :(得分:5)

一个更好的问题可能是:“为什么你有这么多add esp, 4指令,你能做些什么来减少它们?”像这样对堆栈指针进行大量的小增量有点不寻常。

您是否同时向堆叠移动堆栈?您可以使用push / pop吗?

或者,你真的需要如此频繁地更新堆栈指针,或者你可以在代码块的开头移动它一次以在堆栈上创建一些空间,然后在结束时恢复它一次例程?

你真的想做什么?

答案 2 :(得分:4)

很抱歉,如果这听起来微不足道......但是如果您设法重新排序代码以便连续使用多个add esp, 4指令,那么您当然可以将它们简化为例如:

add esp, 8

甚至:

add esp, 12

确保移动的指令不引用esp或堆栈;或者如果他们确实在堆栈上引用某些内容,则只能通过ebp寄存器进行。

答案 3 :(得分:2)

尝试使用pop eax

答案 4 :(得分:2)

如果您有多个函数调用,可以使用一种方法:

sub esp, 4
mov 0(esp), param
call ...
...
mov 0(esp), param2
call ...
...
add esp, 4

即,在多个函数调用中重用为第一个参数分配的堆栈。

答案 5 :(得分:1)

如果您在调用后调整堆栈,则更好的方法是使用RETN X,其中X是要在ESP上添加的字节数...

PUSH EAX
CALL EBX (in this func, you use RETN 4)    
<<here the stack is already aligned>>

或者,使用POPFD =x

答案 6 :(得分:0)

如果您正在管理堆栈(我假设您是),您可以使用push eaxpop eax向堆栈添加值并维护esp。您还可以使用pusha/popa等指令将所有GPR打开/弹出堆栈,并pushf/popf将EFLAGS寄存器推入/弹出堆栈。

答案 7 :(得分:0)

popfd只会在一个字节中向esp添加4,副作用是随机化您的标记。执行起来可能很慢;我不知道。

当然,查看代码或了解真正的要求会有所帮助。