So I'm wondering if I write a subroutine that doesn't use stack space for local vars or saved registers, do I need to prepare a stack frame?
MS C compiler generates this code for a simple function like this (without optimizations):
int foo()
{
return 123;
}
push ebp
mov ebp,esp
mov eax,7Bh
pop ebp
ret
Is there any need to prepare a stack frame if I aint using it?
Hi Fabioxds,
You can write functions without prologue and epilogue. In the C language, it's about naked functions :
QuoteThe naked storage-class attribute is a Microsoft-specific extension to the C language. For functions declared with the naked storage-class attribute, the compiler generates code without prolog and epilog code. You can use this feature to write your own prolog/epilog code sequences using inline assembler code. Naked functions are particularly useful in writing virtual device drivers.
https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/21d5kd3a%28v=vs.100%29
A quick Masm example :
include \masm32\include\masm32rt.inc
sum PROTO :DWORD,:DWORD
.data
template db '80 + 20 = %u',0
.data?
buffer db 32 dup(?)
.code
start:
invoke sum,20,80
invoke wsprintf,ADDR buffer,\
ADDR template,eax
invoke StdOut,ADDR buffer
invoke ExitProcess,0
; no prologue and no epilogue
; this means no stack frame generation
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
sum PROC x:DWORD,y:DWORD
mov eax,DWORD PTR [esp+8]
add eax,DWORD PTR [esp+4]
ret 2*4 ; balance the stack manually
sum ENDP
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
END start
sometimes, i even use EBP as a general register :biggrin:
you certainly do not need to use a stack frame if you don't want to :t
Thanks guys.
I'm just coming back from the x64 world and have another simple question, the stack space you restore when using naked functions would always be 4 * number of args? Assuming only DWORDs are being used, of course.
No more fuss with stack alignment, right ?? I miss x86!
Quotethe stack space you restore when using naked functions would always be 4 * number of args? Assuming only DWORDs are being used, of course.
Exactly. Since the parameters are passed to the stack, you need to balance it before returning back the control to the main procedure :
_start PROC NEAR
push 80
push 20
call _sum@8
.
.
.
_sum@8 LABEL NEAR
mov eax, dword ptr [esp+8H]
add eax, dword ptr [esp+4H]
ret 8 ; sum is a __stdcall function.
_start ENDP