Lecture 15 - Control Flow I
Goals
- Learn how x86 handles data movement
- Start thinking about control flow
- Learn about the branch instruction
I want to start by wrapping up some of the details from last time
x86
We looked at load and store on the ARM, what do they look like for x86?
it is all handled by the MOV command
mov eax, [ebx]
Meaning: eax ← Mem[ebx] (load base)
mov eax, [imm]
Meaning: eax ← Mem[imm] (load immediate)
mov [ebx], eax
Meaning: Mem[ebx] ← eax (store base)
mov ebx, [esi + 2*ecx]
Meaning: ebx ← Mem[esi + 2*ecx] (load base + scaled register)
There are, as you may imagine, some other variants, but these cover most of the important bases
Flow of execution
Now that we have a little more of an idea how memory and the processor work together, lets get a little more detailed about the fetch execute cycle for ARM32
Lets talk about a simple little assembly program
mov r0, #180
mov r1, #42
add r2, r0, r1
xor r0, r0, r0
str r2, [r0]
As you will recall, I described a special register called the program counter that stored the address of the next instruction to be executed.
For our ARM processors, the PC hangs out with the rest of the registers in the register file as r15. The implication of this is that we can read the value and even change it (though it is usually not a good idea to arbitrarily meddle with it).
if I tell you that the first instruction here starts at address 96, what can we say about the instructions
before any instructions are executed
r0 ?
r1 ?
r2 ?
...
r15 96
We grab the instruction pointed to by the PC, and execute it. So, r0 now holds a 180. Meanwhile, we increment the PC to… 100
mov r0, #180
r0 180
r1 ?
r2 ?
...
r15 100
Why 100?
- we know that each instruction is 32 bits
- we know that ARM uses byte-level addressing
- so, when we update
r15, we need to increment it by… 4
mov r1, #42
r0 180
r1 42
r2 ?
...
r15 104
add r2, r0, r1
r0 180
r1 42
r2 222
...
r15 108
xor r0, r0, r0
r0 0
r1 42
r2 222
...
r15 112
What is going on with xor r0, r0, r0?
What do we get if we xor a number with itself? zero
So this is quick way to zero out a register
xor r0, r0, r0
r0 0
r1 42
r2 222
...
r15 116
Control flow
So far, so good. However, this won’t lead to very interesting programs. For interesting and complex programs we want something like our conditional statements, loops and function calls.
In other words we need a way to change the control flow and break away from the rigid updating of PC ← PC + 4
Let’s consider the simplest of our control statements – the if statement
if (condition){
//do_conditional_thing
}
//do_next_thingIf the condition is true, then we do the conditional thing and then we do the next thing. If the condition is false, then we just do the next thing.
Now let’s imagine this as a block of assembly instructions. We are advancing through the instructions, with the PC remorselessly incrementing by 4 for every instruction. We get to right before this conditional statement. Let’s imagine, for a moment that the condition is just a value – 0 or 1.
If the condition is a 1, then we want to just keep trucking along and advance to the next instruction, which will be our “conditional thing”
If the condition is a 0, then we want to jump over the conditional instructions and advance to the next thing. So, we need some way to keep the PC from getting its normal +4 and replacing the value with the address of the next.
Note that this new way of thinking about it is slightly counter intuitive. We usually think about it the opposite way – if this condition is true then do this thing. We are turning this on its head and inverting the condition to say if the inverted condition is true, then skip over this stuff.
Mechanical level
vocabulary
Skills