Your first COBOL program: all four divisions, DISPLAY, STOP RUN
A complete first COBOL program for GnuCOBOL, explained division by division, with DISPLAY, WITH NO ADVANCING, signed and unsigned numbers, and STOP RUN.
This lesson gives you one complete COBOL program, forty lines long, written to be compiled with GnuCOBOL and run. By the end you will know what each of the four divisions is for, how DISPLAY writes to the terminal, why an unsigned number prints with leading zeros, and what STOP RUN actually does. Every later tutorial on this site builds on this shape, so it is worth reading slowly once.
The listing below was first desk-checked against the GnuCOBOL 3.2 Programmer's Guide, with its output derived by hand from the documented rules. On 29 October 2026 we compiled and ran it with GnuCOBOL 3.2, and the output shown further down is what it printed, which matched the hand derivation line for line.
The program
>>SOURCE FORMAT IS FREE
*> cobol-hello-world.cob - a first program: four divisions,
*> DISPLAY, and STOP RUN
*> Dialect: GnuCOBOL 3.x, free format
*> Status : desk-checked against the GnuCOBOL 3.2 Programmer's Guide;
*> compiled and run with GnuCOBOL 3.2 on 2026-10-29
*> Inputs : none
*> Outputs: six lines on standard output
*> Build : cobc -x cobol-hello-world.cob
*> Run : ./cobol-hello-world
*> (Windows: cobol-hello-world.exe)
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO-FOUR.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. DESKTOP-PC.
OBJECT-COMPUTER. DESKTOP-PC.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-Greeting PIC X(20) VALUE "Hello from COBOL".
01 WS-Unsigned-Count PIC 9(3) VALUE 7.
01 WS-Signed-Count PIC S9(3) VALUE -7.
01 WS-Sum PIC S9(4) VALUE ZERO.
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
DISPLAY WS-Greeting
DISPLAY "Unsigned count : " WS-Unsigned-Count
DISPLAY "Signed count : " WS-Signed-Count
ADD WS-Unsigned-Count TO WS-Sum
ADD WS-Signed-Count TO WS-Sum
DISPLAY "Sum : " WITH NO ADVANCING
DISPLAY WS-Sum
DISPLAY "A literal : " 42
DISPLAY "Two literals : " "COBOL" " " 1959
STOP RUN.
Line by line
The first line is a compiler directive, not COBOL. >>SOURCE FORMAT IS FREE tells cobc that everything after it is free-format source, so we can start statements in any column. It sits seven spaces in, at column 8, because the Programmer's Guide (section 2.1.16) says the compiler starts in fixed format and in that mode a directive must begin in column 8 or later. After the directive, the column rules are gone. Lines beginning with *> are comments, and a *> can also follow code on the same line.
Why does the directive exist at all? For most of its life COBOL source was punched on 80-column cards. Columns 1 to 6 held a sequence number, column 7 was an indicator column (an asterisk there made the line a comment), division and section headers and level numbers 01 and 77 had to start in Area A (columns 8 to 11), everything else went in Area B (columns 12 to 72), and columns 73 to 80 were ignored. That layout is still the default in GnuCOBOL and it is what you will meet in any bank's source library. This lesson just uses the modern form; the column rules above are all you need to read an older fixed-format listing.
IDENTIFICATION DIVISION. The only required entry here is PROGRAM-ID, which names the program. The name matters more than it looks: when a program is called from another, the caller uses this name, and GnuCOBOL derives the entry-point name of the compiled object from it. The Programmer's Guide notes that the IDENTIFICATION DIVISION. header line itself is optional in GnuCOBOL, but this site always writes it.
ENVIRONMENT DIVISION. This division describes the machine and the files. The CONFIGURATION SECTION with SOURCE-COMPUTER and OBJECT-COMPUTER is where a program from 1975 said which mainframe it was compiled on and which it would run on. The names are user-defined words and GnuCOBOL does nothing with them, so the whole section could be deleted. We keep it here once so that you recognise it when you see it. The INPUT-OUTPUT SECTION, which is where files are declared, is absent because this program reads nothing; the sequential file lesson is where it first appears.
DATA DIVISION. Every variable a COBOL program uses is declared here, before any statement runs. The WORKING-STORAGE SECTION holds items that live for the whole run. Each line is a data description entry: a level number, a name, a PIC (short for PICTURE) that says what the item holds and how big it is, and an optional VALUE giving its starting contents. PIC X(20) is twenty alphanumeric characters; PIC 9(3) is three decimal digits with no sign; PIC S9(3) is three digits with a sign. The figurative constant ZERO sets a numeric item to zero. The PICTURE clause has its own lesson, but one rule is worth stating now: the picture decides not only the size but also what arithmetic is allowed on the item.
PROCEDURE DIVISION. This is the code. It is organised into paragraphs, and MAIN-PARAGRAPH. is the only one here. Inside it, each DISPLAY writes one line to standard output. A DISPLAY may list any number of operands, literals or identifiers, and writes them one after another with no separator, which is why the literals in the last line carry their own spaces. The IBM Language Reference describes the same statement with an UPON phrase for choosing the device; GnuCOBOL accepts UPON too, and without it the output is standard output.
WITH NO ADVANCING suppresses the line ending after the operands, so the next DISPLAY continues on the same line. The IBM page puts it plainly: without the phrase, the device is positioned at the start of the next line after the display; with it, the position is not changed. The two ADD statements are the simplest arithmetic verbs COBOL has, and ADD a TO b leaves the result in b.
STOP RUN. ends the run unit and returns control to the operating system. According to the IBM STOP statement page, it also closes every file that is still open in any program of the run unit, and the exit status comes from the RETURN-CODE special register. GnuCOBOL's Programmer's Guide (section 7.8.42) says the same, and adds a STOP RUN RETURNING n form if you want to set the exit status explicitly. Note the period after STOP RUN: in COBOL a period ends a sentence, and the paragraph ends with the last sentence. In modern code the period is used sparingly, once at the end of a paragraph, and scope terminators such as END-IF do the rest.
Compile and run
cobc -x cobol-hello-world.cob
./cobol-hello-world
The -x option asks for an executable rather than a module. The GnuCOBOL Manual's own "Hello, world" example shows that a program written in free format needs either the -free compiler option or the >>SOURCE FORMAT IS FREE directive; since the directive is in the file, the plain command above works, and adding -free is harmless. The executable takes its name from the source file unless you pass -o.
Worked example
The output, as GnuCOBOL 3.2 printed it:
Hello from COBOL
Unsigned count : 007
Signed count : -007
Sum : +0000
A literal : 42
Two literals : COBOL 1959
Three of those lines deserve a second look. WS-Greeting is twenty characters wide and the value is sixteen characters long, so the item is padded with four trailing spaces; they are displayed too, invisibly. WS-Unsigned-Count prints as 007 because a PIC 9(3) item always occupies three character positions and a USAGE DISPLAY numeric item stores one character per digit, leading zeros included. That is not a formatting choice by DISPLAY; it is the contents of memory.
The signed items are where GnuCOBOL differs visibly from a mainframe. In storage, a PIC S9(3) item still occupies three bytes and the sign is carried inside the last digit. GnuCOBOL's default compiler configuration turns on an option called pretty-display ("alternate formatting of numeric fields", in the words of the shipped manual's configuration appendix), and with it a signed item is displayed with a separate leading sign, so -7 appears as -007 and the zero sum appears as +0000. The value is identical; only the rendering differs. On Enterprise COBOL the same DISPLAY shows the raw bytes, and the embedded sign turns the last digit into a letter, which is why mainframe programmers move numbers into an edited picture before printing them. That is the subject of the edited pictures lesson.
Numeric literals are displayed as written, so 42 and 1959 have no leading zeros; they are not stored in a picture. There is one more result you cannot see: STOP RUN returns exit status 0 to the shell, because nothing changed RETURN-CODE.
Limitations
The output above comes from one GnuCOBOL 3.2 build with its default configuration. The leading zeros, the padding, and the separate sign follow from the Programmer's Guide's descriptions of PICTURE, USAGE DISPLAY, and the pretty-display configuration default; if your GnuCOBOL was built with a different default configuration, or you compile with a dialect option such as -std=ibm, the signed lines can render differently. The CONFIGURATION SECTION names are decorative. And this program does nothing with its data beyond adding two numbers, which is deliberate: the next lesson, on the PICTURE clause, is where the storage model gets explained properly, and only after that do MOVE, PERFORM, and COMPUTE make sense.
Correction, 29 October 2026: the build command shown before named the source cobol-hello-world-four-divisions.cob, and GnuCOBOL 3.2's cobc refuses a source file whose base name is longer than 31 characters ("invalid file base name ... length exceeds maximum"), even with -o, so the first command of the first lesson failed as printed. The listing is now shipped as cobol-hello-world.cob, and the old download address redirects there. The same day we compiled and ran the program with GnuCOBOL 3.2, and its output matched the output shown here line for line, so the page now says that instead of calling the listing desk-checked only.
Index terms cobol, gnucobol, display, stop run, divisions