ADVERTISEMENT
Responsive Ad Unit • Systems Architecture & Low-Level Engineering

Module 4 — Program Counter (PC) / Instruction Pointer (IP)

Learning Objectives

By the end of this module, you should be able to explain:

  • What is the Program Counter?
  • Why is it needed?
  • How does it change during execution?
  • How do loops work?
  • How do if, switch, and goto work?
  • How do function calls change the PC?
  • How do interrupts change the PC?
  • How does the OS use the PC during context switching?
  • ARM vs x86 PC differences

1. What is the Program Counter?

The Program Counter (PC) is a special CPU register that contains the address of the next instruction to execute.

Think of it as the CPU's bookmark.

Example:

Suppose memory contains:

Address      Instruction

1000         MOV R1,#10
1004         ADD R2,R1,#5
1008         SUB R3,R2,#2
1012         STORE R3,[2000]

Initially,
PC = 1000

The CPU fetches:
MOV R1,#10

After fetching,
PC = 1004

After the next instruction,
PC = 1008

The PC keeps advancing through the program.

Graphical View

Memory

1000 → MOV R1,#10 ← PC
1004 → ADD R2,R1,#5
1008 → SUB R3,R2,#2
1012 → STORE

After one instruction:

Memory

1000 → MOV
1004 → ADD ← PC
1008 → SUB
1012 → STORE

The PC simply moves from one instruction to the next during normal execution.

2. Why Do We Need a Program Counter?

Imagine reading a book.

Without a bookmark, every time you closed the book, you would have to start from page 1.

The PC is that bookmark.

It tells the CPU:
"This is where you should continue executing."

Without a PC, the CPU would have no idea which instruction comes next.

3. Sequential Execution

Consider:

int a = 10;
int b = 20;
int c = a + b;

Compiler (simplified):

1000 LOAD a
1004 LOAD b
1008 ADD
1012 STORE c

Execution:

PC =1000
↓
LOAD a
↓
PC=1004
↓
LOAD b
↓
PC=1008
↓
ADD
↓
PC=1012
↓
STORE

This is called sequential execution.

4. Fetch-Decode-Execute with PC

Every instruction begins with the PC.

PC
|
V
RAM Memory
|
Fetch Instruction
|
Decode
|
Execute
|
Update Program Counter
|
Repeat

Notice the cycle always returns to updating the PC.

5. What Happens Inside the CPU?

Suppose
PC =1000

  • Step 1
    CPU reads Memory[1000]
  • Step 2
    Instruction goes into Instruction Register
  • Step 3
    Control Unit decodes it.
  • Step 4
    ALU executes it.
  • Step 5
    PC becomes 1004

6. How Does a Loop Work?

Example

for(int i=0;i<5;i++)
{
    printf("%d",i);
}

People often think the CPU "understands" a for loop.

It doesn't.

It only understands jump instructions.

Simplified Assembly

1000 MOV i,0
1004 CMP i,5
1008 JGE 1024
1012 PRINT i
1016 INC i
1020 JMP 1004
1024 EXIT

Execution

PC=1000
↓
1004
↓
1008
↓
1012
↓
1016
↓
1020
↓
1004
↓
1008
↓
1012

Notice:
The PC jumps backwards.
That's the loop.

Visualization

1004
↓
1008
↓
1012
↓
1016
↓
1020
↓
↑
└───────────────

A loop is simply the PC repeatedly jumping to an earlier address.

7. How Does an if Statement Work?

Example

if(a>b)
{
   x=1;
}
else
{
   x=2;
}

Assembly (simplified)

1000 CMP a,b
1004 JLE 1016
1008 MOV x,1
1012 JMP 1020
1016 MOV x,2
1020 Continue

If a>b

PC
1000
↓
1004
↓
1008
↓
1012
↓
1020

Otherwise

1000
↓
1004
↓
1016
↓
1020

The Program Counter decides which block executes.

8. Function Calls

Example

main()
↓
add()
↓
return

Assembly

1000 CALL add
1004 PRINT
2000 ADD
2004 RETURN

Execution

PC=1000
↓
CALL
↓
PC=2000
↓
Execute
↓
Return
↓
PC=1004

The return address is saved (in the Link Register on ARM or on the stack on x86), allowing execution to continue correctly.

Visualization

Main

1000 CALL
↓
Spacer
Spacer
↓
1004

Function

2000
↓
2004
↓
Return

9. Interrupt Example

Suppose
The CPU is executing
PC=1500

Suddenly
Camera interrupt occurs.

CPU automatically

Save PC
↓
Jump
↓
ISR

Suppose ISR starts 5000

Execution

1500
↓
Interrupt
↓
5000
↓
ISR
↓
Restore PC
↓
1500

The CPU resumes exactly where it stopped.

Embedded Example

In your ADAS project:

Image Processing
↓
PC=10000
↓
Camera Interrupt
↓
ISR=50000
↓
DMA Complete
↓
Restore PC
↓
Continue Image Processing

This happens in microseconds.

Without saving the PC, the interrupted task could never resume correctly.

10. Context Switching

Suppose Process A is running.
PC=3000

Timer interrupt
↓
OS Scheduler
↓
Save
PC=3000
Load Process B
PC=9000

CPU continues
9000

Later
Process A resumes
PC=3000

The OS stores the PC in the Process Control Block (PCB) along with other registers.

Visualization

Process A
PC=3000
↓
Save PCB
↓
Scheduler
↓
Process B
PC=9000
↓
Run
↓
Save PCB
↓
Restore A
↓
PC=3000

ARM vs x86

ARM x86
PC register RIP (Instruction Pointer)
Uses Link Register for many function returns Typically pushes return address onto stack
Fixed-width instructions (common in AArch32; AArch64 uses fixed 32-bit instructions) Variable-length instructions

Debugger Example

When you set a breakpoint:

printf("Hello");

The debugger watches the Program Counter.

When
PC == breakpoint address
Execution pauses.

Single-stepping simply executes one instruction, updates the PC, then pauses again.

Why Is the PC So Important for an OS?

Without the Program Counter:

  • No process execution
  • No multitasking
  • No function calls
  • No interrupts
  • No scheduler
  • No debugging
  • No exceptions
  • No context switching

The PC represents where a thread or process is currently executing.

Interview Questions

Beginner

  • What is the Program Counter?
  • What information does it store?
  • Why is it needed?

Intermediate

  • How does the PC change during sequential execution?
  • How do loops use the Program Counter?
  • How does an if statement affect the PC?
  • What happens to the PC during a function call?

Senior

  • How does the CPU save and restore the PC during an interrupt?
  • How is the PC used during context switching?
  • Why must the PC be saved in the PCB?
  • Explain the difference between ARM's PC behavior and x86's RIP.
  • How does a debugger implement breakpoints using the Program Counter?

Common Mistakes

  • ❌ Thinking the PC stores the current C source line. It stores a machine instruction address.
  • ❌ Assuming the PC always increments by a fixed amount. Branches, jumps, calls, returns, exceptions, and interrupts can all change it.
  • ❌ Believing loops are special CPU constructs. They are implemented using conditional and unconditional jumps.
  • ❌ Forgetting that the OS must save the PC during a context switch.

Summary

The Program Counter is the CPU register that determines the flow of execution. Every instruction begins with the address in the PC, and every change in program flow—loops, branches, function calls, interrupts, and multitasking—is implemented by changing the Program Counter. This makes it one of the most critical registers in both CPU architecture and operating system design.

Mini Quiz

  1. Why does the CPU need a Program Counter?
  2. How does the PC behave during sequential execution?
  3. How is a for loop implemented using the PC?
  4. What happens to the PC during a function call?
  5. What happens to the PC when an interrupt occurs?
  6. Why does the OS save the PC during a context switch?
  7. How does a debugger use the Program Counter?
Knowledge Check

Concept Mastery Assessment — Module 04

Verify your conceptual understanding with 12 targeted technical assessment questions. Instant feedback and explanations are provided for every choice.

Question 1 of 12
What fundamental action does the CPU perform on the Program Counter (PC) during the normal instruction fetch stage?
Explanation
During fetch, the CPU automatically increments the PC by the length of the current instruction so it references the next instruction in sequence.
Question 2 of 12
What occurs to the Program Counter when an unconditional jump instruction (e.g., JMP target) is executed?
Explanation
A jump instruction replaces the current value in the Program Counter with the target jump address, redirecting execution.
Question 3 of 12
How does a processor execute a conditional branch instruction (e.g., JZ - Jump if Zero)?
Explanation
Conditional branches inspect status flags. If the condition is met, the PC is loaded with the branch target; otherwise, PC advances sequentially.
Question 4 of 12
What does the x86 CALL instruction automatically do before modifying the Program Counter (RIP)?
Explanation
The CALL instruction pushes the return address (the next sequential instruction address) onto the stack pointed to by RSP before jumping.
Question 5 of 12
How does the RET (Return from Subroutine) instruction restore program flow back to the caller?
Explanation
RET pops the return address off the stack and loads it into the Program Counter, resuming execution immediately after the original CALL instruction.
Question 6 of 12
What is 'RIP-relative addressing' in x86-64 assembly, and why is it essential for modern operating systems?
Explanation
RIP-relative addressing allows binaries to compute memory references relative to the current instruction pointer, enabling Position-Independent Code.
Question 7 of 12
When a context switch occurs between two processes, how is the Program Counter handled by the kernel?
Explanation
The kernel saves the outgoing process's PC and register state into its PCB/thread structure and loads the incoming process's saved PC into hardware.
Question 8 of 12
What hardware feature anticipates whether a conditional branch will be taken or not before the condition flag is actually calculated?
Explanation
A branch predictor uses historical pattern tables to guess whether branches are taken, preventing pipeline stalls.
Question 9 of 12
What is the consequence of a branch misprediction on a deeply pipelined processor?
Explanation
When a branch prediction is incorrect, all speculative instructions in the pipeline must be discarded and the pipeline reloaded from the correct PC address.
Question 10 of 12
What security vulnerability occurs when an attacker overwrites the saved return address on the stack to point the Program Counter to malicious code?
Explanation
Smashing the stack allows attackers to overwrite the return address, controlling the value loaded into RIP upon RET to hijack control flow.
Question 11 of 12
What security mechanism randomizes the memory locations of program sections (including code/text) so attackers cannot predict target addresses for the Program Counter?
Explanation
ASLR randomizes the base addresses of the executable, stack, heap, and shared libraries, preventing attackers from relying on static target addresses.
Question 12 of 12
Can user-mode software directly write arbitrary values into the Program Counter using a generic MOV instruction (e.g., mov rip, 0x1000) on x86-64?
Explanation
Architectural instruction pointers cannot be targeted directly by MOV; control transfer is strictly mediated via jump, call, ret, and syscall instructions.
0 / 12 (0%)
Great job! Review the concepts above and proceed when ready.
ADVERTISEMENT
Responsive Ad Unit • Technical Courses & Certifications