tags:

views:

106

answers:

2

I'm using GCC with the -fomit-frame-pointer and -O2 options. When I looked through the assembly code it generated,

push %ebp
movl %esp, %ebp

at the start and pop %ebp at the end is removed. But some redundant subl/addl instructions to esp is left in - subl $12, %esp at the start and addl $12, %esp at the end.

How will I be able to remove them as some inline assembly will jmp to another function before addl is excecuted.

+2  A: 

You probably don't want to remove those -- that's usually the code that allocates and deallocates your local variables. If you remove those, your code will trample all over the return addresses and such.

The only safe way to get rid of them is not to use any local variables. Even in macros. And be really careful about inline functions, as they often have their own locals that'll get put in with yours. You may want to consider explicitly disabling function inlining for that section of code, if you can.

If you're absolutely sure that the adds and subs aren't needed (and i mean really, really sure), on my machine GCC apaprently does some stack manipulation to keep the stack aligned at 16 byte boundaries. You may be able to say "-mpreferred-stack-boundary=2", which will align to 4-byte boundaries -- which x86 processors like to do anyway, so no code is generated to realign it. Works on my box with my GCC; int main() { return 0; } turned into

main: 
    xorl %eax, %eax
    ret

but the alignment code looked different to start with...so that may not be the problem for you.

Just so you're warned: optimization causes a lot of weird stuff like that to happen. Be careful with hand-coded assembler language and optimized <insert-almost-any-language-here> code, especially when you're doing something as unstructured as a jump from the middle of one function into another.

cHao
I'm not using any local variables in that function so I can remove them just fine. It properly assemles and links without any errors if I remove them by hand.
kotarou3
Yes, but does it *run*? The compiler doesn't generally insert code for the heck of it -- it usually knows what it's doing, so chances are there's a reason it reserved 18 bytes of stack space. If that space isn't there, chances are any code that would use it will corrupt the stack instead. Updated the answer a bit.
cHao
I looked through the code thoroughly and removing the subl/addl will not affect it in any way. And yes, it runs
kotarou3
@kotarou3: Edited.
cHao
Yes, I'm absolutely sure that addl/subl is not needed. And it didn't work for me. Changing `-mpreferred-stack-boundary` to 2 replaced the `$12, %esp` with `$4, %esp` instead. Interesting... Or it might be because I'm using Windows
kotarou3
It could be. I don't see why it'd want 4 extra bytes on Windows, but i've seen stranger things happen. Just wondering, though: is this a 64-bit machine you're compiling on, and/or perhaps a 64-bit version of gcc?
cHao
No. It is all 32bit/x86
kotarou3
It's local variables and/or temporary value storage. Just because you don't name local variables doesn't mean no stack space is allocated in a function.
nategoose
The function is almost pure assembly.
kotarou3
A: 

How will I be able to remove them as some inline assembly will jmp to another function before addl is excecuted.

This will corrupt your stack, that caller expects the stack pointer to be corrected on function return. Does the other function return by ret instruction? What exactly do you try to achieve? maybe there's another solution possible?

Please, show us the lines around the function call (in the caller) and your entry/exit part of your function in question.

Regards

rbo

rubber boots
The stack will only be corrupted if the `subl` stays. Thats why I am trying to make gcc not add it in.
kotarou3