Skip to main content
CNC.wiki

Guide to Writing and Calling Subprograms on Fanuc, Siemens, and Mitsubishi

Master subprograms on Fanuc, Siemens, and Mitsubishi. Learn M98, M198, MCALL syntax, configure parameters like 3404, and resolve nesting alarms 0077 and 14012.

Hakan Gündoğdu
Hakan Gündoğdu

CNC CARE Co-founder

Introduction

Failing to restore absolute coordinate positioning at the end of a CNC subprogram creates an uncommanded spatial shift that drives the turret or spindle directly into a machine fixture. When the CNC interpreter reads an M99 or M17 return block while the active state is still set to incremental positioning (G91), the parent program resumes execution relative to the last subprogram coordinate instead of the absolute work coordinate system (G54). The operator sees the machine slide shift away from its expected path, followed by a high-pitched grinding sound as the cutting tool plunges violently into a clamp, vise jaw, or the chuck itself. This hard collision instantly bends the spindle shaft, shatters the tooling, and results in a ruined, scrapped workpiece. Preventing these catastrophic crashes requires a strict understanding of subprogram structure, parameter lockouts, and modal data boundaries across Fanuc, Siemens, and Mitsubishi control systems.

Technical Summary

Technical SpecificationDetails
Command CodesFanuc: M98, M99, M198
Siemens: L<number>, <program name>, MCALL, EXTCALL, M17, RET
Mitsubishi: M98, M99, M198
Modal Group / ModalitySubprogram Call and Return Commands
Brands CoveredFanuc, Siemens, Mitsubishi
Critical ParametersFanuc: 3404#2 (SBP), 6001#5/7000#0 (TCS)
Siemens: P (INT), VAR keyword
Mitsubishi: #8876 (M198 device), #8129 (Search priority)
Main ConstraintNesting limits: Max 4 levels (Fanuc), Max 11/16 levels (Siemens), Max 8/10 levels (Mitsubishi). Nested M198 calls on external storage media are prohibited.

Quick Read

  • Modal Reset Action: Consistently restore absolute positioning (G90) and reset any modified modal feeds before exiting a subprogram to prevent catastrophic tool path drifts.
  • Nesting Boundary Constraint: Limit subprogram nesting levels to 4 on Fanuc, 8 to 10 on Mitsubishi, and 11 to 16 on Siemens to avoid interpreter memory overflows.
  • External Storage Call: Program M198 (Fanuc/Mitsubishi) or EXTCALL (Siemens) to execute large programs directly from external memory cards or data servers.
  • Parameter Lock Protection: Lock editing permissions for 8000- and 9000-series macro programs on Fanuc using parameters PRG8 (0389#2) and PRG9 (0010#4) to prevent accidental modification.
  • Alias Customization Decision: Use custom M, S, T, or B codes to automatically alias and trigger background subroutines, such as turret rotation sequences.
  • Siemens Modal MCALL: Apply MCALL in Siemens systems to automatically execute a subprogram at every coordinate position listed in subsequent blocks until deselected.

Basic Concepts

The practical programming effect of a subprogram is the ability to modularize repetitive machining sequences, significantly reducing program file sizes and simplifying future engineering changes. Instead of copying and pasting the exact same geometric roughing passes, slotting routines, or pallet change sequences multiple times in a single large program, developers save these actions as independent, sub-level files. The main program simply calls these subroutines as needed and instantly resumes the main path once the subprogram terminates, allowing clean, streamlined files that consume minimal memory.

Control brands diverge in how they locate, call, and execute these sub-level files. Legacy platforms require strict numeric O-number naming conventions, while modern controls allow descriptive alphanumeric names. Subprograms can also be executed modal-like across different coordinates, or streamed dynamically from external hardware interfaces to bypass internal memory constraints entirely. Because a subprogram executes as an active extension of the calling program, modal states like feedrates and positioning coordinates flow fluidly across levels, requiring strict programming practices to avoid coordinate bleeding.

Command Structure

To call a subprogram, the CNC interpreter must parse a specific command code along with the target program's identifier and the number of repetitions. In standard Fanuc and Mitsubishi environments, the M98 code initiates this jump, transferring control to the program designated by the P address. The controller tracks each iteration of the subprogram using an iteration counter before executing the final return sequence. Upon reaching the end of the subprogram, a return code halts execution in the subroutine and returns the program pointer back to the block directly following the original call instruction.

Siemens controls support a more flexible structure, allowing subprograms to be called directly by their program name or an L address. The definition of a Siemens subprogram can include a PROC header, which defines parameter types and names for transferring values between program levels. The return jump is executed via M17 or RET. In all brands, external calls like M198 or EXTCALL allow streaming from memory cards or network drives. The parameters and syntax addresses govern how the control searches, repeats, and returns from these routines.

Command Syntax Addresses:

  • Fanuc Standard Call: M98 P_ L_ ;
  • Fanuc External Call: M198 P_ ;
  • Fanuc Return: M99 ;
  • Siemens Definition: PROC <program name> (<ParamType> <ParamName>, VAR <ParamType> <ParamName>) [SAVE] [DISPLOF] [SBLOF] [ACTBLOCNO]
  • Siemens Call: <program name> (<Param1>, <Param2>) or L<number> or MCALL <program name>
  • Siemens Return: M17 or RET
  • Mitsubishi Standard Call: M98 P__ H__ L__ ,D__ ; or M98 <file name> H__ L__ ,D__ ;
  • Mitsubishi External Call: M198 P__ L__ ; or M198 <file name> L__ ;
  • Mitsubishi Return: M99 P__ ;
Parameter AddressControl BrandDescriptionValid Settings
PFanuc / MitsubishiSpecifies the target program number to callUp to 8 digits
LFanuc / MitsubishiDetermines the number of times the subprogram repeats1 to 9999 (Default: 1)
HMitsubishiSpecifies the starting sequence block number inside the subprogramSequence code (e.g., H100 matches N100)
,DMitsubishiExplicitly routes the call to a specific physical storage device0 to 4 (mapped via parameters)
<file name>MitsubishiSpecifies an alphanumeric filename inside angle bracketsUp to 32 characters
P (in call)SiemensControls the number of times the program repeats1 to 9999 (e.g., P3)
VARSiemensDeclares call-by-reference parameter transfer in the PROC headerN/A (keyword)
SAVESiemensAutomatically saves and restores active modal G-functions and framesN/A (attribute)
DISPLOFSiemensSuppresses block display on HMI during subprogram executionN/A (attribute)
SBLOFSiemensDisables single-block mode stepping during executionN/A (attribute)

Brand Applications

Fanuc CNC Integration

Fanuc controls support parameter-driven aliases to trigger subprograms. The system can execute background subroutines using parameter 6001#5 (TCS) to map tool calls to program O9000.

Standard subprograms are called via M98, external storage card files via M198, and returned using the M99 command.

Parameter / Alarm / VersionTypeDescriptionSettings / Details
Parameter 0010#4 (PRG9)ParameterDetermines if editing of subprograms O9000 to O9999 is prohibited.0 (not prohibited), 1 (prohibited)
Parameter 0389#2 (PRG8)ParameterDetermines if editing of subprograms O8000 to O8999 is prohibited.0 (not prohibited), 1 (prohibited)
Parameter 3404#2 (SBP)ParameterDictates whether address P in M198 specifies a file number or program number.0 (file number), 1 (program number)
Parameter 3457ParameterSearch folder hierarchy configurations (e.g., user folders, MTB folders, system folders).Bit values
Parameters 6071 to 6079ParameterAssigns specific M-codes to automatically call subprograms O9001 through O9009.3 to 99999999 (excluding reserved M-codes)
Alarm 0076AlarmPROGRAM NOT FOUND: Called program cannot be found in memory or search folders.Check parameter 3457 and verify O-number registration.
Alarm 0077AlarmTOO MANY SUB, MACRO NESTING: Nesting level exceeds limit.Max 4 nested subprograms (8 including macro calls).
Alarm 1080AlarmDUPLICATE DEVICE SUB PROGRAM CALL: Nested M198 call.Avoid calling M198 from inside an active M198 subprogram.
Alarm 1091AlarmDUPLICATE SUB-CALL WORD: Multiple calls in same block.Specify subprogram calls in separate blocks.
Parameter 0001#1 (FCV)VersionLegacy compatibility mode for FS0-TC/FS15-TA tape formats.0 (standard format), 1 (reverts to Series 15 format, merging repeat and P address)

Warning: Failing to reset coordinate offsets or modal positioning (G91) prior to an M99 return command causes coordinate system drift, driving the turret into the vise jaw.

Siemens SINUMERIK Integration

Siemens supports high-level subprogram definitions with local variable scoping. Standard calls use the program name or an L-number, passing parameters directly via the PROC header.

Modal subprogram calls are initiated via MCALL, executing the subprogram after each coordinate block until deselected. Returns use M17 or RET.

Parameter / Alarm / VersionTypeDescriptionSettings / Details
P (INT)ParameterAddress to program the number of subprogram repetitions.1 to 9999
VARParameterDeclares call-by-reference parameters in the PROC header.N/A (keyword)
SAVEAttributeAutomatically saves and restores active modal G-functions and frames.N/A
DISPLOF / SBLOFAttributeSuppresses block display on HMI / disables single-block mode.N/A
Alarm 14011Alarmprogram not existing or will be edited. Called file missing or open on HMI.Close the file on the HMI; check path _N_SPF_DIR.
Alarm 14012Alarmmaximum subroutine level exceeded. Maximum nesting depth surpassed.Check nesting levels.
Alarm 12720Alarmprogram number for macro call (G65/G66) missing in ISO mode.Specify the target program number using the address P.
SINUMERIK 808D vs 828D/840D slVersionHardware tier differences for subprogram nesting levels.808D: 11 levels · 828D/840D sl: 16 levels (18 with ASUBs)
Software Version 5+VersionSafety interlock preventing execution of programs open for editing.Programs open on the HMI cannot be started with NC Start.

Warning: Omitting the SAVE attribute from the PROC line allows modal G-code settings (such as G91) to bleed back into the main program, causing immediate axis crashes.

Mitsubishi CNC Integration

Mitsubishi enables alphanumeric subprogram calls directly in the G-code block. Search priority is configured using parameter #8129 to determine O-number formatting.

Subprograms are invoked using M98 with angle brackets (e.g., <PART.PRG>), and routed to external media using M198 or the ,D address.

Parameter / Alarm / VersionTypeDescriptionSettings / Details
#8876 (M198 pro stor: dev)ParameterSelects the target storage device for subprograms called via M198.G (Hard Disk), R (Memory card), D (Data server), N (USB memory)
#8880 to #8888ParameterSets specific hardware devices mapped to the ,D address (0 to 4).M (Memory), G (HD), R (M-Card), D (Data server), T (Ethernet), F (FLD)
#8129 (Subpro No. select)ParameterDetermines prioritization for searching subprogram numbers.0 (commanded number), 1 (4-digit O-number), 2 (8-digit O-number)
Program Error (P230)AlarmSubprogram nesting over: Maximum nesting depth exceeded.Check nesting limits and data server configurations.
Program Error (P231)AlarmNo sequence No.: Return sequence block or jump destination missing.Verify sequence number matches target in M99 P.
Program Error (P232)AlarmNo program No.: Target file missing or external drive unmounted.Check drive mounting status and filename length (max 32 chars).
M70V/M700V vs M800V/M80VVersionCNC series limits for subprogram nesting levels.M70V/M700V: 8 levels · M800V/M80V: 10 levels
M800VW/M80VW vs M800VS/M80VVersionDefault search device for M198 when parameter #8876 is unset.VW/Type-W: Data Server · VS/Type-S: front-side SD card

Warning: Running an M198 subprogram from an SD card simultaneously on multiple part systems is blocked, triggering immediate execution halts.

Brand Comparison

TopicFanucSiemensMitsubishi
Alphanumeric FilesNo native support; requires strictly O-numbers.Supported natively using program name strings.Supported natively using angle brackets (e.g., <PART-FILE.PRG>).
Repetitive Modal CallBlock-by-block execution or G66 modal macro call.Modal subprogram execution via MCALL <prog>.Block-by-block execution.
Nesting DepthMax 4 nested levels (8 including macros).Max 11 (808D), 16 (828D/840D sl), up to 18 with ASUBs.Max 8 (M70V/M700V), 10 (M800V/M80V).
Storage Media CallM198 P_ streams from card/data server.EXTCALL calls external subprograms.M198 calls from device configured by #8876 or explicit ,D address parameter.
Parameter PassingRequires Custom Macro calls (G65/G66).Supported directly via PROC definition ("call-by-value" and "call-by-reference" via VAR).Requires macro call or variables.

Technical Analysis

An analytical review of these three CNC architectures reveals different approaches to subprogram execution, memory scoping, and parameter transfer. Siemens models its execution on high-level PC programming languages, allowing programmers to define local scopes and parameter passing mechanisms directly in the subprogram header. By using the VAR keyword in the PROC line, Siemens enables call-by-reference execution, allowing subprograms to modify and return calculations to the parent program. Fanuc and Mitsubishi utilize legacy register architectures, requiring macro options like G65 or G66 to transfer values, or forcing programmers to rely on volatile common or global variables, which introduces the risk of modal data corruption.

Nesting hierarchies also reflect distinct hardware philosophies. Fanuc's 4-level nesting limit requires programmers to maintain simplified, shallow call trees. Siemens provides up to 16 to 18 nesting levels, but because these levels are shared dynamically between user subprograms, standard canned cycles, and manufacturer OEM background routines (such as spindle speed clamps or turret control macros), this budget can be quickly depleted. Mitsubishi occupies a middle ground, offering 8 levels on legacy M70V series and 10 levels on newer M80V controls. Exceeding these limits on any control immediately halts execution, demonstrating the necessity of tracing call depths across all active systems.

Directory routing and safety controls differentiate these platforms. Fanuc utilizes parameter 3457 to search a rigid, automated folder hierarchy, while Mitsubishi allows direct physical routing via the ,D address or angle-bracket filenames like <PART.PRG>. Siemens isolates subprogram calls to the local workpiece directory unless an EXTERN declaration is declared. Siemens enforces an HMI edit safety lock (version 5 and higher) that prevents NC Start if the called file is open on the screen, a feature not natively present on Fanuc or Mitsubishi systems.

Program Examples

Fanuc Subprogram Call Example

; Fanuc Subprogram Call Example
O0001 (MAIN PROGRAM) ;
G90 G54 G00 X0 Y0 Z10.0 ; Pre-position axes
M98 P1000 L5 ; Call subprogram O1000 five times
G00 Z50.0 M30 ; Retract and end main program

O1000 (SUBPROGRAM) ; G91 G01 Z-2.0 F150 ; Switch to incremental and feed Z G90 G01 X50.0 F300 ; Switch to absolute and cut to X50.0 G91 G01 Z2.0 ; Incremental Z retract G90 G01 X0 ; Absolute return to X0 M99 ; Return to main program

dry run

When proving the Fanuc code in a dry run, the machine first moves to coordinates X0, Y0, and Z10.0 in absolute mode. When the interpreter reaches the M98 P1000 L5 block, it suspends the main program and jumps to subprogram O1000. In O1000, the controller switches to incremental mode (G91) to feed Z down by 2.0 mm, then reverts to absolute mode (G90) to execute the X-axis feed to 50.0 mm. It performs an incremental retract, returns to absolute X0, and then reads M99. The controller repeats this loop five times before returning to the main program, where it retracts Z to 50.0 mm and terminates via M30.

Siemens Subprogram Call Example

; Siemens Subprogram Call Example
N10 G90 G54 G00 X0 Y0 Z10.0 ; Pre-position axes
N20 MCALL POCKET_CYCLE(3.0, 150.0) ; Modally call POCKET_CYCLE subprogram
N30 X50.0 Y50.0 ; Execute subprogram at coordinate 1
N40 X100.0 Y50.0 ; Execute subprogram at coordinate 2
N50 MCALL ; Deselect modal subprogram call
N60 G00 Z50.0 M30 ; Retract Z and end main program

Note: Below is the subprogram POCKET_CYCLE.SPF saved in the workpiece directory:

PROC POCKET_CYCLE(REAL DEPTH, REAL FEED) SAVE DISPLOF ;
G91 G01 Z=-DEPTH F=FEED ; Incremental plunge
G90 G01 G41 X0 Y0 ; Engage tool radius compensation
G03 X0 Y0 CR=25.0 ; Machine circular pocket
G40 G01 X0 Y0 ; Cancel compensation
G91 G01 Z=DEPTH ; Incremental retract
M17 ; Return to main program

dry run

Proving the Siemens program during a dry run shows the machine first traversing to X0, Y0, and Z10.0. The MCALL command in block N20 registers the POCKET_CYCLE routine modally in the NC memory. The machine does not execute the subprogram on N20, but upon reading block N30 (X50.0 Y50.0), it traverses to the coordinate, pauses, and calls the subroutine. The subroutine runs with the SAVE attribute active, automatically storing the calling program's modal settings. It switches to incremental mode to feed Z down by 3.0 mm, mill a circle, retracts, and reads M17. The controller automatically restores the original modal settings and continues. It repeats this sequence at N40 (X100.0 Y50.0), before block N50 clears the modal state.

Mitsubishi Subprogram Call Example

; Mitsubishi Subprogram Call Example
O0002 (MAIN PROGRAM) ;
G90 G54 G00 X0 Y0 Z10.0 ; Pre-position axes
M98 <POCKET-ROUT.PRG> H200 L3 ,D1 ; Call file POCKET-ROUT.PRG from device 1 starting at block N200
G00 Z50.0 M30 ; Retract and end main program

Note: Below is the subprogram POCKET-ROUT.PRG stored on the CF Card (Device 1):

O2000 (SUBPROGRAM) ;
N100 G01 Z-5.0 F100 ; This block is skipped due to H200 start address
N200 G91 G01 Z-2.0 F120 ; Execution starts here; incremental feed
N300 G90 G01 X30.0 Y30.0 F250 ; Cut absolute profile
N400 G91 G01 Z2.0 ; Incremental retract
N500 G90 G01 X0 Y0 ; Return absolute
M99 ; Return to main program

dry run

During a dry run, the Mitsubishi controller pre-positions the tool at X0, Y0, and Z10.0. When executing the M98 command, the CNC checks device 1 (CF Card), locates the file <POCKET-ROUT.PRG>, and searches for sequence block N200. The interpreter bypasses block N100 completely, starting Z-axis incremental movement at N200. After executing the profile cuts, the tool returns to X0, Y0 in absolute mode. Upon reading M99, the controller returns to the main program, repeating this process three times before ending with M30.

Error Analysis

BrandAlarm CodeTrigger ConditionOperator SymptomRoot Cause / Fix
FanucAlarm 0076Called program number is missing from memory or search folders.The machine halts instantly, showing a PROGRAM NOT FOUND error message.Check parameter 3457 folder path configurations and verify the O-number file exists in local memory.
FanucAlarm 0077Nesting depth exceeds the maximum allowance.The CNC stops mid-cycle, presenting a TOO MANY SUB, MACRO NESTING error.Simplify the program logic. Verify calling levels do not exceed 4 levels (8 including macro calls).
FanucAlarm 1080Nested M198 external device call executed within an active M198 subprogram.Execution freezes and displays a DUPLICATE DEVICE SUB PROGRAM CALL error.Avoid nesting M198 blocks. Copy secondary routines to local SRAM.
FanucAlarm 1091Multiple subprogram call commands programmed in the same block.The interpreter halts and outputs a DUPLICATE SUB-CALL WORD error.Isolate each subprogram call command into its own block.
SiemensAlarm 14011Called subroutine is missing, unreleased, or open for editing.The controller halts execution, displaying a program not existing or will be edited message.Close the file on the HMI to release the editing lock. Verify path in _N_SPF_DIR.
SiemensAlarm 14012Nesting depth limit is exceeded.The system stops with a maximum subroutine level exceeded message, disabling NC Start.Review the calling tree. Reduce nested cycles or OEM macros like Turret3_CODE_T.
SiemensAlarm 12720ISO mode macro call executed without defining program number via P.The control rejects the command, showing a program number for macro call missing error.Specify the target program number using address P.
MitsubishiError P230Nesting level exceeds capacity, or nested M198 data server calls executed.The control halts and displays a Subprogram nesting over error.Review nesting levels. Limit calls to 8 (M70V/M700V) or 10 (M800V/M80V).
MitsubishiError P231Specified return block (M99 P) or jump destination is missing.Interpreter faults out, displaying a No sequence No. error.Ensure the sequence number programmed after P exists in the target program.
MitsubishiError P232Called file is missing, drive is unmounted, or name exceeds 32 characters.Execution stops, showing a No program No. error.Mount external media securely, check file names, and keep character counts under 32.

Application Note

An uncommanded turret or spindle collision that shatters tooling and scraps expensive workpieces is the direct result of failing to protect modal positioning states and nesting budgets during subprogram execution. In Siemens environments, omitting the SAVE attribute on the PROC statement of a custom cycle allows a temporary coordinate shift like G91 (incremental positioning) to bleed back into the parent program. When the controller jumps back to the main path via M17, it executes subsequent commands relative to the last subprogram coordinate instead of absolute G90 positions. The operator sees the axis wander off-path and crash into a clamp or vise jaw. On Fanuc controls, failing to protect parameters 0010#4 (PRG9) and 0389#2 (PRG8) allows operators to accidentally overwrite background macros, causing subsequent turret indexes to fail or execute incorrect tooling profiles. To secure operations, programmers must lock editing permissions for 8000- and 9000-series subprograms, ensure all subprograms contain explicit modal restoration blocks, and trace nesting levels to prevent buffer overflows.

Related Command Network

  • G65 Simple Macro Call: Initiates a single, non-modal call to a subprogram while allowing direct passing of local variables to macro registers.
  • G66 Modal Macro Call: Instructs the CNC interpreter to execute a designated macro subprogram automatically after every subsequent motion block until canceled.
  • G645 Tolerance-Based Smoothing: Regulates contour smoothing tolerances during high-speed machining, which must be carefully coordinated with subprogram feedrates to prevent chordal errors.
  • G68.2 Inclined Surface Control: Establishes tilted working plane coordinates for multi-axis machining, requiring correct coordinate mapping prior to executing subprogram loops.
  • Mitsubishi High-Speed Control III (G05 P20000): Activates advanced look-ahead path buffering for micro-segment processing, which must be programmed in a standalone block separate from subprogram calls to prevent command conflicts.

Conclusion

Developing a standardized subprogram programming checklist is the most effective way to eliminate coordinate drift and nesting alarms. Programmers should establish a habit of placing absolute coordinate restoration commands (G90) and compensation cancels (G40, G49) immediately before any return block (M99 or M17). Isolating external storage media calls, verifying hardware-specific nesting limits, and locking editing parameters for macro libraries will ensure stable, crash-free automated production runs.

Frequently Asked Questions

Why does a subprogram cause coordinate shifts in the main program?

This coordinate drift occurs because modal commands, such as incremental positioning (G91) or tool length compensation adjustments, bleed across program boundaries if they are not explicitly canceled. When the subroutine returns control, the parent program continues using these modified modal states instead of the original parameters. Practical Action: Place a modal reset block containing G90 and any active compensation cancel codes immediately before the M99 or M17 return block.

How can we prevent operators from modifying or deleting critical subprograms?

Critical routines, such as tool changers or probe macros, are usually stored in the 8000- and 9000-series program numbers. Failing to lock editing permissions allows unauthorized changes that can result in spindle crashes. Practical Action: On Fanuc systems, set parameter 0010#4 (PRG9) to 1 to lock 9000-series programs, and parameter 0389#2 (PRG8) to 1 to lock 8000-series programs.

What is the difference between call-by-value and call-by-reference parameter passing?

Call-by-value passes a copy of a variable's value to the subprogram, meaning any changes made inside the subroutine do not affect the main program's variable. Call-by-reference (using the VAR keyword in Siemens) passes direct access to the variable's memory address, allowing the subprogram to overwrite and return the new value. Practical Action: Use VAR in the PROC definition line only when you want the subprogram to update and return modified parameters to the main program.

Still not resolved?

Ask our AI assistant about this topic in natural language. Grounded in verified sources, no hallucinations.

Ask AI Assistant
Hakan Gündoğdu
Hakan Gündoğdu
  • CNC CARE Co-Founder (May 2025 - Present)
  • Mitsubishi Electric NC Sales & Service Section Manager (2008 - 2025)
  • Reis CNC Service Engineer (2003 - 2005)
  • Ören Kalıp CNC Mold Line Team Leader (1999 - 2002)

With over 25 years of experience working in all areas of the CNC machine industry, I continue my activities as a co-founder of CNC CARE, where we offer brand-independent consulting, engineering, and original spare parts services.

Related Articles

Other articles on this topic