Flow of control:
Every program execution can be described by such a linear sequence
In Java:
xxxxxxxxxx
91public static Foo {
2 static int s = 0;
3 static int i i;
4 static int a[] = new int [] {2, 4, 6, 8, 10, ..., 20};
5 static void foo() {
6 for (i = 0; i < 10; i++)
7 s += a[i];
8 }
9}
In C:
xxxxxxxxxx
71int s = 0;
2int i;
3int a[] = {2, 4, 6, 8, 10, 12, 14, 16 ...};
4void foo() {
5 for (i = 0; i < 10; i++)
6 s += a[i];
7}
alternatively:
i < sizeof(a) / sizeof(a[0]);
Keep a pointer (instead of index) at current location:
xxxxxxxxxx
81int s = 0;
2int *p;
3int a[] = {2, 4, 6, 8, 10, ...};
4void foo() {
5 p = a;
6 while (p < a + 10)
7 s += *p++;
8}
Trade-off:
Copying an array using array syntax:
xxxxxxxxxx
41void intcpy(int *s, int *d, int n){
2 for (int i = 0; i< n; i++)
3 d[i] = s[i];
4}
Copying an array using pointer arithmetic:
xxxxxxxxxx
41void intcpy(int *s, int *d, int n){
2 while(n--)
3 *d++ = *s++;
4}
xxxxxxxxxx
71int s = 0;
2int i;
3int a[] = {2, 4, 6, ..., 12};
4void foo() {
5 for (i = 0; i < 10; i++)
6 s += a[i];
7}
This vcode is equivalent ("unrolled" version)
xxxxxxxxxx
81int s = 0;
2int a [] = {2, 4, 6, 8, 10,...}
3void foo() {
4 s += a[0];
5 s += a[1];
6 ...
7 s += a[9];
8}
Can we generalize this technique?
xxxxxxxxxx
21for (i = 0; i < 10; i++)
2 s += a[i];
Can be translated to:
xxxxxxxxxx
61 i = 0;
2loop: goto end_loop if not (i < 10)
3 s += [ai];
4 i++;
5 goto loop
6end_loop:
Program Counter (PC)
For sequential instructions, PC is updated in fetch
So, to implement a goto, all we need is to change the PC
loop: goto end_loop if not (i<10)
New instruction: conditional jump
Options for evaluating condition
Unconditional (always jump)
Conditional based on register value
Conditional based on result of last ALU instruction
Problem: memory addresses are big
Jumps usually move a short distance (forward or backward)
Solution: relative addressing
instead of specifying the address to jump, specify the offset from current instruction
must be signed number (can jump backward)
jumps using relative addresses are called branches
Assembly still specifies actual address / label
xxxxxxxxxx
511000: goto 1008
21002: ...
31004: ...
41006: ...
51008: ...
Option 1: absolute addressing (jump)
X— 00001008
Option 2: relative addressing (branch)
Y-03
PC after fetch is 1002, so offset is 6 Since offset is always even, we can divide by 2
So, we need the following instructions:
at least one PC-relative jump (branch)
at least one absolute jump
some form of conditional jumps
New instructions:
xxxxxxxxxx
61 i = 0;
2loop: goto end_loop if (i - 10 == 0)
3 s += a[i];
4 i++;
5 goto loop
6end_loop:
xxxxxxxxxx
151 ld $0, r0
2 ld $a, r1
3 ld $s, 42
4 ld (r2), r2
5 ld $-10, r4
6loop: mov r0, r5
7 add r4, r5
8 beq r5, end_loop
9 ld (r1, r0, 4), r3
10 add r3, r2
11 inc r0
12 br loop
13end_loop: ld $2, r1
14 st r2, (r1)
15 st r0, 4(r1)
-
In Java or C:
if (<condition>) <then-statements> else <else-statements>
Pseudo-code using goto:
xxxxxxxxxx
61c = not <condition>
2goto then if (c == 0)
3else: <else-statements>
4goto end_if
5then: <then-statements>
6end_loop:
xxxxxxxxxx
101public class A {
2 public static void ping () {
3
4 }
5}
6public class Foo {
7 public static void foo() {
8 A.ping();
9 }
10}
Method: subroutine with a name, arguments and a local scope
Method invocation: causes the method to run with:
xxxxxxxxxx
41void ping () {}
2void foo () {
3 A.ping ();
4}
Procedure/function: subroutine with a name, arguments and local scope
Procedure call causes the procedure to run with:
xxxxxxxxxx
31void foo () {
2ping();
3}
xxxxxxxxxx
11void ping () {}
Caller: goto ping (jump)
Caller: continue executing
Question: return is a jump, but to where?
Return address is:
The address the procedure jumps to when it completes
The address of the instruction following the call that caused the run
A dynamic property of the program
Questions
Only the caller knows the address
So the caller must save it before it makes the call
Convention: caller will save the return address in r[6]
We need a new instruction to read the PC
Jumping back to return address
New requirements
New instructions:
xxxxxxxxxx
31void foo() {
2ping();
3}
xxxxxxxxxx
11void ping () {}
xxxxxxxxxx
51foo: gpc $6, r6 # r6 = pc of instruction after jump
2 j ping # goto ping
3
4ping: ...
5 j (r6) # return