[MUSIC]. Hi there. Now that we know how to set condition codes, let's see how we use branch instructions that depend on these condition codes to modify the control flow of your program. Okay? So, x86 supports several branch instructions of type J for jump X. And X can be a bunch of things here. And the first one is an unconditional branch, means that it jumps no matter what. There's no condition. So the condition for the branch is always true, is one. So that's the JXP instruction. But let's pick another one here for example, if we have JE here. JE only jumps to the destination instruction address if the ZF condition register is set to one. Which is used, for example, when you do an equality comparison. Right, so if you do a compare a and b for example. the ZF condition code is going to be set to one only if they're equal. Because if you recall, the comparison performs the difference. The difference is zero, it happens that the numbers are the same. Then there's a bunch of other jumping circumstances, they encourage you to take a look and see how their conditions work. Now we're going to jump into an example. So, this piece of code here, absdiff, does the following. It receives x and y as a parameter. And then returns the absolute difference between them. And the way we do that is by first comparing if x is greater than y, and if so the result is x minus y, because x is greater. So and otherwise it does y minus x in case y is greater than or equal to x. And this the asembly code in IA32 that implements this piece of code. And the first thing to note here is that we're using two, branch instructions to jump instructions. The first one here, jle, says jump less than or equal. And, note that there's a new thing here. There's a doc outside, but that's whats called a label. A label simply specifies a location in your code, where the jumps going to jump to if the condition evaluates the true. So, if this, if the comparison does lead to less than or equal result. The control flow is going to, so the program execution is going to go from here to one of it's instructions. It's going to go in, jump here, and then this instruction is going to be executed. And now there's an unconditional jump here that just branches to dot L8, it's a different label, to return from the function. Okay? So, you might have a hard time actually mapping this code directly to this assembly implementation here. Because there's some other thing is going on here, let me show you what. First, we when we are looking at this, is, to put a bunch of goto's, let's convert this program to use goto's to make it easier to see the translation to assembly. And by the way, we do not I recommend using goto's in your code. You can use goto's in C but it's generally considered bad coding style. What we're doing here just to make it clear how the translation happens. First note that expression in the comparison here changed from x greater than y to x less than or equal y. Because this is determining whether we should jump to the Else position since they invert. Condition, okay? And if so we execute the Else. And if we're done with the Else, it comes back to the exit, which is this part here, okay? So the exit here. Now if this evaluates to false, we actually executing the then part of your of your if. So that means that's called the The fallback. When you do not take a branch, it's called the fallback. In this case, you have the fallback as the then position. Okay? So, a high level way to think about this, that we converted this such that we jump over the then part of your if condition, 'kay and execute the Else only if the condition evaluates. Great. So let's look at this example step by step. Now note that we're at the c code that's converted to goto's now. these instructions here are just reading x and y putting them in edx and eax respectively. And now that's when I'm performing the comparison. Now that x and y are in the eax and edx registers we're comparing them. Okay so we're comparing x and y. That's in implementing this comparison here. And if this comparison happens to evaluate that x is less than or equal. Why? Then we jump to L7, to implement the Else block. Now let's see how the Else block, okay. So now if the jump does not happen, we're executing the, this part of the code. We're going to execute this search, and this is how it's implemented here this where we implement it. So, the sub instruction here thus edx equals edx minus eax. So it's essentially doing X minus Y. And then it gets the results and stores it in eax. And the reason we're storing to eax is because that's where we put return values for the function, that we can actually return the results. now the next step here is to implement the Else part of[INAUDIBLE] . And that's going to implement x minus y. And we use another subinstruction here, except that now see that the parameters are inverted compared to the other one. Now, what we're doing is, eax equals eax minus edx. And then from there we just jump To .L8, that's going to be return. And note that we did not have to, we did not need to copy the result to eax since that we can return it. Because the results was, was already in eax. so, let's look at conditional expressions in general and see how their, their translation happens. Well, in, C, you can write the following conditional expression. You can put a task here, which is any condition. For example x greater than y. And then we, we put the then expression, means that if this test, evaluates to true, we're going to return, the then expression. Otherwise, we're going to return the Else expression. So one way to implement the code, we just showed you, is to say, compare x, whether x is greater than y. And if so, we return x minus y. Otherwise, we return y minus x. So, and here's the goto version of that. And so we are evaluating the the opposite of this expression. So, in this case it's just going to be the complement of that expression. In execute the Else in case it reverts to true and then otherwise we're going to execute the then. So it does exactly what we just saw in the previous slide. So now you might be ask, you might be asking, how can we make this more efficient? Just so we can implement this simple conditional expression, we are inserting a bunch of branches in our code, a bunch of jumps. And this is not very efficient, branches tend to be expensive, especially modern, deeply pipelined processors. So x86 supports a special, x86-64 supports a special type of instruction that solves that problem. It's called a conditional move instruction. So what Conditional move does is it moves a value from one branches from the source to the destination. Only if a certain condition is met. And this condition the same ones that we use for jumps. So that means we can rewrite this code here in a way that we perform the comparison. And depending on the result of the comparison here we do a move. So we say we do move less than or equal. So essentially, we only move the value from edx to eax, if the condition is satisfied. So we can implement exactly what we just showed in the previous slide, without any branches. So we do the two subtractions here. We subtract x y, from x, and y from and x from y. Store them in ede, eax or edx, and then here we only move edx to eax if the condition gets set. And then we just return it, because we should put the return value in eax. Isn't that great? So, now, this is a way of, executing conditionals. Implement some conditional box without using, branch instructions. So this can be, a big win in performance in several cases. So, one last thing I want to show before ending this video is, how, addressing actually happens. Addressing of the destination instruction in, in in branches. 'Kay. And often the destination's specified in what we call a PC relative way. It means that the instruction specifies an offset that should be jumped to relative to the current instruction address. So in, in this example we have this "je" instruction. that jumps to, that, that's located in address 0x102 and then jumps to 0x172. But note that the destination here is specified as 0x70. Because this address here is computed as 0x102 + 0x70. Which is this value here, let's call PC relative. And the reason that this is so important is because now you can relocate this block. You can just change for example here we change it to different address and now we still have this compare because if we change where the code is since everything is relative you're not going to have to recompute the targets. in the branches in your codes. But note that some branches have absolute addresses. In that case they're not relocatable. See you next time.