Describe the Function of the Program Status Word in Assembly Language

Describe the function of the program status word in Assembly language

Somewhere behind every jz, jnz, bcc, or beq instruction you’ve ever written, there’s a small, unglamorous register quietly doing the real work: the Program Status Word (PSW). It doesn’t hold your data, and it doesn’t hold an address. It holds the state of the CPU itself — the flags, the mode, the interrupt-enable bits. I used to skim right past it in reference manuals, until I hit a bug that only made sense once I understood exactly what the PSW was tracking. This post is the explanation I wish I’d read first.

What Exactly Is a Program Status Word?

The Program Status Word (sometimes called the flags register, status register, or on ARM, the Current Program Status Register — CPSR/xPSR) is a special-purpose register that packs together multiple single-bit and multi-bit fields describing the current state of the processor. It’s not one “thing” so much as a bitfield of many small things:

  • Condition flags — results of the last arithmetic/logic operation (zero, carry, sign, overflow, parity).
  • Control flags — interrupt-enable bits, direction flags, trap flags.
  • Mode/privilege bits — what privilege level or execution mode the CPU is currently in.

Different architectures name and organize this differently, but the underlying purpose is identical everywhere: give the CPU (and the programmer) a compact snapshot of “what just happened” and “what mode am I in” at any instant.

The x86/x86-64 View: EFLAGS/RFLAGS

On x86, the Program Status Word is the FLAGS register (16-bit), extended to EFLAGS (32-bit) and RFLAGS (64-bit). Key bits include:

FlagBitMeaning
CF (Carry)0Set on unsigned overflow/borrow
PF (Parity)2Set if low byte of result has even parity
ZF (Zero)6Set if result is zero
SF (Sign)7Set if result is negative (MSB = 1)
TF (Trap)8Enables single-step debugging
IF (Interrupt Enable)9Enables maskable hardware interrupts
DF (Direction)10Controls direction of string instructions
OF (Overflow)11Set on signed overflow

Example: Flags in Action

mov     eax, 5
sub     eax, 5          ; result is 0
jz      is_zero          ; jumps because ZF was set by SUB

mov     eax, 0x7FFFFFFF
add     eax, 1           ; signed overflow — OF gets set
jo      overflow_detected

Every conditional jump (JZ, JNZ, JC, JO, JL, JG, and dozens more) is really just a test of one or more bits in EFLAGS/RFLAGS. That’s the entire mechanism behind conditional control flow in x86 assembly.

Reading and Writing EFLAGS Directly

pushfq                  ; push RFLAGS onto the stack
pop     rax             ; RAX now holds the flags
or      rax, 0x40       ; manually set ZF bit (illustrative)
push    rax
popfq                   ; RFLAGS updated from stack

The ARM View: CPSR / APSR / xPSR

ARM splits this concept slightly differently depending on the profile:

  • ARM classic/Cortex-A/R: the Current Program Status Register (CPSR) holds condition flags (N, Z, C, V), interrupt masks (I, F), the Thumb state bit (T), and the current processor mode (User, FIQ, IRQ, Supervisor, etc.) — all in one register.
  • ARM Cortex-M: splits this into the APSR (Application PSR — just the condition flags), IPSR (Interrupt PSR — current exception number), and EPSR (Execution PSR — Thumb state, IT-block state), collectively addressable as xPSR.
FlagMeaning
NNegative result
ZZero result
CCarry/borrow occurred
VSigned overflow occurred
QSaturation occurred (DSP-oriented)
I / FIRQ / FIQ mask bits
TThumb execution state
Mode bitsCurrent privilege/execution mode

ARM Assembly Example

CMP     R0, R1          ; compare, updates N, Z, C, V in APSR
BEQ     equal_case       ; branch if Z is set

MRS     R2, APSR         ; read APSR into R2
MSR     APSR_nzcvq, R2   ; write flag bits back from R2

ARM’s conditional execution goes further than most architectures — many ARM instructions themselves can be conditionally executed based on PSW flags (e.g., ADDEQ, MOVNE), not just branches, which is a distinctive feature worth knowing if you’re comparing architectures.

Internal Working Process

sequenceDiagram
    participant ALU as ALU/Execute Stage
    participant PSW as Program Status Word
    participant CU as Control Unit

    ALU->>PSW: Write result flags (Z, C, N, V...)
    CU->>PSW: Read flags for conditional branch/instr
    PSW-->>CU: Flag values
    CU->>CU: Decide branch taken / instruction executes
    Note over PSW: PSW also holds mode & interrupt-enable bits,<br/>checked continuously by hardware

Why the PSW Matters Beyond Just Branching

  1. Context switching — when an OS switches between processes or threads, it must save and restore the PSW along with the general-purpose registers and program counter. Get this wrong, and a resumed process could behave as though a previous comparison or interrupt state still applied.
  2. Exception/interrupt handling — entering an ISR typically pushes the current PSW onto the stack automatically (x86’s INT/hardware interrupt entry does this; ARM pushes xPSR as part of exception entry), so the interrupted context can be perfectly restored afterward.
  3. Privilege enforcement — the mode bits inside the PSW (ARM’s mode field, x86’s CPL derived from segment selectors plus system flags) determine what the currently executing code is allowed to do, which is foundational to OS/user separation.
  4. String and loop instruction behavior — on x86, the Direction Flag (DF) in EFLAGS controls whether MOVS, CMPS, SCAS, etc., process memory forward or backward.

Comparison Table: PSW Across Architectures

Aspectx86/x86-64 (EFLAGS/RFLAGS)ARM (CPSR/xPSR)
Register nameEFLAGS / RFLAGSCPSR (A/R profile), xPSR (M profile)
Condition flagsCF, ZF, SF, OF, PF, AFN, Z, C, V (+ Q)
Interrupt controlIF flagI, F mask bits
Mode/privilege infoDerived from segment/CPL, separate from EFLAGSEncoded directly in CPSR mode field
Conditional execution scopeBranches onlyBranches + many data-processing instructions
Direct read/writePUSHF/POPF, LAHF/SAHFMRS/MSR

Advantage of x86’s approach: a single, well-known flat flags register that’s simple to save/restore. Advantage of ARM’s approach: built-in conditional execution of ordinary instructions reduces branch count, which — as covered in pipeline discussions — reduces misprediction risk.

Practical Use Cases

  • Implementing multi-word arithmetic (ADC/SBB on x86, ADCS/SBCS on ARM) relies entirely on the carry flag propagating correctly between instructions.
  • Writing bootloaders and OS kernels requires manual PSW manipulation to switch privilege levels or enable/disable interrupts during critical setup phases.
  • Debuggers rely on the Trap Flag (x86) or debug-related exception mechanisms to implement single-step execution.

Debugging and Optimization Considerations

  • Common mistake: assuming flags persist across instructions that don’t actually preserve them. Many instructions (like MOV) don’t touch the flags at all, but plenty of others silently clobber them — always check the ISA reference for “flags affected.”
  • Debugging tip: most debuggers display the flags register directly; when a conditional jump doesn’t do what you expect, check the actual flag bits rather than assuming the comparison “should” have worked.
  • Optimization tip: ARM’s conditional instruction execution can eliminate short branches entirely, which is faster on pipelines where misprediction is costly — but overusing it on cores where predicated instructions still cost a cycle each way can be a wash. Profile before assuming it’s a win.

Best Practices

  1. Always check an instruction’s documented “flags affected” list before relying on it for a subsequent conditional operation.
  2. When writing interrupt handlers or context-switch code, never assume the PSW is preserved automatically unless the architecture explicitly documents that it pushes/restores it.
  3. Use PUSHF/POPF (x86) or MRS/MSR (ARM) sparingly and deliberately — manual flag manipulation is powerful but easy to misuse.
  4. When comparing signed vs. unsigned values, make sure you’re branching on the correct flag combination (JG/JL vs JA/JB on x86 test entirely different flag sets).

FAQs

Is the Program Status Word the same as the “flags register”? Functionally, yes, in most literature — “PSW” is the more general/textbook term, while specific architectures use their own names (EFLAGS, CPSR, xPSR).

Can user-mode code freely modify the entire PSW? No — mode/privilege bits and interrupt-enable bits are typically protected and can only be modified by privileged (kernel-mode) code, even though condition flags are freely modifiable by any code.

Why do signed and unsigned comparisons use different flags? Because “greater than” means something different depending on interpretation — unsigned comparisons rely on the Carry flag, signed comparisons rely on the relationship between the Sign and Overflow flags.

What happens to the PSW during a context switch? The OS scheduler saves the outgoing thread’s PSW (usually as part of its saved register/context block) and restores the incoming thread’s PSW, so each thread sees its own consistent flag/mode state.

Summary and Key Takeaways

The Program Status Word is the CPU’s compact record of “what just happened” and “what mode am I in” — condition flags from the last operation, control bits like interrupt-enable and direction, and privilege/mode information. Every conditional branch, every context switch, and every interrupt entry/exit depends on it being tracked and preserved correctly.

Key takeaways:

  • On x86/x86-64 it’s EFLAGS/RFLAGS; on ARM it’s CPSR (or the split APSR/IPSR/EPSR on Cortex-M).
  • Condition flags (zero, carry, sign, overflow) drive conditional branching and arithmetic chaining.
  • Control and mode bits govern interrupt masking and privilege enforcement.
  • Proper save/restore of the PSW is essential for correct interrupts, exceptions, and context switching.

References

  • Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1 — Basic Architecture, EFLAGS chapter.
  • AMD64 Architecture Programmer’s Manual, Volume 1 — RFLAGS register description.
  • ARM Architecture Reference Manual — Program Status Registers (CPSR, APSR, xPSR) chapters.
  • GNU Assembler (GAS) documentation for pushf/popf/lahf/sahf and ARM mrs/msr syntax.
Total
1
Shares

Leave a Reply

Previous Post
How is memory allocation managed in Assembly language

How Is Memory Allocation Managed in Assembly Language?

Next Post
What is the purpose of the instruction pipeline in Assembly language

What Is the Purpose of the Instruction Pipeline in Assembly Language?

Related Posts