Hello and welcome back to a new section.
In this session, we are going to study the stack.
So what is the stack?
Let me show you.
If you open your template to see, the stack is located here.
You can see the stack.
Actually, the stack is just the memory, the RAM memory.
So every process that is running will be allocated some location in memory for it to use.
So for this particular program, template two -, this is a stack for the template two.
So what do you use the stack for?
The stack is used for pushing and popping values, so you can push data to the stack.
And then you can pop the data back into the registers.
So that is what it's used for.
It is also used partly for setting up the parameters for function calls in x64.
In 64-bit operations, we use a convention called fast call.
Fast call is where some of the parameters are loaded into the registers, and some are loaded into the
stack.
So it's combined, both.
So those are used.
Why do we load them to registers?
Because it's faster.
The stack involves memory access,
so it's slightly slower than the register.
But we use both.
We push parameters to the stack and also load some data into the registers.
Then we call the function, which makes use of those parameters.
But we will do that later on in the course.
For now, we just want to understand how the stack works in a 64-bit environment.
So, I've got the diagram for you here.
Now, as you can see over here, assuming we have three values in the registers,
-,
-, and -.
- has got all ones.
This is 16 ones here.
- has got 16 twos, and - 16 threes.
So this is a quadword.
Quadword is eight bytes, eight bytes, eight bytes.
So the first operation we do is to push,
and then the second operation we do is to pop.
And for the stack, the memory address increases downwards.
That means you can see here, the memory address is F0 and F8 and 0E00, and so on.
So it's increasing by steps of quadword, or eight bytes.
And we have a register called the - register, which stores the location of the top of the stack.
So the stack will grow in this direction, from the higher memory to the lower memory.
So let's say we push -. If you are going to push - to the stack, first we have to allocate space
for the value that you want to push.
So currently, our - points to this location.
So as you can see here, - is a stack pointer.
It points to 65428.
Let me run to our breakpoint,
and then we see that happening.
We step over, step over.
And you can see the - is pointing to the top of the stack, which is 65420.
It might be different for you because every operating system will allocate the stack differently
for each different machine.
For me, it's 65420.
So what we do is now, I reproduced that in this diagram.
So the - is pointing to this location.
It is the top of the stack right now, as you can see here, pointing here.
And you can notice the memory address grows higher as we go down.
So every time you push something, it will allocate space above it,
and then you will move the data from the RAM to that location.
If you are pushing -.
So in this case, we are pushing -. It's the first instruction.
So what we do is we will allocate space first for the new data that we're going to push by minusing
eight.
So we minus eight. Let's do the instruction now. - minus eight,
it will reduce this memory address by eight,
so it will go up.
But before that, let us put our data in here.
Right-click on that and type in all ones, 16 ones.
So now we are going to push - to the stack.
And then,
now let's step over this.
So now you notice ones are on the stack, and the address has moved up by eight bytes.
Previously, the stack pointer was set to zero.
Now the stack pointer is pointing to F18.
So, F18.
So previously it was here.
So what it does is when we push -, it does this operation, - minus eight, first.
That means it moves this - up by eight bytes to point to the new location.
Then it makes a copy of this.
And then it saves,
saves a copy here.
Now we are going to try another one.
We are going to put something in -.
So we put 2, 16 twos.
And then we are going to push this out to the stack as well.
So let's do that now.
We're going to do a push here.
Okay.
So now we step over, and you see now - is on the stack with a new address.
So what happened was we allocated space again, moved up this by eight bytes, and then it makes a copy of
this.
And copied that.
That's what's happening.
As you can see now, the - is pointing to F10, which is here, top of the stack.
So the stack grows higher, up and up, to lower memory addresses.
So now we're going to do the third one.
We're going to push -.
So we modify - first.
We put 16 threes there.
And then now we are going to do a push.
-.
Okay.
So let's step over that now.
And you see - is now on the stack.
So, and the memory address is again reduced by eight.
So what happened was - moved up by eight bytes to point to another new address, allocated some space,
and then made a copy of this and pushed it there.
So that is what is happening.
All right.
So now we have got these three values in the stack.
We are going to pop.
So a pop is just a reverse of a push.
The syntax of a pop is that it looks like this: pop, followed by register.
The syntax for push is push, followed by the value in the register.
So normally you specify a register here as well.
Then you push, and then here, pop means that you are popping the value at the top of the stack to the
register.
And then you clean the stack by adding eight, so that the stack pointer goes back
down like this.
So now we are going to pop.
So let's do a pop.
So let's assume now that this - register, we modify to some random number, or let's just zero.
Let's zero,
zero everything else is easier. Zero,
everything else.
All right.
So now we are going to see what happens when we pop. We will use the syntax: pop, followed by the
register you want to pop to.
So whatever is going to pop now is the value on top.
So we can pop this value into any register we want.
You can put -, or we can put -, or -, or whatever.
You see, originally this value 3333 was in -.
So normally we would pop it back to -.
So we put -, then okay.
So now you watch - when we step over that.
So the threes go back into -.
Yes.
So now, once you pop already, what happened was that it has cleaned the stack.
That means the address has gone down.
Previously, the address was up here.
Stack pointer was here.
So you plus eight, it goes down.
Note that the old value is still there, but it is no longer the top of the stack.
The top of the stack now is here, because the - is now pointing there, right?
So what is happening was this operation: when you pop, it goes to the address in -, dereferences
it to fetch the value, and then moves it to the register, makes a copy to the register, and then it adds
eight to -.
So that's why what happened was that it makes a copy of this and then puts it back in -.
Then it moves this down by eight because you add it, you add eight,
so it goes down, goes down like this.
Remember, memory address goes in this direction.
So next, next instruction is to pop whatever now is on top.
The top now is here.
So if we do a pop, it's going to pop this to wherever the destination you specify.
So you can pop this to any register you want.
You want to - register, or - register, or any register.
But normally we will pop it back to its original register, which is -, so we pop to -.
Okay, so you take a look at - as we run this step over.
And now - has got two, two, two, two, and the top of the stack pointer now goes down again.
See, if I scroll up, we see previously the stack pointer was here.
Now it goes down to 65418, stack pointer 65418.
So again, what happened was you make a copy of 2222, put it back in -, and then plus eight, and this
goes down.
So now the new stack top is here at this address.
So now we're again going to do another pop.
So this time we're going to pop 1111 to wherever you specify.
So we do a pop.
Let's put it back to -, and then okay.
So let's step over and watch -.
Now - becomes ones because we just popped it.
And now the new stack pointer goes to the bottom, as you can see.
Right.
So what happens is, again, it makes a copy of 1111, copies into -, and then plus eight, and it moves down.
So this is the, we just reversed what we did during the push.
And now the - is back to its original position.
So this is how we use stacks.
Whenever you push something to the stack, make sure you pop it back out so that it reverts back to
its original position.
Otherwise, you might have problems later on.
When you come back to your main program and run, the stack is not reversed to its original state,
we would say the stack is unbalanced. So we have to rebalance it by popping whatever you have pushed
earlier.
So based on this understanding, we can use the stack to store memory addresses.
We can store values temporarily while we perform other things.
Then we want back the old value,
we can just pop it back to the register.
So that is the usefulness of a stack.
Stack also can be used to swap values around. Assuming if we had reversed the order of
the pop, then the values inside would have been swapped with each other.
So this is another use of a stack.
So that's all for this video.
Thank you for watching.