Assembly

Course
Time
13 hours 15 minutes
Difficulty
Beginner
CEU/CPE
14

Video Transcription

00:00
Hello. This is Dr Miller, and this is Episode 9.2 of Assembly.
00:05
Today we're gonna talk about pipelines, the order of execution and conditional execution
00:12
pipelines.
00:13
So, pipelines, or what allows a multiple instructions to be in different stages of processing all at the same time.
00:21
And this is important because things like fetching and storing are going to be much slower.
00:26
So Ram is several orders of magnitude slower than the processor in the hard drive and network, or even slower than that.
00:33
So here's some example times. So, for example, a register takes 0.4 nanoseconds to access.
00:39
Where is Ram takes over 100 nanoseconds.
00:42
So we're gonna have well over 100 clock cycles before Ram is going to be able to access something.
00:48
And then even if you pick some of the fastest SSD Zen V M E s STS those air
00:54
25,000 nanoseconds, and so again, orders of magnitude difference in all of these,
01:00
and so pipelines help us to optimize our processes.
01:06
And you can see that this is something that we've had processors have done for quite some time.
01:11
So, for example, with penny and fours and penny MD's. The number of pipeline stages they have are between
01:17
20 and 30. And so it's something that processes have been doing for quite some time.
01:23
So here's what happens when we have sort of normal execution and we don't have a pipeline, so
01:29
we can kind of see here in the diagram, we fetch an instruction, then the next cycle we decode it than we executed. And then we write the data.
01:36
Then we fetch our next instruction decode execute,
01:38
and then right back either data or flags.
01:44
And so when we have something like
01:46
pipeline ing, we can see here that while we're fetching one instruction, we do that and then we will decode that instruction at the same time will fetch the next instruction.
01:56
Then, while we are patching this instruction, we're decoding this. Instruction were executing this one.
02:01
And so, as we can see, if we look at this eight nanoseconds versus eight nanoseconds,
02:07
we can see that here. We got to instructions done. And here we ended up getting four or five, depending on if you're at 88 nanoseconds or 19 seconds
02:17
and so we can see that
02:20
there is a benefit to that where we're getting mawr instructions executed in the same amount of time if we add pipelines.
02:29
And so the thing with branching or jumping is the case we have may have
02:35
the This will cause the processor to flush its pipeline. So as it's going, if this X this instruction does a branch,
02:44
then the next instruction or all these instructions in the pipeline are going to have to be gotten rid of because they're not correct.
02:52
So what we have is we have what modern processes do, and they speculate about which branch is gonna be taken
02:58
and then they'll actually, um,
03:00
change the order of execution. Additionally,
03:02
so is there a couple things that are processes do
03:06
so for a speculative execution? Basically, we have two different types.
03:09
We have the eager where we basically try and do both branches, and then whichever one is wrong, then we undo all of those changes or don't commit those.
03:17
And then we also have predictive. So predictive
03:21
is basically the processor has a
03:23
processor within it that is trying to predict which branches taking the most often.
03:29
And then it will go ahead and do that prediction
03:32
and guess and then if it's wrong and has to backtrack. But if it's right, then it just goes through the pipeline
03:39
and it speeds up our execution
03:44
out of order. Execution.
03:46
So one of the things that process is also do is if we think about just in order processor reinfection instruction. If it's available, or if it's in,
03:53
um, on the CPU, then we continue. Otherwise, we basically have to wait
03:59
until we can retrieve that data from RAM. And so this fetch can take a long time.
04:05
And then we go ahead and execute and store the results.
04:10
But what happens is with modern processors. What they do is they determine which instructions depend on which other ones. And so if they keep track of things like what instructions that's already fetched, what stores it's done, the results of each instruction and then dependencies as to which instruction is dependent on another one.
04:29
Then basically we can do out of order execution.
04:31
And so, with out of order execution, we go ahead infection instruction. We added to the Q of things that can be executed,
04:40
Um, and then you check the dependencies. And so if one register depends on another one. Then that instruction is gonna have to wait. But if to
04:48
instructions are independent of each other than, basically you can do either one and eat or either order.
04:55
And so if you are waiting on dependencies when those have finally met, or when all the instructions that precede this instruction
05:01
that it requires have met, then we go ahead and continue,
05:05
and then we can,
05:06
um, executing, store the instructions.
05:11
So conditional instructions.
05:14
So it's conditional instructions that basically have the ability to execute an instruction based on flags. So let either do the instruction or not, depending on which flags are set
05:24
so often we do something like compare, and then we might move some data depending on the result of that comparison. And we've done this using jumps so compares and jumps.
05:34
But basically we are able to reduce branching and increase efficiency. If we can go ahead and do this without having to,
05:43
um, do jumps, which again are going to be inefficient as faras are processor.
05:50
So a conditional move.
05:53
So this is going to check the state of the E flags or the set of flags that we have on the processor
05:58
and it's only going to do the move. So the sea part stands for conditional and then move. And then we have the condition
06:04
and so on. Lee, move it. The flag is set and again we have the typical. We have our pneumonic. We have the destination, we have the source
06:13
and then the CC part is the condition.
06:15
So here a couple examples. There's a whole list here,
06:19
but we have conditional move above, So move if above. So
06:24
if we did a compare and then
06:26
the part on the left is greater than the part on the right,
06:30
then we'll go ahead and actually do the move from the source to the destination. Otherwise, we won't actually do that,
06:35
or you can do something like move greater than or equal to or move less than again. Any of these will only get executed if the correct flag is set for that condition, just like we did with jumps.
06:48
So here's some examples.
06:50
So we're comparing a X and EBX and then we can say conditional, move above
06:56
e d x e X, and so we can see that if this one is greater than this one, then we're going to copy its value into GDX.
07:03
And then you can see in this example we're doing vice versus we have above and then blower equal.
07:09
So then, if this one is below or equal, then we copy EBX into E. D. X, and that's only if that is condition is true.
07:16
So with these set of three instructions, this compare and then these two moves one of these moves will get executed in the other own will not.
07:26
And then here's another compare, and then maybe a below or equal. So there's some examples of conditional moves.
07:32
So today we talked about pipelines, the order of execution and then conditional execution.
07:40
Looking forward, we're gonna take our max of three numbers, and we're going to go ahead and use conditional execution for that.
07:46
So here's a quiz. Why're but jumps bad for processors
07:53
because they cause a pipeline to be flushed, which will take more time.
07:58
How do you copy data based on flags?
08:03
Use conditional instructions. For example, the sea move,
08:07
Um, and then some condition.
08:09
If you have questions, you can contact me at Miller MJ at you and Kate I e to you, and you can find me on Twitter at Milhouse 30

Up Next

Assembly

This course will provide background and information related to programming in assembly. Assembly is the lowest level programming language which is useful in reverse engineering and malware analysis.

Instructed By

Instructor Profile Image
Matthew Miller
Assistant Professor at the University of Nebraska at Kearney
Instructor