WEBVTT

1
00:01.040 --> 00:03.950
Hello and welcome back to a new section.

2
00:03.950 --> 00:06.680
In this session, we are going to study the stack.

3
00:07.310 --> 00:09.410
So what is the stack?

4
00:10.130 --> 00:11.240
Let me show you.

5
00:11.270 --> 00:16.670
If you open your template to see, the stack is located here.

6
00:17.270 --> 00:18.680
You can see the stack.

7
00:19.100 --> 00:23.300
Actually, the stack is just the memory, the RAM memory.

8
00:23.300 --> 00:29.450
So every process that is running will be allocated some location in memory for it to use.

9
00:29.510 --> 00:34.940
So for this particular program, template two -, this is a stack for the template two.

10
00:35.480 --> 00:37.370
So what do you use the stack for?

11
00:37.400 --> 00:43.910
The stack is used for pushing and popping values, so you can push data to the stack.

12
00:44.840 --> 00:47.990
And then you can pop the data back into the registers.

13
00:48.260 --> 00:50.150
So that is what it's used for.

14
00:50.180 --> 00:59.570
It is also used partly for setting up the parameters for function calls in x64.

15
00:59.600 --> 01:04.160
In 64-bit operations, we use a convention called fast call.

16
01:04.160 --> 01:11.780
Fast call is where some of the parameters are loaded into the registers, and some are loaded into the

17
01:11.780 --> 01:12.440
stack.

18
01:12.710 --> 01:14.390
So it's combined, both.

19
01:14.870 --> 01:17.150
So those are used.

20
01:17.150 --> 01:19.280
Why do we load them to registers?

21
01:19.280 --> 01:20.450
Because it's faster.

22
01:20.840 --> 01:22.790
The stack involves memory access,

23
01:22.790 --> 01:24.830
so it's slightly slower than the register.

24
01:25.430 --> 01:26.600
But we use both.

25
01:26.750 --> 01:33.140
We push parameters to the stack and also load some data into the registers.

26
01:33.140 --> 01:36.800
Then we call the function, which makes use of those parameters.

27
01:36.800 --> 01:39.140
But we will do that later on in the course.

28
01:39.140 --> 01:44.720
For now, we just want to understand how the stack works in a 64-bit environment.

29
01:45.380 --> 01:48.290
So, I've got the diagram for you here.

30
01:48.290 --> 01:54.380
Now, as you can see over here, assuming we have three values in the registers,

31
01:54.410 --> 01:55.100
-,

32
01:55.760 --> 01:57.170
-, and -.

33
01:57.350 --> 01:59.900
- has got all ones.

34
01:59.900 --> 02:02.030
This is 16 ones here.

35
02:02.360 --> 02:05.960
- has got 16 twos, and - 16 threes.

36
02:05.960 --> 02:07.100
So this is a quadword.

37
02:07.490 --> 02:10.280
Quadword is eight bytes, eight bytes, eight bytes.

38
02:10.280 --> 02:14.000
So the first operation we do is to push,

39
02:14.330 --> 02:16.790
and then the second operation we do is to pop.

40
02:17.450 --> 02:22.070
And for the stack, the memory address increases downwards.

41
02:22.070 --> 02:29.270
That means you can see here, the memory address is F0 and F8 and 0E00, and so on.

42
02:29.270 --> 02:32.870
So it's increasing by steps of quadword, or eight bytes.

43
02:33.260 --> 02:39.590
And we have a register called the - register, which stores the location of the top of the stack.

44
02:39.590 --> 02:45.530
So the stack will grow in this direction, from the higher memory to the lower memory.

45
02:46.160 --> 02:52.730
So let's say we push -. If you are going to push - to the stack, first we have to allocate space

46
02:52.730 --> 02:55.580
for the value that you want to push.

47
02:55.580 --> 02:58.640
So currently, our - points to this location.

48
02:59.450 --> 03:03.410
So as you can see here, - is a stack pointer.

49
03:03.410 --> 03:06.140
It points to 65428.

50
03:06.500 --> 03:08.300
Let me run to our breakpoint,

51
03:08.300 --> 03:09.980
and then we see that happening.

52
03:10.610 --> 03:13.910
We step over, step over.

53
03:13.910 --> 03:20.660
And you can see the - is pointing to the top of the stack, which is 65420.

54
03:21.260 --> 03:27.080
It might be different for you because every operating system will allocate the stack differently

55
03:27.080 --> 03:29.810
for each different machine.

56
03:29.810 --> 03:32.660
For me, it's 65420.

57
03:33.230 --> 03:39.650
So what we do is now, I reproduced that in this diagram.

58
03:39.770 --> 03:43.910
So the - is pointing to this location.

59
03:44.060 --> 03:49.010
It is the top of the stack right now, as you can see here, pointing here.

60
03:49.010 --> 03:53.360
And you can notice the memory address grows higher as we go down.

61
03:53.480 --> 03:56.900
So every time you push something, it will allocate space above it,

62
03:56.900 --> 04:01.700
and then you will move the data from the RAM to that location.

63
04:01.700 --> 04:03.020
If you are pushing -.

64
04:03.620 --> 04:07.160
So in this case, we are pushing -. It's the first instruction.

65
04:07.160 --> 04:13.340
So what we do is we will allocate space first for the new data that we're going to push by minusing

66
04:13.340 --> 04:13.850
eight.

67
04:14.030 --> 04:20.630
So we minus eight. Let's do the instruction now. - minus eight,

68
04:20.630 --> 04:24.050
it will reduce this memory address by eight,

69
04:24.050 --> 04:25.070
so it will go up.

70
04:25.550 --> 04:28.070
But before that, let us put our data in here.

71
04:28.430 --> 04:32.300
Right-click on that and type in all ones, 16 ones.

72
04:37.390 --> 04:40.090
So now we are going to push - to the stack.

73
04:44.150 --> 04:44.480
And then,

74
04:44.690 --> 04:46.130
now let's step over this.

75
04:47.810 --> 04:53.720
So now you notice ones are on the stack, and the address has moved up by eight bytes.

76
04:53.990 --> 04:57.080
Previously, the stack pointer was set to zero.

77
04:57.110 --> 04:59.840
Now the stack pointer is pointing to F18.

78
05:00.920 --> 05:02.330
So, F18.

79
05:02.330 --> 05:04.130
So previously it was here.

80
05:04.490 --> 05:10.460
So what it does is when we push -, it does this operation, - minus eight, first.

81
05:10.700 --> 05:15.770
That means it moves this - up by eight bytes to point to the new location.

82
05:15.800 --> 05:17.780
Then it makes a copy of this.

83
05:20.830 --> 05:22.240
And then it saves,

84
05:22.240 --> 05:23.830
saves a copy here.

85
05:27.380 --> 05:29.330
Now we are going to try another one.

86
05:29.360 --> 05:31.790
We are going to put something in -.

87
05:31.790 --> 05:34.370
So we put 2, 16 twos.

88
05:37.550 --> 05:41.510
And then we are going to push this out to the stack as well.

89
05:42.350 --> 05:43.610
So let's do that now.

90
05:43.850 --> 05:45.440
We're going to do a push here.

91
05:51.430 --> 05:51.850
Okay.

92
05:51.850 --> 05:59.080
So now we step over, and you see now - is on the stack with a new address.

93
05:59.080 --> 06:07.150
So what happened was we allocated space again, moved up this by eight bytes, and then it makes a copy of

94
06:07.150 --> 06:07.810
this.

95
06:09.580 --> 06:11.320
And copied that.

96
06:11.770 --> 06:13.090
That's what's happening.

97
06:13.090 --> 06:20.500
As you can see now, the - is pointing to F10, which is here, top of the stack.

98
06:20.710 --> 06:26.290
So the stack grows higher, up and up, to lower memory addresses.

99
06:26.290 --> 06:28.000
So now we're going to do the third one.

100
06:28.000 --> 06:29.470
We're going to push -.

101
06:29.680 --> 06:30.910
So we modify - first.

102
06:31.030 --> 06:33.220
We put 16 threes there.

103
06:39.100 --> 06:43.060
And then now we are going to do a push.

104
06:44.620 --> 06:46.270
-.

105
06:50.250 --> 06:50.610
Okay.

106
06:50.610 --> 06:51.750
So let's step over that now.

107
06:53.340 --> 06:55.200
And you see - is now on the stack.

108
06:55.560 --> 06:59.010
So, and the memory address is again reduced by eight.

109
06:59.220 --> 07:07.290
So what happened was - moved up by eight bytes to point to another new address, allocated some space,

110
07:07.290 --> 07:12.390
and then made a copy of this and pushed it there.

111
07:12.990 --> 07:15.240
So that is what is happening.

112
07:15.870 --> 07:16.290
All right.

113
07:16.290 --> 07:19.830
So now we have got these three values in the stack.

114
07:19.860 --> 07:20.820
We are going to pop.

115
07:20.880 --> 07:23.400
So a pop is just a reverse of a push.

116
07:23.640 --> 07:29.550
The syntax of a pop is that it looks like this: pop, followed by register.

117
07:30.390 --> 07:33.660
The syntax for push is push, followed by the value in the register.

118
07:33.690 --> 07:36.390
So normally you specify a register here as well.

119
07:36.480 --> 07:44.430
Then you push, and then here, pop means that you are popping the value at the top of the stack to the

120
07:44.430 --> 07:44.970
register.

121
07:44.970 --> 07:52.590
And then you clean the stack by adding eight, so that the stack pointer goes back

122
07:52.590 --> 07:53.730
down like this.

123
07:54.030 --> 07:55.530
So now we are going to pop.

124
07:56.760 --> 07:57.870
So let's do a pop.

125
07:58.560 --> 08:06.660
So let's assume now that this - register, we modify to some random number, or let's just zero.

126
08:07.050 --> 08:07.560
Let's zero,

127
08:07.560 --> 08:10.950
zero everything else is easier. Zero,

128
08:10.950 --> 08:11.460
everything else.

129
08:12.150 --> 08:12.450
All right.

130
08:12.450 --> 08:20.910
So now we are going to see what happens when we pop. We will use the syntax: pop, followed by the

131
08:20.910 --> 08:22.530
register you want to pop to.

132
08:22.560 --> 08:25.920
So whatever is going to pop now is the value on top.

133
08:25.920 --> 08:30.210
So we can pop this value into any register we want.

134
08:30.210 --> 08:36.480
You can put -, or we can put -, or -, or whatever.

135
08:36.480 --> 08:41.970
You see, originally this value 3333 was in -.

136
08:42.120 --> 08:43.980
So normally we would pop it back to -.

137
08:44.100 --> 08:46.980
So we put -, then okay.

138
08:47.370 --> 08:50.070
So now you watch - when we step over that.

139
08:51.760 --> 08:54.700
So the threes go back into -.

140
08:54.970 --> 08:55.510
Yes.

141
08:55.510 --> 09:00.640
So now, once you pop already, what happened was that it has cleaned the stack.

142
09:00.640 --> 09:03.520
That means the address has gone down.

143
09:03.520 --> 09:06.370
Previously, the address was up here.

144
09:06.520 --> 09:07.630
Stack pointer was here.

145
09:07.810 --> 09:10.120
So you plus eight, it goes down.

146
09:10.510 --> 09:14.470
Note that the old value is still there, but it is no longer the top of the stack.

147
09:14.500 --> 09:19.780
The top of the stack now is here, because the - is now pointing there, right?

148
09:19.780 --> 09:27.700
So what is happening was this operation: when you pop, it goes to the address in -, dereferences

149
09:27.700 --> 09:33.040
it to fetch the value, and then moves it to the register, makes a copy to the register, and then it adds

150
09:33.040 --> 09:34.120
eight to -.

151
09:34.300 --> 09:42.250
So that's why what happened was that it makes a copy of this and then puts it back in -.

152
09:42.790 --> 09:47.140
Then it moves this down by eight because you add it, you add eight,

153
09:47.140 --> 09:49.480
so it goes down, goes down like this.

154
09:49.480 --> 09:52.600
Remember, memory address goes in this direction.

155
09:52.600 --> 09:56.590
So next, next instruction is to pop whatever now is on top.

156
09:56.590 --> 09:58.090
The top now is here.

157
09:58.090 --> 10:02.860
So if we do a pop, it's going to pop this to wherever the destination you specify.

158
10:03.040 --> 10:05.800
So you can pop this to any register you want.

159
10:05.800 --> 10:10.960
You want to - register, or - register, or any register.

160
10:10.960 --> 10:17.260
But normally we will pop it back to its original register, which is -, so we pop to -.

161
10:20.260 --> 10:23.170
Okay, so you take a look at - as we run this step over.

162
10:23.170 --> 10:29.530
And now - has got two, two, two, two, and the top of the stack pointer now goes down again.

163
10:29.890 --> 10:33.310
See, if I scroll up, we see previously the stack pointer was here.

164
10:33.340 --> 10:39.580
Now it goes down to 65418, stack pointer 65418.

165
10:39.670 --> 10:48.610
So again, what happened was you make a copy of 2222, put it back in -, and then plus eight, and this

166
10:48.610 --> 10:49.270
goes down.

167
10:50.200 --> 10:53.890
So now the new stack top is here at this address.

168
10:54.640 --> 10:56.530
So now we're again going to do another pop.

169
10:57.070 --> 11:01.060
So this time we're going to pop 1111 to wherever you specify.

170
11:01.150 --> 11:02.380
So we do a pop.

171
11:02.380 --> 11:05.710
Let's put it back to -, and then okay.

172
11:06.160 --> 11:08.410
So let's step over and watch -.

173
11:09.130 --> 11:12.070
Now - becomes ones because we just popped it.

174
11:12.070 --> 11:16.330
And now the new stack pointer goes to the bottom, as you can see.

175
11:16.900 --> 11:17.260
Right.

176
11:17.260 --> 11:25.420
So what happens is, again, it makes a copy of 1111, copies into -, and then plus eight, and it moves down.

177
11:26.140 --> 11:30.250
So this is the, we just reversed what we did during the push.

178
11:30.400 --> 11:33.850
And now the - is back to its original position.

179
11:33.850 --> 11:35.890
So this is how we use stacks.

180
11:35.890 --> 11:41.500
Whenever you push something to the stack, make sure you pop it back out so that it reverts back to

181
11:41.500 --> 11:42.400
its original position.

182
11:42.400 --> 11:44.680
Otherwise, you might have problems later on.

183
11:44.680 --> 11:51.280
When you come back to your main program and run, the stack is not reversed to its original state,

184
11:51.490 --> 11:57.280
we would say the stack is unbalanced. So we have to rebalance it by popping whatever you have pushed

185
11:57.280 --> 11:57.730
earlier.

186
11:58.360 --> 12:04.780
So based on this understanding, we can use the stack to store memory addresses.

187
12:04.780 --> 12:08.350
We can store values temporarily while we perform other things.

188
12:08.350 --> 12:10.000
Then we want back the old value,

189
12:10.000 --> 12:11.980
we can just pop it back to the register.

190
12:11.980 --> 12:14.080
So that is the usefulness of a stack.

191
12:14.170 --> 12:22.240
Stack also can be used to swap values around. Assuming if we had reversed the order of

192
12:22.240 --> 12:26.530
the pop, then the values inside would have been swapped with each other.

193
12:26.920 --> 12:29.860
So this is another use of a stack.

194
12:30.160 --> 12:32.710
So that's all for this video.

195
12:32.710 --> 12:33.970
Thank you for watching.