The program counter (pc)

Program counter and jumps

The program is stored in memory, where each instruction takes 1 or 2 field elements (for example, when an immediate value is used in the instruction, it takes 2 field elements, where the second one is the immediate value).

The program counter (pc) keeps the address of the current instruction. Usually it advances by 1 or 2 per instruction according to the size of the instruction (when the current instruction occupies two field elements, the program counter advances by 2 for the next instruction).

A jmp instruction may be used to jump to a different instruction. jmp is available in three flavors:

  1. Absolute jump: jumps to a given address (by changing the program counter to the given value). For example, jmp abs 17; will change pc to 17.

  2. Relative jump: jumps to an offset from the current instruction. For example, jmp rel 17; will change pc to pc + 17. Note that pc refers to the value of the program counter of the current instruction. Thus, a special case is the instruction jmp rel 0; which jumps to itself, thus creating an infinite loop.

  3. Jump to a label: this translates to a relative jump where the Cairo compiler is automatically computing the difference between the current instruction and the label. This is the most useful (and readable) jump.


What does the following code do? (run with --no_end --step=16 to avoid the End of program was not reached error)

func main() {
    [ap] = 2, ap++;

    [ap] = [ap - 1] * [ap - 1], ap++;
    [ap] = [ap - 1] + 1, ap++;
    jmp my_loop;

Bonus exercise

What happens in the following code? (you can start by running it and looking at the memory; note that you will need the --no_end flag)

func main() {
    [fp + 1] = 2, ap++;
    [fp] = 5201798304953761792, ap++;
    jmp rel -1;

Conditional jumps

Another important type of instruction is the conditional jump. The syntax of the instruction is jmp <label> if [<expr>] != 0; where <expr> is either ap + offset or fp + offset (offset may be omitted). If the corresponding memory cell is not zero, the Cairo machine will jump to the given label. Otherwise, it will continue to the next instruction normally. Instead of using a label, you may also use rel <expr> in a similar way to a regular jump (for example jmp rel 17 if [ap - 1] != 0;).


Edit the loop my_loop in the exercise above so that it starts by writing 10 to [ap], continues by writing the decreasing sequence \(9, 8, 7, \ldots, 0\) and then returns. Don’t forget the ret instruction. Verify that your code works as expected by looking at the memory.