Back to GSM Code List

M98 and M99: subprograms in the CNC control

M98 calls a subprogram and M99 hands control back to the main program. With M98 P1000, the control jumps to program O1000, runs it until it finds the M99 and comes back to the block after the call. It is there so you write once what repeats: a pocket that appears in four places, the machining that has to be done in two setups or a pass given several times stepping down in Z. Repeats are given with L, or with the P itself on old Fanucs.

For reference only: syntax changes with the control, the post-processor and the machine parameters. Check the official manual and run a simulation before cutting. Legal notice.

Family
Program
Machine
Milling, Turning, Mill-turn
Risk
Medium
Example
M98 P1000 / M99

Syntax by control

Fanuc

M98 P1000 L4

P is the subprogram number without the O, and leading zeros are ignored: P1000 calls O1000 and P1 calls O0001. On old Fanuc controls, P takes eight digits where the first four are the repeats, so P00041000 is four passes of O1000.

Haas

M98 P1000 L4

Same syntax. Haas adds M97 P, which calls a local subprogram by N block number inside the same program: it saves managing two files and is very handy for short programs.

Mitsubishi and some Fanucs

M98 P1000 H50 L2

H gives the N sequence number of the subprogram to start from, instead of starting at its first line. It does not exist on every control: check it before using it.

Siemens 840D / 828D

L1000 P4

Siemens uses neither M98 nor M99: the subprogram is called by writing its name (L1000, or a name of your own such as TALADROS) and P gives the repeats. The subprogram ends with M17 or with RET. EXTCALL calls a program held in external memory.

Heidenhain TNC (Klartext)

CALL LBL 1 REP4

Subprograms are labels inside the same program: LBL 1 marks the start, LBL 0 the end and CALL LBL 1 REP4 runs it four times. To call another complete program you use CALL PGM.

M99 in the main program

/M99

An M99 written in the main program returns nowhere: it restarts the program from the beginning, creating an infinite loop. With the block delete slash in front, the operator can break it from the panel. It is the usual trick on machines with a bar feeder.

Address letters used with it

LetterWhat it setsUnit
P (with M98)Number of the subprogram being called, written without the O. On old Fanucs it can carry eight digits, with the repeats in the first four.integer
LNumber of repeats of the call. M98 P1000 L4 runs the subprogram four times in a row. With no L, it runs once.integer
HN sequence number inside the subprogram to start from, on Mitsubishi controls and some Fanucs. It is not universal.block number
P (with M99)N block of the main program to return to, instead of returning to the block after the call. It lets you jump forward or backward on the way back.block number
O number of the subprogramHeader of the subprogram in its own file or its own area of memory. It has to exist in the control: if it is not loaded, the call throws a program not found alarm.integer (O1000)

Worked example

A 12 mm deep slot in steel that has to be taken down in four 3 mm passes. Instead of writing the same thing four times, the pass lives in a subprogram that drops 3 mm in incremental and runs the slot out and back, and the main program calls it four times with L4. Notice that the subprogram leaves the tool at the same point in the plane it started from: if it did not, every repeat would walk further along.

O0098 (RANURA EN CUATRO PASADAS)
( Header of the main program. )
G21 G17 G40 G49 G80
( Millimeters, XY plane and a clean state. )
G91 G28 Z0.
( Z to the reference point in incremental before the change. )
T4 M06 (FRESA D10)
( 10 mm cutter. )
G90 G54 G00 X10. Y30. S2800 M03
( Absolute, work offset, positioning at the start of the slot and spindle on. )
G43 H04 Z50.
( T4 length offset. )
G00 Z0.5 M08
( Sits half a millimeter above the face: that is the starting point of the first step down, and the subprogram counts on it. )
M98 P2001 L4
( Calls subprogram O2001 four times. Each call drops another 3 mm, so by the end the slot is 12 mm deep. )
G90 G00 Z50. M09
( Back to absolute in case the subprogram left something in incremental, retract in Z and coolant off. )
G91 G28 Z0. M05
( Z to the reference point and spindle stop. )
G90 M30
( End of the main program. This M30 is essential: without it, the control would keep reading and walk into the subprogram as if it were new code. )
O2001 (UNA PASADA DE LA RANURA)
( Header of the subprogram. It lives in its own file or its own area of the control memory. )
G91 G01 Z-3. F150
( Drops 3 mm in incremental from wherever the tool is. That is the key to the repeats: in absolute, the four passes would all go to the same depth. )
G90 G01 X150. F700
( Runs the slot out, now in absolute. )
G01 X10.
( Comes back along the same slot to the starting point, so the tool ends up where the next step down needs it. )
M99
( Hands control back to the main program. Since the call carried L4, the control comes back in until the four passes are done and only then carries on with the block after the M98. )
Open the simulator to check the example

Practical keys to using M98/M99 in the workshop

What a program gains from subprograms

First, maintenance: if the pocket repeats in six positions and one dimension has to change, you change it in one place and not in six. Second, readability: the main program becomes a list of operations you can read at a glance. Third, memory, which on old controls is still a real limit. And fourth, production flexibility: the same subprogram is called from several work offsets to machine several setups, or repeated with L to take successive passes. The cost is that you have to manage two files and that a missing subprogram stops the machine.

Incremental mode is what makes the repeats useful

A subprogram called with L4 runs four times exactly the same, so if everything inside is absolute, the four passes do the same thing in the same place. What gives the repeat any meaning is that something inside is incremental: dropping another 3 mm in Z, moving another 40 mm in X for the next hole, indexing the fourth axis another step. That is why G91 and G90 live together inside the subprogram and why the main program should write G90 the moment it comes back: whichever mode is active when the M99 runs is the one the rest of the program takes with it.

Nesting, returns with P and the main program loop

A subprogram can call another, but there is a limit on levels: Fanuc usually allows four and other controls allow more, so it pays not to build long chains. M99 P hands control back to a particular N block instead of the next one, which is useful for skipping part of the program when it suits, although it makes the code harder to follow. And an M99 written in the main program returns nowhere: it restarts from the first block. With the block delete slash in front, the operator decides from the panel whether the machine keeps producing or stops.

Mistakes that cost you a part (or a tool)

  • Forgetting the M99 at the end of the subprogram: the control keeps reading whatever is behind it in memory or reaches the end of the file and alarms, with the tool wherever it was.
  • Writing M30 instead of M99 at the end of the subprogram: instead of returning, the whole program ends in the middle of the part.
  • Not putting M30 at the end of the main program, before the subprogram: the control falls into the subprogram and runs it as if it were new code, normally with the tool already retracted and in another work offset.
  • Calling a subprogram that is not loaded in the control or mistyping the number in the P: program not found alarm, nearly always in the middle of a run.
  • Leaving G91 active when the M99 runs: everything that follows in the main program is read as incremental, and the first rapid positioning move turns into a crash.
  • Writing a subprogram that does not return the tool to the point it started from: with L4, every repeat starts where the last one finished and the result walks away pass by pass.
  • Going past the number of nesting levels the control allows: the alarm does not say which level, only that there is a subprogram problem.
  • Expecting a subprogram to take parameters like a function: M98 passes no variables. That is what macro calls with G65 and local variables are for.

Frequently Asked Questions (FAQ)

Does the P of M98 carry the O of the subprogram?

No. You write the number alone: to call O1000 you write M98 P1000. Leading zeros are ignored, so P1 calls O0001. On some old Fanucs the P takes eight digits because the first four are the repeats.

How do I repeat a subprogram several times?

With L: M98 P1000 L4 runs it four times in a row. On the Fanucs that use the eight digit P, P00041000 does the same. For the repeat to be worth anything, there has to be some incremental move inside the subprogram; otherwise the four passes repeat the same path.

What is the difference between M98 and the Haas M97?

M98 calls another program stored separately in the control memory. M97 P calls an N block inside the same program, so everything lives in a single file. M97 is handier for short programs and avoids losing the subprogram when you copy the program to another machine; M98 is the standard and works on any control.

How many subprograms can be nested?

It depends on the control: Fanuc usually allows four levels of nesting and other controls allow more. It is a limit nobody remembers until the alarm goes off, so as a shop rule it pays not to go past two or three levels even if the machine takes more.

What is an M99 in the main program for?

To make the program start over by itself, in a loop. It is used on machines with a bar feeder or with automation, where the next part comes in on its own. The normal thing is to write it with the block delete slash in front, so the operator can break the loop from the panel at the end of the part in progress.

Related codes

Other codes in Program

See the full list of G and M codes

Related tools