1
00:00:00,190 --> 00:00:06,671
[MUSIC]. 

2
00:00:06,671 --> 00:00:10,992
We've now seen how a call chain gets 
translated into stack frames. 

3
00:00:10,992 --> 00:00:16,910
how each call puts a new stack frame on 
the stack, each return takes one off. 

4
00:00:16,910 --> 00:00:20,144
so now let's go into a little bit more 
details on what's inside of those stack 

5
00:00:20,144 --> 00:00:24,246
frames. 
So we going to look at the Linux stack 

6
00:00:24,246 --> 00:00:29,056
frame, what's used in the IA32 
conventions. 

7
00:00:29,056 --> 00:00:35,506
again the stack frame in, in this diagram 
am showing the caller's stack frame which 

8
00:00:35,506 --> 00:00:42,542
includes bunch of arguments that its set 
up for the callee. 

9
00:00:42,542 --> 00:00:48,830
And some other space that it might of 
used for it's own temporary variables. 

10
00:00:48,830 --> 00:00:53,998
And then when it makes the call, it also 
stores the return address that it wants 

11
00:00:53,998 --> 00:01:00,875
the system to return to when the callee 
procedure is finished, okay. 

12
00:01:00,875 --> 00:01:06,335
So, what the caller has done is built up 
a bit of, a bit of an area here where 

13
00:01:06,335 --> 00:01:13,770
it's put in the arguments to the callee 
function. 

14
00:01:13,770 --> 00:01:18,810
And then a little bit more space for that 
return address. 

15
00:01:18,810 --> 00:01:25,551
Okay, what happens next in the callee's 
frame is that we have the old base 

16
00:01:25,551 --> 00:01:36,300
pointer of the callers stack saved of the 
caller's stack frame saved. 

17
00:01:36,300 --> 00:01:39,462
we're also going to save some other 
registers that we might want to be able 

18
00:01:39,462 --> 00:01:43,300
to reuse, so we'll have to restore these 
before we return. 

19
00:01:43,300 --> 00:01:46,745
And then of course, some local variables 
as well, that we might want to use in the 

20
00:01:46,745 --> 00:01:51,030
callee procedure. 
And we'll get ready building up arguments 

21
00:01:51,030 --> 00:01:54,905
for any other functions that we want to 
call from this procedure. 

22
00:01:54,905 --> 00:02:00,332
Okay, and of course as we do this, the 
stack pointer will continue to move as we 

23
00:02:00,332 --> 00:02:05,395
add more and more things to the stack 
frame. 

24
00:02:05,395 --> 00:02:11,133
Okay, so has the basic idea. 
Lets see this in the context of an 

25
00:02:11,133 --> 00:02:14,932
example. 
Here we're going to go back to that swap 

26
00:02:14,932 --> 00:02:21,530
function swap procedure that we had do it 
a little bit differently this time. 

27
00:02:21,530 --> 00:02:27,638
here we have a function called call_swap 
which doesn't do very much. 

28
00:02:27,638 --> 00:02:32,958
All it does is it calls another procedure 
called swap with two arguments, two 

29
00:02:32,958 --> 00:02:40,055
addresses you'll notice, right? 
Two addresses there for the two variables 

30
00:02:40,055 --> 00:02:45,404
whose values we want to swap. 
So, the address of zip1, the address of 

31
00:02:45,404 --> 00:02:49,532
zip2. 
Alright, here's the definition of the 

32
00:02:49,532 --> 00:02:53,466
swap procedure. 
You notice that it has its two argument 

33
00:02:53,466 --> 00:02:57,624
it's describe that the type they built 
pointers and they both points to the type 

34
00:02:57,624 --> 00:03:01,651
int. 
So, these match up because of course our 

35
00:03:01,651 --> 00:03:07,050
two zip in two zip variables were ints to 
begin with. 

36
00:03:07,050 --> 00:03:12,060
Right well we do then is to have two 
temporary variables t0 and t1. 

37
00:03:12,060 --> 00:03:16,785
we load them up with the values stored at 
those pointers, remember we're 

38
00:03:16,785 --> 00:03:22,264
dereferencing the pointer. 
Going to get the value at that address, 

39
00:03:22,264 --> 00:03:26,880
that's going to be the value 15213 and 
98195. 

40
00:03:26,880 --> 00:03:32,000
then we take those temporary values and 
put them in the opposite location. 

41
00:03:32,000 --> 00:03:37,712
Again, dereferencing the pointers. 
Okay, that's our function call_swap and 

42
00:03:37,712 --> 00:03:43,700
swap, our two procedures. 
Alright call_swap is pretty easy to see 

43
00:03:43,700 --> 00:03:47,978
in assembly code. 
What it's going to be doing at at least 

44
00:03:47,978 --> 00:03:53,910
the parts we care about are going to be 
doing something pretty straight forward. 

45
00:03:53,910 --> 00:03:57,394
They're going to be putting two arguments 
onto the stack using push instructions, 

46
00:03:57,394 --> 00:04:01,360
okay? 
These will push the two addresses of the 

47
00:04:01,360 --> 00:04:08,270
two variables onto the stack, and then 
it's going to execute the call_swap. 

48
00:04:08,270 --> 00:04:14,534
to get the callee procedure started. 
Well before we get, well before we get to 

49
00:04:14,534 --> 00:04:17,898
that, let's take a look at the stack 
then, at the end of this we'll of had 

50
00:04:17,898 --> 00:04:23,204
some previous stack of course. 
And then we've added two values during, 

51
00:04:23,204 --> 00:04:28,290
during the push instructions that those 
two addresses for our two arguments. 

52
00:04:28,290 --> 00:04:34,282
And then of course, we've added the 
return address at, of being the call. 

53
00:04:34,282 --> 00:04:39,586
which is where we want to return when we 
execute the return statement in the 

54
00:04:39,586 --> 00:04:47,043
callee procedure in this case swap. 
Okay, so that's now the contents of the 

55
00:04:47,043 --> 00:04:50,497
stack. 
Alright, so now let's go look at what 

56
00:04:50,497 --> 00:04:55,850
swap looks like in assembly code. 
And here we have that setup code you've 

57
00:04:55,850 --> 00:05:00,025
seen before in other examples. 
some finishing up code that we've seen in 

58
00:05:00,025 --> 00:05:04,239
other examples, and we've ignored this 
for the most part until now. 

59
00:05:04,239 --> 00:05:08,145
Now, we'll talk about it in some detail 
and here's of course, the body of swap 

60
00:05:08,145 --> 00:05:12,605
that does the actual flipping of those 
two values. 

61
00:05:12,605 --> 00:05:16,505
Alright, so what we're going to do is 
look at this in a lot of detail in the 

62
00:05:16,505 --> 00:05:22,150
next few slides. 
let's start with that stack that as it 

63
00:05:22,150 --> 00:05:27,610
was when we started executing the swap 
procedure. 

64
00:05:27,610 --> 00:05:32,260
So here's the first few instructions of 
swap that setup code, right? 

65
00:05:32,260 --> 00:05:36,832
What happens after these instructions 
execute the first three instructions? 

66
00:05:36,832 --> 00:05:43,088
Alright, so the stack starts off with 
having a new value to it you'll notice 

67
00:05:43,088 --> 00:05:49,770
here we have a push of the register ebp 
onto the stack. 

68
00:05:49,770 --> 00:05:54,996
So what did ebp point to? 
Well, it was pointing to the base of the 

69
00:05:54,996 --> 00:06:01,125
previous stack frame. 
The one for call swap and we've just 

70
00:06:01,125 --> 00:06:08,568
saved that pointer onto the stack, okay? 
And of course, the push instruction also 

71
00:06:08,568 --> 00:06:14,076
change the value of esp to now point to 
this new point of the stack. 

72
00:06:14,076 --> 00:06:19,746
Okay, the next instruction is a move 
instruction that takes the value of the 

73
00:06:19,746 --> 00:06:25,514
esp and moves it to ebp. 
This is setting up the new base pointer 

74
00:06:25,514 --> 00:06:29,505
for the new stack frame for the swap 
procedure. 

75
00:06:29,505 --> 00:06:34,389
Okay, so right now both of those pointers 
are pointing to the same location, the 

76
00:06:34,389 --> 00:06:40,460
top of the stack. 
The very next instruction pushes the 

77
00:06:40,460 --> 00:06:44,005
value of ebx. 
This is maybe a register that we're 

78
00:06:44,005 --> 00:06:47,942
going to use inside a swap. 
So, we're going to push that value onto 

79
00:06:47,942 --> 00:06:51,575
the stack so we can restore ebx before we 
return. 

80
00:06:51,575 --> 00:06:55,800
Okay, so we've just pushed that onto the 
stack. 

81
00:06:55,800 --> 00:07:00,915
The stack has grown some more, you notice 
that esp has been adjusted yet again. 

82
00:07:00,915 --> 00:07:04,260
So now, esp and ebp are not the same any 
longer. 

83
00:07:04,260 --> 00:07:09,078
We're starting to grow that frame down, 
in this case by saving away a register we 

84
00:07:09,078 --> 00:07:14,465
need to restore later. 
Alright, next step is to start looking at 

85
00:07:14,465 --> 00:07:19,940
the the instructions that look at the 
arguments the function. 

86
00:07:19,940 --> 00:07:24,425
those were these two, the next two 
instructions of swap and what is going on 

87
00:07:24,425 --> 00:07:28,700
here? 
You'll notice that we're taking the 

88
00:07:28,700 --> 00:07:35,232
current value of our frame pointer the 
base pointer to our frame, and adding 12 

89
00:07:35,232 --> 00:07:39,606
to it. 
Okay, so we're taking that address, 

90
00:07:39,606 --> 00:07:44,560
remember the parentheses, in this case, 
means use the address stored there. 

91
00:07:44,560 --> 00:07:51,330
Add 12, go get that value and put it into 
ecx, okay? 

92
00:07:51,330 --> 00:07:54,740
So, what does that mean? 
Well if we go to ebp, it's pointing to 

93
00:07:54,740 --> 00:07:59,978
this location here. 
When we add 12 to it, we're now pointing 

94
00:07:59,978 --> 00:08:05,730
to this location, which is where we've 
stored one of our arguments, right? 

95
00:08:05,730 --> 00:08:10,560
Because we're starting our frame right 
immediately after the previous frame. 

96
00:08:10,560 --> 00:08:14,342
We know that if we just do a little bit 
of an offset, we can get to the value of 

97
00:08:14,342 --> 00:08:18,582
those arguments, that's that calling 
convention. 

98
00:08:18,582 --> 00:08:23,136
The fact, that we put those arguments in 
the, in a certain order right there in at 

99
00:08:23,136 --> 00:08:30,150
the top end of that previous stack frame. 
Okay, so this lets us get to yp that's 

100
00:08:30,150 --> 00:08:37,250
first pointed argument and then this as 
statement adds eight to that same pointer 

101
00:08:37,250 --> 00:08:45,564
to go get the other argument xp. 
Alright, so this is why we see these 

102
00:08:45,564 --> 00:08:52,670
frequently at the top of procedure the 
instructions get to get the arguments. 

103
00:08:52,670 --> 00:08:56,087
We've now have the arguments stored in 
ecx and edx. 

104
00:08:57,280 --> 00:09:00,976
Once we have the arguments, of course, 
we'll perform the operations of the swap 

105
00:09:00,976 --> 00:09:04,370
function, but we've seen those before 
already. 

106
00:09:04,370 --> 00:09:10,050
So, let's skip ahead and talk about the 
finish portion of swap. 

107
00:09:10,050 --> 00:09:14,400
Those instructions at the end that clean 
things up. 

108
00:09:14,400 --> 00:09:20,340
Here we see a a move instruction that 
takes the base pointer, subtracts 4, so 

109
00:09:20,340 --> 00:09:26,100
we're actually going to look at this 
location 4 down from the current value of 

110
00:09:26,100 --> 00:09:34,420
our base pointer, and go take that value 
and put it in ebx. 

111
00:09:34,420 --> 00:09:39,938
In fact, that was the old value of ebx 
and so we're going to restore the value 

112
00:09:39,938 --> 00:09:48,110
of ebx to what it was previously, okay? 
So, we saved and restored the registered 

113
00:09:48,110 --> 00:09:55,320
ebx and put that back exactly where it 
was when we came into the function. 

114
00:09:55,320 --> 00:10:01,567
The next instruction again, copies the 
value of the base pointer into esp. 

115
00:10:01,567 --> 00:10:07,167
and you notice that's the adjusting the 
stack so that we don't think about the 

116
00:10:07,167 --> 00:10:13,260
value, the old value of ebx being at the 
top of the stack. 

117
00:10:13,260 --> 00:10:18,636
Now, you might ask why didn't we use a 
pop instruction here, and move the value 

118
00:10:18,636 --> 00:10:24,096
at the top of the stack into ebx and 
automatically add 4 to the stack pointer 

119
00:10:24,096 --> 00:10:30,292
to get that adjustment. 
Well we could of done that, it would have 

120
00:10:30,292 --> 00:10:33,812
been the equivalent thing. 
this is a, a bit of an optimization, 

121
00:10:33,812 --> 00:10:37,483
because if we had to do that for several 
registers. 

122
00:10:37,483 --> 00:10:41,082
we could use some faster move 
instructions to do a bunch of things at 

123
00:10:41,082 --> 00:10:45,280
the same time, rather than the pop 
instructions. 

124
00:10:45,280 --> 00:10:51,090
but essentially, that those two lines are 
equivalent to a pop in structure. 

125
00:10:51,090 --> 00:10:55,314
And you'll notice that the very next 
instruction is another pop this time to 

126
00:10:55,314 --> 00:11:00,670
take the old value of ebp and put it into 
the base pointer register. 

127
00:11:00,670 --> 00:11:07,456
So, now we've back to the state where we 
first were when we entered the procedure. 

128
00:11:07,456 --> 00:11:13,100
swap with the frame pointers, the base 
pointer pointing to the top of the frame 

129
00:11:13,100 --> 00:11:19,917
for, called swap and esp to the bottom. 
At this point, we can execute the return 

130
00:11:19,917 --> 00:11:24,142
instruction and use the return address 
that was at the top of the swap, pop that 

131
00:11:24,142 --> 00:11:28,918
off. 
And jump to that address which is that 

132
00:11:28,918 --> 00:11:33,598
one immediately after the call 
instruction inside of the call_swap 

133
00:11:33,598 --> 00:11:38,372
function, okay? 
and of course we, with the arguments left 

134
00:11:38,372 --> 00:11:43,395
on the stack, now it's up to call swap to 
remove those arguments if it needs to. 

135
00:11:43,395 --> 00:11:48,155
or it could choose to just leave them 
there and return itself having its stack 

136
00:11:48,155 --> 00:11:54,565
pointer adjusted to the previous frame 
for the function that called it. 

137
00:11:54,565 --> 00:11:59,227
Alright, so let's go back to look at all 
of the code for the swap instruction, 

138
00:11:59,227 --> 00:12:04,259
here are all the insructions of for the 
procedure, and the code that called the 

139
00:12:04,259 --> 00:12:09,805
swap. 
From call swap maybe consists of these 

140
00:12:09,805 --> 00:12:15,640
few lines as well as maybe other things 
that were in that other procedure. 

141
00:12:15,640 --> 00:12:19,355
I'm not showing all of those here, you 
notice here's the call instruction. 

142
00:12:19,355 --> 00:12:23,765
It had to provide the address swap of 
course, the address actually stored in 

143
00:12:23,765 --> 00:12:28,680
memory is a relative address, as we've 
seen before. 

144
00:12:28,680 --> 00:12:32,712
So, you'll notice that this is a negative 
value, and because it has leading ff 

145
00:12:32,712 --> 00:12:37,814
there so it's a negative value. 
So, we're actually going to subtract a 

146
00:12:37,814 --> 00:12:42,370
little from our current address of 409 
probably enough to get us to 3a4 which is 

147
00:12:42,370 --> 00:12:49,215
the start of the swap procedure. 
Okay, and we can get listings like this 

148
00:12:49,215 --> 00:12:55,394
of course using gdp. 
Okay the return value that was stored on 

149
00:12:55,394 --> 00:13:01,455
the stack was this address ending in 
840e. 

150
00:13:01,455 --> 00:13:08,245
You notice a different instruction here 
called leave, leave is just a shorthand 

151
00:13:08,245 --> 00:13:17,030
for in fact the equivalent to 
instructions move edb to esp and pop ebp. 

152
00:13:17,030 --> 00:13:21,386
Because those are so common, we always 
use these in combination as the very last 

153
00:13:21,386 --> 00:13:26,620
two instructions as we finish up a 
procedure and clean up. 

154
00:13:26,620 --> 00:13:31,604
They've actually been given a special 
code in the x86 archetecture. 

155
00:13:31,604 --> 00:13:38,581
using the word the keyword leave and a 
code of c9 for its output. 

156
00:13:38,581 --> 00:13:43,107
The last observation to make is that 
although we saved and restored the 

157
00:13:43,107 --> 00:13:49,190
register ebx, we didn't bother to do that 
for eax, ecx, or edx. 

158
00:13:49,190 --> 00:13:53,120
we just didn't bother saving those at 
all. 

159
00:13:53,120 --> 00:13:58,665
and why not, we used those registers as 
well in the code turns out. 

160
00:13:58,665 --> 00:14:03,288
well the reason we didn't save them is 
because our convention is that the caller 

161
00:14:03,288 --> 00:14:08,227
needs to save those registers. 
We're going to talk more about this in 

162
00:14:08,227 --> 00:14:09,740
the next section. 

