COBOL GnuCOBOL 3.2.0 ·
✓ verified by execution on 2026-08-16
The PERFORM statement is the engine of COBOL. It serves two distinct purposes that are usually handled by completely different keywords in modern languages: it is both a looping construct (like for or while) and a subroutine caller (like a function invocation).
Mastering PERFORM is the key to reading real-world, legacy mainframe code, because it’s how COBOL structures control flow.
The Inline Block
At its simplest, PERFORM executes a block of code exactly once. This is called an inline perform, and it acts as a container for statements, bounded by END-PERFORM.
While a simple PERFORM block on its own isn’t very useful, it becomes incredibly powerful when combined with COBOL’s looping clauses.
The Out-of-Line Subroutine (Paragraphs)
If you give PERFORM a name instead of an inline block, it acts like a function call. It temporarily transfers control to a paragraph (a named section of code), executes it, and then automatically returns control to the statement immediately following the PERFORM.
Notice that MY-PARAGRAPH doesn’t have an explicit RETURN or END-PARAGRAPH statement. A paragraph automatically ends when the compiler encounters the next paragraph heading or the end of the program.
Here’s how control flow routes through an out-of-line PERFORM:
Warning: The Fall-Through Trap
If the normal execution flow reaches a paragraph without being explicitly called by a PERFORM statement, the program will execute it and fall through into the next paragraph! PERFORM gives paragraphs subroutine semantics, but structurally they are just labels.
Loops: PERFORM UNTIL
To create a while loop, you add the UNTIL phrase to PERFORM.
There is a massive gotcha here for modern developers: PERFORM UNTIL runs until the condition becomes true. It does not run “while the condition is true”. It is essentially a while (!condition) loop.
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. PERF-UNTIL. DATA DIVISION. WORKING-STORAGE SECTION. 01 COUNTER PIC 9 VALUE 1. PROCEDURE DIVISION. PERFORM UNTIL COUNTER > 3 DISPLAY 'COUNT: ' COUNTER ADD 1 TO COUNTER END-PERFORM STOP RUN.
Output
COUNT: 1
COUNT: 2
COUNT: 3
Your output
The “Test Before” Guarantee
By default, COBOL assumes WITH TEST BEFORE. This means it evaluates the condition before the first iteration. If the condition is already true, the loop body will be skipped entirely.
COBOL’s equivalent to the standard for loop is PERFORM VARYING. This structure automatically handles initializing a counter, checking the condition, and incrementing the counter on each iteration.
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. PERF-VARY. DATA DIVISION. WORKING-STORAGE SECTION. 01 I PIC 9. PROCEDURE DIVISION. PERFORM VARYING I FROM 1 BY 1 UNTIL I > 3 DISPLAY 'ITERATION: ' I END-PERFORM STOP RUN.
Output
ITERATION: 1
ITERATION: 2
ITERATION: 3
Your output
This reads exactly like it executes: set I to 1, test if I > 3 (TEST BEFORE), execute the block, increment I by 1, and repeat.
Exact Repeats: PERFORM TIMES
If you just need a block of code to repeat a specific number of times and don’t care about the loop index, PERFORM n TIMES is the cleanest option.
In the upcoming challenges, you’ll put PERFORM UNTIL and PERFORM VARYING into practice. Remember the golden rule: COBOL loops run until true, not while true!
Check yourself
If you want a loop to execute as long as X is less than 10, how do you write the PERFORM UNTIL condition?
Reveal answer
PERFORM UNTIL X >= 10 — COBOL's UNTIL means 'loop while this condition is FALSE'. To loop while X < 10, you must tell COBOL to stop when X >= 10.
What happens when a paragraph reaches its last statement and it was called by a PERFORM statement?
Reveal answer
Control automatically returns to the statement immediately following the PERFORM. — When called by PERFORM, a paragraph acts like a subroutine and automatically returns control when its end is reached.
By default, when does PERFORM UNTIL check its condition?
Reveal answer
Before every iteration, including the first (TEST BEFORE). — By default, PERFORM UNTIL implies WITH TEST BEFORE, meaning the loop body may never execute if the condition is already true.
Challenges
Challenge 1 +25 XP
Complete the PERFORM UNTIL loop to display 'STEP' followed by the step number, from 1 up to 3. Use the STEP-NUM variable.
cobol✓ solution verified at build time
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real — it came from compiling the solution with GnuCOBOL when this page
was built.
Test 1 — expects "STEP 1\nSTEP 2\nSTEP 3\n"
Need a hint? (−25% XP)
Loop UNTIL STEP-NUM > 3, then inside the loop DISPLAY the number and ADD 1 TO it.
Show solution (0 XP)
IDENTIFICATION DIVISION.PROGRAM-ID. CHAL-UNTIL.DATA DIVISION.WORKING-STORAGE SECTION.01 STEP-NUM PIC 9 VALUE 1.PROCEDURE DIVISION. PERFORM UNTIL STEP-NUM > 3 DISPLAY 'STEP ' STEP-NUM ADD 1 TO STEP-NUM END-PERFORM. STOP RUN.
Challenge 2 +25 XP
Use PERFORM VARYING to loop from 1 to 3 by 1, storing the loop counter in IDX. Display the value of IDX on each iteration.
cobol✓ solution verified at build time
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real — it came from compiling the solution with GnuCOBOL when this page
was built.
Test 1 — expects "1\n2\n3\n"
Need a hint? (−25% XP)
Use `VARYING IDX FROM 1 BY 1 UNTIL IDX > 3`.
Show solution (0 XP)
IDENTIFICATION DIVISION.PROGRAM-ID. CHAL-VARY.DATA DIVISION.WORKING-STORAGE SECTION.01 IDX PIC 9.PROCEDURE DIVISION. PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > 3 DISPLAY IDX END-PERFORM. STOP RUN.