Assembly local variable and parameters - c

I have the following code
#include<stdio.h>
int adunare(int a,int b)
{
int c=3;
int d=6;
while(c>10) c++;
if(c>15) return a+b+c+d;
else return a+b+c-d;
}
int main()
{
int w=5;
int y=6;
printf("%d",adunare(w,y));
}
My question is in assembly it puts the variable w,y at the [esp+24] ,[esp+28].
Why it puts my variables there?
I know that local variables are always [ebp-....].
Why here it is not [ebp-..]?

I know that local variables are always [ebp-....]
They're not (as evidenced by your question too, I suppose).
It's legal for a compiler to compile really naively, always using a frame pointers (even in functions that don't do variable-size stack allocations) and always putting locals on the stack in the first place (which is definitely not a rule). In a first year course in university, it is sometimes pretended that that's normal, to keep things simple.
Not using a frame pointer is usually possible, it works mostly the same as if you had used one except that offsets are calculated relative to the stack pointer, which you are now only allowed to move in predictable ways. Because it has to be predictable (that is, every instructions that references a stack slot can use a constant offset to do so), this optimization cannot be used in functions that use alloca or VLAs. In your example function neither are used, so no frame pointer is necessary.
Also in general you should not expect local variables to correspond to specific stack slots in the first place, regardless of how they are addressed. It is allowed, common, and often a good thing, to keep a variable in a register over the entire lifetime of the variable. Especially if that life time is short or if the usage-density is very high. On top of that, variables with non-overlapping life times can (and should, because it reduces the stack size) share stack slots, since it would be the case that at most one of them needs storage at any one moment (thanks to the assumption of non-overlapping life times).
It's also allowed to have a variable hop from one stack slot to an other, this might happen when you swap two variables in a way that allows the swap to be resolved "virtually", by just changing which stack slot the variables live in and not actually exchanging the data.

That's probably a compiler optimization. The variables aren't used within main scope so are placed directly on the stack, ready for the function call.

Related

Local Variable in Function

I found out something hilarious problem in C.
Here is my Code
#include <stdio.h>
void method()
{
int indx;
printf("%d\n", indx);
indx++;
}
int main(void)
{
method();
method();
method();
}
This is simple example.
indx variable is not initialized. So, The result of printf in method function would be something strange value.
And indx is local variable. So indx++ is useless.
But The answer is
0
1
2
It seems like that indx is remain
I can't understand. why?
Local variables are stored on the stack. Because you are doing no other action between each function call, the stack is essentially preserved (unaltered) between calls, and the lack of initialisation means that the value of indx is whatever happens to be stored in that stack location.
If you made other function calls, the stack might well be overridden, resulting in non-sequential values, and likely not starting from zero.
One reason why the stack might contain zero values at startup can be because, depending on compiler, compiler options and standard library startup, the stack might be deliberately initialised to zero (or just because the region of memory used happens to contain zeros from a previous application etc).
One should never rely on such behaviour, it is specifically undefined behaviour, and thus initialising variables and ensuring you understand variable scope is an important thing to learn in software development.
I think there are plenty of descriptions of how stack is used in software development languages (and variability across hardware architectures and implementations) that you should research that separately.
The local variables are especially stored in the memory area of the corresponding function, hence you can see the increment of the indx value by single value each time the function is called.
But the answer returns the memory values of the stored variable.

Can we get the elements in the middle of "stack" directly?

Think of the situation as follow.
int main(void)
{
...
int a=10; //a get into the stack.
int b=20; //b get into the stack.
int c=30; //c get into the stack.
...
}
As we know, the “stack segment” is satisfied with the storage approach of "stack data structure"; and here, the local variables a, b, and c are exactly stored in such a direction of memory, so in theory we can only access to the element at the top of the stack.
But what if we do something like this?
printf("b = %d",b);
Local variable b is in the middle of a and c, but we can get it.
So...can we say that we can directly get the element in the middle of the stack?
Here is the image of " a, b, and c stored in stack "
the local variables a, b, and c are exactly stored in such a direction of memory
I don't know from where you got this but this is not true, at least in modern compilers.
First of all, C itself doesn't specify anything about using a stack. How the function calls are implemented is implementation defined. Lots of common implementations use stack like data structure to implement function call in the sense that last called function will be returned first.
But this doesn't mean that the local variables are stored in stack like structure. There are lots of options to the compiler like:
It can eliminate the variable completely if that is not needed in run-time.
It can place the variables in register.
It can re-order variables.
In all of these cases the only thing that compiler guarantees that the observable behavior of the code is not changed.
Since it doesn't store variables in stack like data structure, it has no problem to access them in middle.
First of all C standard never utter stack` anywhere. Now moving from standard - implementors may implement such a way that local variables are stored in stack memory as part of function frame.
Now you are thinking - stack is always accessed on top but here we can access the variable b directly. Though it is in the middle somewhere. Nope you are wrong - the thing is the frame of the functions are which are stored in stack and popped off when done(though an implementation can do it other way also - but speaking in general). It is not the variables that are the unit of operations here.
By accessing b we are not violating any rule of stack data structure. The function frames are the ones which are accessed in LIFO manner not the variables inside those frames.
Also it's a bit out of context now a days to segregate like that. We can simply say that they have automatic storage duration. And that's it. They can be implemented in group of registers also(standard won't stop them). The function frames are the one which will likely to be have that stack data-structures behavior.
Usage of the stack to store automatic variables is only an implementation detail, nothing is required by the standard. But at a lower level it is indeed the most common implementation. It is because in processors, a special register (stack pointer) is used to store return addresses in function calls (instructions call and return). When automatic variables are also stored in that stack, it is trivial to reclaim there storage back at return time or at end of the block. But they are not individually pushed onto a stack: a frame pointer is used to store the memory zone for the current block (including a reference for upper frames) and the stack pointer is increased in one single operation for the size of the frame containing all the local variables. Then those variables are known by the offset to the current frame pointer. So they are known by their own address and not as elements of a stack.

How to undeclare (delete) variable in C?

Like we do with macros:
#undef SOMEMACRO
Can we also undeclare or delete the variables in C, so that we can save a lot of memory?
I know about malloc() and free(), but I want to delete the variables completely so that if I use printf("%d", a); I should get error
test.c:4:14: error: ‘a’ undeclared (first use in this function)
No, but you can create small minimum scopes to achieve this since all scope local variables are destroyed when the scope is exit. Something like this:
void foo() {
// some codes
// ...
{ // create an extra minimum scope where a is needed
int a;
}
// a doesn't exist here
}
It's not a direct answer to the question, but it might bring some order and understanding on why this question has no proper answer and why "deleting" variables is impossible in C.
Point #1 What are variables?
Variables are a way for a programmer to assign a name to a memory space. This is important, because this means that a variable doesn't have to occupy any actual space! As long as the compiler has a way to keep track of the memory in question, a defined variable could be translated in many ways to occupy no space at all.
Consider: const int i = 10; A compiler could easily choose to substitute all instances of i into an immediate value. i would occupy 0 data memory in this case (depending on architecture it could increase code size). Alternatively, the compiler could store the value in a register and again, no stack nor heap space will be used. There's no point in "undefining" a label that exists mostly in the code and not necessarily in runtime.
Point #2 Where are variables stored?
After point #1 you already understand that this is not an easy question to answer as the compiler could do anything it wants without breaking your logic, but generally speaking, variables are stored on the stack. How the stack works is quite important for your question.
When a function is being called the machine takes the current location of the CPU's instruction pointer and the current stack pointer and pushes them into the stack, replacing the stack pointer to the next location on stack. It then jumps into the code of the function being called.
That function knows how many variables it has and how much space they need, so it moves the frame pointer to capture a frame that could occupy all the function's variables and then just uses stack. To simplify things, the function captures enough space for all it's variables right from the start and each variable has a well defined offset from the beginning of the function's stack frame*. The variables are also stored one after the other.
While you could manipulate the frame pointer after this action, it'll be too costly and mostly pointless - The running code only uses the last stack frame and could occupy all remaining stack if needed (stack is allocated at thread start) so "releasing" variables gives little benefit. Releasing a variable from the middle of the stack frame would require a defrag operation which would be very CPU costly and pointless to recover few bytes of memory.
Point #3: Let the compiler do its job
The last issue here is the simple fact that a compiler could do a much better job at optimizing your program than you probably could. Given the need, the compiler could detect variable scopes and overlap memory which can't be accessed simultaneously to reduce the programs memory consumption (-O3 compile flag).
There's no need for you to "release" variables since the compiler could do that without your knowledge anyway.
This is to complement all said before me about the variables being too small to matter and the fact that there's no mechanism to achieve what you asked.
* Languages that support dynamic-sized arrays could alter the stack frame to allocate space for that array only after the size of the array was calculated.
There is no way to do that in C nor in the vast majority of programming languages, certainly in all programming languages that I know.
And you would not save "a lot of memory". The amount of memory you would save if you did such a thing would be minuscule. Tiny. Not worth talking about.
The mechanism that would facilitate the purging of variables in such a way would probably occupy more memory than the variables you would purge.
The invocation of the code that would reclaim the code of individual variables would also occupy more space than the variables themselves.
So if there was a magic method purge() that purges variables, not only the implementation of purge() would be larger than any amount of memory you would ever hope to reclaim by purging variables in your program, but also, in int a; purge(a); the call to purge() would occupy more space than a itself.
That's because the variables that you are talking about are very small. The printf("%d", a); example that you provided shows that you are thinking of somehow reclaiming the memory occupied by individual int variables. Even if there was a way to do that, you would be saving something of the order of 4 bytes. The total amount of memory occupied by such variables is extremely small, because it is a direct function of how many variables you, as a programmer, declare by hand-typing their declarations. It would take years of typing on a keyboard doing nothing but mindlessly declaring variables before you would declare a number of int variables occupying an amount of memory worth speaking of.
Well, you can use blocks ({ }) and defining a variable as late as possible to limit the scope where it exists.
But unless the variable's address is taken, doing so has no influence on the generated code at all, as the compiler's determination of the scope where it has to keep the variable's value is not significantly impacted.
If the variable's address is taken, failure of escape-analysis, mostly due to inlining-barriers like separate compilation or allowing semantic interpositioning, can make the compiler assume it has to keep it alive till later in the block than strictly neccessary. That's rarely significant (don't worry about a handful of ints, and most often a few lines of code longer keeping it alive are insignificant), but best to keep it in mind for the rare case where it might matter.
If you are that concerned about the tiny amount of memory that is on the stack, then you're probably going to be interested in understanding the specifics of your compiler as well. You'll need to find out what it does when it compiles. The actual shape of the stack-frame is not specified by the C language. It is left to the compiler to figure out. To take an example from the currently accepted answer:
void foo() {
// some codes
// ...
{ // create an extra minimum scope where a is needed
int a;
}
// a doesn't exist here
}
This may or may not affect the memory usage of the function. If you were to do this in a mainstream compiler like gcc or Visual Studio, you would find that they optimize for speed rather than stack size, so they pre-allocate all of the stack space they need at the start of the function. They will do analysis to figure out the minimum pre-allocation needed, using your scoping and variable-usage analysis, but those algorithms literally wont' be affected by extra scoping. They're already smarter than that.
Other compilers, especially those for embedded platforms, may allocate the stack frame differently. On these platforms, such scoping may be the trick you needed. How do you tell the difference? The only options are:
Read the documentation
Try it, and see what works
Also, make sure you understand the exact nature of your problem. I worked on a particular embedded project which eschewed the stack for everything except return values and a few ints. When I pressed the senior developers about this silliness, they explained that on this particular application, stack space was at more of a premium than space for globally allocated variables. They had a process they had to go through to prove that the system would operate as intended, and this process was much easier for them if they allocated everything up front and avoided recursion. I guarantee you would never arrive at such a convoluted solution unless you first knew the exact nature of what you were solving.
As another solution you could look at, you could always build your own stack frames. Make a union of structs, where each struct contains the variables for one stack frame. Then keep track of them yourself. You could also look at functions like alloca, which can allow for growing the stack frame during the function call, if your compiler supports it.
Would a union of structs work? Try it. The answer is compiler dependent. If all variables are stored in memory on your particular device, then this approach will likely minimize stack usage. However, it could also substantially confuse register coloring algorithms, and result in an increase in stack usage! Try and see how it goes for you!

C variable allocation time and space

If i have a test.c file with the following
#include ...
int global = 0;
int main() {
int local1 = 0;
while(1) {
int local2 = 0;
// Do some operation with one of them
}
return 0;
}
So if I had to use one of this variables in the while loop, which one would be preferred?
Maybe I'm being a little vague here, but I want to know if the difference in time/space allocation is actually relevant.
If you are wondering whether declaring a variable inside a for loop causes it to be created/destroyed at every iteration, there is nothing really to worry about. These variables are not dynamically allocated at runtime, nothing is being malloced here - just some memory is being set aside for use inside the loop. So having the variable inside is just the same as having it outside the loop in terms of performance.
The real difference here is scope not performance. Whether you use a global or local variable only affects where you want this variable to be visible.
In case you're wondering about performance differences: most likely there aren't any. If there are theoretical performance differences, you'll find it hard to actually devise a test to measure them.
A decision like this should not be based on performance but semantics. Unless the semantic behavior of a global variable is required, you should always use automatic (local non-static) variables.
As others have said and surely will say, there are unlikely to be any differences in performance. If there are, the automatic variable will be faster.
The C compiler will have an easier time making optimizations on the variables declared local to the function. The global variable would require an optimizer to perform "Inter-Procedural Data Flow Analysis", which isn't that commonly done.
As an example of the difference, consider that all your declarations initialize the variable to zero. However, in the case of the global variable, the compiler cannot use that information unless it verifies that no flow of control in your program can change the global prior to using it in your example function. In the case of the locally declared ("automatic") variables, there is no way the initial value can be changed by another function (in particular, the compiler verifies that their address is never passed to a sub-function) and the compiler can perform "killed definitions" and "value liveness" analysis to determine whether the zero value can be assumed in some code paths.
Of the two local variables, as a guideline, the optimizer will always have an easier time optimizing access to the variable with the smaller (more limited) scope.
Having stated the above, I would suggest that other answers concerning a bias toward semantics over optimizer-meta-optimization is correct. Use the variable which causes the code to read best, and you will be rewarded with more time returned to you than assisting the def-use optimization calculation.
In general, avoid using a global variable, or any variable which can be accessed more broadly than absolutely necessary. Limited scoping of variables helps prevent bugs from being introduced during later program maintenance.
There are three broad classes of variables: static (global), stack (auto), and register.
Register variables are stored in CPU registers. Registers are very fast word-sized memories, which are integrated in the CPU pipeline. They are free to access, but there are a very limited number of them (typically between 8 and 32 depending on your processor and what operations you're doing).
Stack variables are stored in an area of RAM called the stack. The stack is almost always going to be in the cache, so stack variables typically take 1-4 cycles to access.
Generally, local variables can be either in registers or on the stack. It doesn't matter whether they are allocated at the top of a function or in a loop; they will only be allocated once per function call, and allocation is basically free. The compiler will put variables in registers if at all possible, but if you have more active variables than registers, they won't all fit. Also, if you take the address of a variable, it must be stored on the stack since registers don't have addresses.
Global and static variables are a different beast. Since they are not usually accessed frequently, they may not be in cache, so it could take hundreds of cycles to access them. Also, since the compiler may not know the address of a global variable ahead of time, it may need to be looked up, which is also expensive.
As others have said, don't worry too much about this stuff. It's definitely good to know, but it shouldn't affect the way you write your programs. Write code that makes sense, and let the compiler worry about optimization. If you get into compiler development, then you can start worrying about it. :)
Edit: more details on allocation:
Register variables are allocated by the compiler, so there is no runtime cost. The code will just put a value in a register as soon as the value is produced.
Stack variables are allocated by your program at runtime. Typically, when a function is called, the first thing it will do is reserve enough stack space for all of its local variables. So there is no per-variable cost.

How to preserve stack space with good design?

I'm programming in C for RAM limited embedded microcontroller with RTOS.
I regularly break my code to short functions, but every function calling require to more stack memory.
Every task needs his stack, and this is one of the significant memory consumers in the project.
Is there an alternative to keep the code well organized and readable, still preserve the memory?
Try to make the call stack flatter, so instead of a() calling b() which calls c() which calls d(), have a() call b(), c(), and d() itself.
If a function is only referenced once, mark it inline (assuming your compiler supports this).
There are 3 components to your stack usage:
Function Call return addresses
Function Call parameters
automatic(local) variables
The key to minimizing your stack usage is to minimize parameter passing and automatic variables. The space consumption of the actual function call itself is rather minimal.
Parameters
One way to address the parameter issue is to pass a structure (via pointer) instead of a large number of parameters.
foo(int a, int b, int c, int d)
{
...
bar(int a, int b);
}
do this instead:
struct my_params {
int a;
int b;
int c;
int d;
};
foo(struct my_params* p)
{
...
bar(p);
};
This strategy is good if you pass down a lot of parameters. If the parameters are all different, then it might not work well for you. You would end up with a large structure being passed around that contains many different parameters.
Automatic Variables (locals)
This tend to be the biggest consumer of stack space.
Arrays are the killer. Don't define arrays in your local functions!
Minimize the number of local variables.
Use the smallest type necessary.
If re-entrancy is not an issue, you can use module static variables.
Keep in mind that if you're simply moving all your local variables from local scope to module scope, you have NOT saved any space. You traded stack space for data segment space.
Some RTOS support thread local storage, which allocates "global" storage on a per-thread basis. This might allow you to have multiple independent global variables on a per task basis, but this will make your code not as straightforward.
In the event you can spare a lot of main memory but have only a small shred of stack, I suggest evaluating static allocations.
In C, all variables declared inside a function are "automatically managed" which means they're allocated on the stack.
Qualifying the declarations as "static" stores them in main memory instead of on the stack. They basically behave like global variables but still allow you to avoid the bad habits that come with overusing globals. You can make a good case for declaring large, long-lived buffers/variables as static to reduce pressure on the stack.
Beware that this doesn't work well/at all if your application is multithreaded or if you use recursion.
Turn on optimization, specifically aggressive inlining. The compiler should be able to inline methods to minimize calls. Depending on the compiler and the optimization switches you use, marking some methods as inline may help (or it may be ignored).
With GCC, try adding the "-finline-functions" (or -O3) flag and possibly the " -finline-limit=n" flag.
One trick that I read somewhere inorder to evaluate the stack requirements of the code in an embedded setup is to fill the stack space at the onset with a known pattern(DEAD in hex being my favorite) and let the system run for a while.
After a normal run, read the stack space and see how much of the stack space has not been replaced during the course of operation. Design so as to leave atleast 150% of that so as to tackle all obsure code paths that might not have been exercised.
Can you replace some of your local variables by globals?
Arrays in particular can eat up stack.
If the situation allows you to share some globals between some those between functions,
there is a chance you can reduce your memory foot print.
The trade off cost is increased complexity, and greater risk of unwanted side effects between functions vs a possibly smaller memory foot print.
What sort of variables do you have in your functions?
What sizes and limits are we talking about?
Depending on your compiler, and how aggressive your optimisation options are, you will have stack usage for every function call you make. So to start with you will probably need to limit the depth of your function calls.
Some compilers do use jumps rather than branches for simple functions which will reduce stack usage. Obviously you can do the same thing by using, say, an assembler macro to jump to your functions rather than a direct function call.
As mentioned in other answers, inlining is one option available although that does come at the cost of greater code size.
The other area that eats stack is the local parameters. This area you do have some control over. Using (file level) statics will avoid stack allocation at the cost of your static ram allocation. Globals likewise.
In (truly) extreme cases you can come up with a convention for functions that uses a fixed number of global variables as temporary storage in lieu of locals on the stack. The tricky bit is making sure that none of the functions that use the same globals ever get called at the same time. (hence the convention)
If you need to start preserving stack space you should either get a better compiler or more memory.
Your software will typically grow (new features,...) , so if you have to start a project by thinking about how to preserve stack space it's doomed from the beginning.
Yes, an RTOS can really eat up RAM for task stack usage. My experience is that as a new user of an RTOS, there's a tendency to use more tasks than necessary.
For an embedded system using an RTOS, RAM can be a precious commodity. To preserve RAM, for simple features it can still be effective to implement several features within one task, running in round-robin fashion, with a cooperative multitasking design. Thus reduce total number of tasks.
I think you may be imagining a problem which doesnt exist here. Most compilers don't actually do anything when they "allocate" automaticic variables on the stack.
The stack is allocated before "main()" is executed. When you call function b() from function a() the address of the storage area immediately after the last variable used by a is passed to b(). This becomes the start of b()'s stack if b() then calls function c() then c's stack starts after the last automatic variable defined by b().
Note that the stack memory is already there and allocated, that no initialisation takes place and the only processing involved is passing a stack pointer.
The only time this becomes a problem would be where all three functions use large amounts of storage the stack then has to accomadate the memory of all three functions. Try to keep functions which allocate large amounts of storage at the bottom of the call stack i.e. dont call another function from them.
Another trick for memory constained systems is to split of the memory hogging parts of a function into separate self contained functions.

Resources