Migrating S5 OB181 LIR TIR BS Instructions to S7 STEP 7

David Krause20 min read
S7-300SiemensTechnical Reference
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Migrating S5 OB181, LIR, TIR, and BS Instructions to S7 STEP 7

When migrating legacy SIMATIC S5 programs—particularly those originally written for the S5-135U or S5-155U chassis with CPU 928, CPU 928B, or CPU 948—engineers frequently encounter low-level S5 operations that have no direct one-to-one S7 equivalent. The instruction set OB181, LIR, TIR, and the BS operand are the most common pain points because they manipulate the S5 interpreter stack, the base address register, and absolute memory. This reference documents the exact semantics of each instruction as defined in the original S5-135U/155U operation list, maps them to the equivalent S7 STEP 7 (TIA Portal or STEP 7 V5.x) constructs, and provides STL/SCL code blocks ready for direct integration into a converted project.

1. Migration Context and Tool Chain

The official Siemens STEP 7 – From S5 to S7 manual describes a two-phase migration: (1) an automatic conversion pass that translates S5 STL/FBD into S7 STL, and (2) a manual rework phase that resolves instructions the converter cannot handle. The conversion tool is delivered as a STEP 7 optional package and produces S7 source files in STL text format that can be opened in either the classic STEP 7 V5.x SIMATIC Manager or, after re-export, in the TIA Portal.

Reference: STEP 7 – From S5 to S7 (Siemens, manual entry ID 45531547) and the SIMATIC S5 to S7 Migration / Renewal Manual.

The automatic converter flags unknown operations as syntax errors and stops the translation. OB181, LIR, TIR, and BS are listed in the converter's "manual rework required" category, along with DO DW, DI, DX, STS, DO, DO DW, ADD BF, ADD BN, ADD BT, SUB BF, SUB BN, and SUB BT (BCD floating-point operations on the S5-135U/155U).

2. S5-135U/155U Instruction Set Background

All four instructions discussed here belong to the extended operation set of the S5-135U and S5-155U. The S5-115U does not support them. They are documented in the S5-135U/155U CPU 928 / 928B / 948 – List of Operations manual and the S5-135U/155U List of Operations (Siemens manual 6ES5 998-0PR02). The CPU 928B was the first S5 CPU to add the floating-point coprocessor operations, and CPU 948 added extended bit and word addressing plus higher interrupt response. If your source program contains LIR or TIR, the original target CPU is almost certainly a 928B or 948.

Critical identification step: Before attempting the conversion, open the S5 program in the original SIMATIC S5 STEP 5 editor and record the CPU model (CPU 928, 928B, or 948), the AG (automation unit) number, and the firmware version. The S7 replacement (S7-300 with CPU 315-2 DP/PN, S7-400, or ET 200S as I/O replacement) must be sized to handle the scan time and work-memory footprint of the original S5 program.

3. OB181 — Test Data Block in S5

3.1 Original S5 Semantics

OB181 is a system-level organization block invoked by the S5 operating system to verify the structure of a data block. It is not a user-callable OB in the same sense as OB1; it is invoked either by a DB/DX open with structure check enabled, or by the S5 test/debugger. The OB receives the DB number in ACCU 1 and the DL/DL stack base address; it must return a status word indicating whether the DB is valid, locked, or corrupted.

On the CPU 928/928B/948, the OB181 stub occupies 32 words of code and is supplied by Siemens as part of the standard firmware. The S5 user never edits OB181 directly; the S5 converter carries the call reference into the S7 program, but the target block has no meaningful behavior because the S7 data block model is different.

3.2 S7 Replacement Strategy

The S7 data block model uses a flat memory area managed by the system; there is no need for a periodic structure test because the S7 block headers contain CRC checksums and length fields that the S7 OS validates on every download and on every cold restart (OB100). The conversion tool replaces the S5 DB n open with the S7 OPN DB [n] or OPN DI [n] instruction, and the S5 DX n open with the S7 OPN DI [n] instruction (instance DB in S7).

If the original S5 program called OB181 as a deliberate runtime check (for example, to validate a DB number received via a peripheral input), the equivalent S7 logic is:

  1. Read the candidate DB number into a temporary variable (DWORD).
  2. Use L DB# with the ANY pointer to test the block existence via SFC 24 / SFC 6 / SFC 7.
  3. Branch on the returned error code.

3.3 STL Replacement for Runtime DB Validation

// S7 STL – runtime DB existence check (replaces OB181 test logic)
      L     #iCandidateDBNum       // INT in, candidate DB number (1..32767)
      L     1                      // lower bound
      <I                            // ACCU2 < ACCU1 ?
      JC    _ERR_RANGE             // -> DB number too low
      L     32767
      >I                            // ACCU2 > ACCU1 ?
      JC    _ERR_RANGE             // -> DB number too high

      // Open the DB; S7 OS will set BR if the block is loaded and valid
      OPN   DB [#iCandidateDBNum]  // S7 raises OB121 if DB does not exist
      AN    OV                     // BR / OV check
      JC    _ERR_LOAD              // branch if load failed

      // Successful open; continue
      SET
      SAVE
      JU    _OK

_ERR_RANGE:
      CLR
_ERR_LOAD:
      SAVE
      // ACCU1 LSB = 0 on error, = 1 on success (binary result)
_OK:  NOP   0

The above replaces the S5 idiom DB n followed by an implicit OB181 invocation. The OB121 (programming error) handler installed by the user program can catch the absence of a DB and route the error to the S7 diagnostic buffer; this is the S7 analogue of the S5 "DB does not exist" signal that OB181 would have returned.

Tip: If the S5 program deliberately used OB181 to identify whether a DB had been overwritten by an online programming operation, replace that logic with a CRC check on the DB's first 16 bytes using the S7 standard FC "CRC16" (Siemens example code) or a custom FC. The S7 block check via the SFC 24 ("TEST_DB") is the direct functional replacement.

4. LIR — Load Register Indirect (S5)

4.1 Original S5 Semantics

The S5 LIR instruction reads a 16-bit word from the absolute memory address contained in ACCU 1. The address is a flat byte address that can point to any memory region: PII (process image input), PIQ (process image output), flags (M), timers (T), counters (C), data (D), or system memory (S). The loaded word is placed into ACCU 1-L (low word) while ACCU 1-H is cleared. The address in ACCU 1 is interpreted as a flat 16-bit address with the most significant bit pattern selecting the memory area according to the S5 addressing scheme:

Table 1 — S5 flat-address space map (CPU 928/928B/948)
Address range (hex) Memory area S7 equivalent
0000h–FFFFh (bottom 32K) Data blocks (DB/DX) DBB/DBW/DBD by OPN DB [n]
0000h–7FFFh (PA range, bits 15=0,14=0) Process I/O (PII / PIQ) PIB/PIW/PID direct peripheral
8000h–FFFFh (flag area, bits 15=1,14=0) Flags (M) MB/MW/MD
E000h–E7FFh Timers (T) T (word access requires T 0..n, LW)
E800h–EFFFh Counters (C) C (word access requires C 0..n, LW)
F000h–FFFFh System memory (S) No S7 equivalent – recreate semantically

The S5 LIR instruction does not check that the address is in a valid range. If the address points to an unused region, the CPU returns 0000h. There is no error bit set. This silent fail behaviour is one of the most common sources of latent S5 program bugs and must be explicitly addressed when migrating.

4.2 S7 Replacement — Area-Internal Pointer

In S7 STEP 7, the equivalent operation is performed with the area-internal pointer (POINTER) or the ANY pointer together with the S7 indirect addressing modes. The most direct S7 replacement for LIR where the address lies inside a known DB is the L DBW [MD0] or L DBB [MD0] instruction with the byte offset held in a memory double word. For area-crossing access (S5 could point at M, T, C, S, or D from one instruction), the S7 replacement uses the area-crossing pointer combined with L W [AR1,P#0.0] or, in SCL, the PEEK / POKE functions from the IEC library.

4.3 STL Replacement for S5 LIR (DB area)

// S5 original
      L     DB  100                // load DB number into ACCU 1 (later bound to address)
      LIR                               // load word at ACCU1 address into ACCU1-L
// (conceptual; LIR consumes the address in ACCU1 directly)

// S7 STL replacement for "load word from DB offset = MW 100"
      OPN   DB [MW100]              // open DB whose number is in MW100
      L     MW 102                  // load byte offset
      SLD   3                       // shift to pointer form (P#x.0)
      LAR1                            // ACCU1 -> AR1
      L     DBW [AR1,P#0.0]         // load the word from DB[MW100] at byte offset MW102

4.4 STL Replacement for S5 LIR (cross-area)

// S7 STL – cross-area read (replaces S5 LIR when source could be M, T, C, or D)
      L     #iAddressWord           // INT input = raw S5 address (0..65535)
      L     0                       // clear ACCU1-H
      T     #dwAddress              // store as DWORD
      TAR1  #arSave1                // save AR1 (S7 allows one AR1 only)
      LAR1  #dwAddress              // AR1 = address
      L     W [AR1,P#0.0]           // area-crossing word read
      T     #wResult                // result word
      LAR1  #arSave1                // restore AR1

Note that the S7 L W [AR1,P#0.0] instruction will raise OB121 (programming error) if the address falls in a region that is not valid for the S7-300/400 memory map (for example, an attempt to read from an empty slot in the S5 address space). Wrap the access with an OB121 error handler if the original S5 code relied on the silent-zero fallback of LIR.

5. TIR — Transfer Register Indirect (S5)

5.1 Original S5 Semantics

TIR is the dual of LIR. It writes the contents of ACCU 1-L (a 16-bit word) to the absolute memory address contained in ACCU 1 at the time TIR executes. The standard S5 idiom is:

      L     W#16#0F00           // example: pointer to flag area + offset 0
      L     MW 200              // value to write
      TIR                          // MW200 -> memory at ACCU1's previous address

The address in ACCU 1 is replaced by the written value; the value previously pointed to is overwritten. Like LIR, the instruction performs no range check.

5.2 S7 Replacement

The S7 equivalent uses T DBW [...], T MW [...], or the area-crossing T W [AR1,P#0.0]. For dynamic DB selection, combine OPN DB [MW_n] with a byte-offset pointer. The conversion rule is:

  1. Determine the target S7 area from the S5 address (use Table 1 above).
  2. Strip the area selector bits; the remaining low-order bits become the byte offset within that area.
  3. For the DB area, pre-open the DB with the desired DB number; for M, T, C, S use the corresponding S7 area directly.
  4. Emit the S7 store instruction with indirect addressing.

5.3 STL Replacement for S5 TIR

// S7 STL – cross-area write (replaces S5 TIR)
      L     #iAddressWord           // S5 raw address
      T     #dwAddress
      L     #wValue                 // value to write
      TAR1  #arSave1
      LAR1  #dwAddress
      T     W [AR1,P#0.0]
      LAR1  #arSave1

Wrap with an OB121 handler if the original S5 code expected the write to be silently ignored on invalid addresses.

6. BS — Base Address Register (ISTACK)

6.1 Original S5 Semantics

The S5 instruction-set identifier BS refers to the "Basisadressregister" (base address register). It is not a stand-alone instruction; it appears as a source operand on a load instruction to read the base address register content from the S5 interrupt stack (ISTACK). The ISTACK stores the call-context data of the currently executing block, including:

  • The block header address (BA, Basisadresse).
  • The block return address (BR, Ruecksprungadresse).
  • The DB number and the current DL/DR pair (data word offset).
  • The status word of the calling block.

The typical S5 sequence that reads BS looks like:

      L     BS 34           // load the BS-offset 34 from the ISTACK into ACCU 1
      T     MW 200

On the CPU 928/928B/948, the ISTACK occupies a fixed memory area in the system RAM, and offset 34 corresponds to the data block (DB/DX) number that was active at the point of the call. The exact mapping of offsets to ISTACK fields is CPU-specific; refer to the S5-135U/155U CPU 928B/CPU 948 – List of Operations manual, chapter "ISTACK structure".

6.2 S7 Replacement — L Stack and Local Data

The S7 operating system maintains the equivalent of the S5 ISTACK in the L stack (Lokaldaten-Stack) of each OB and the block call chain. The S7 information that maps to the S5 BS offsets is:

Table 2 — S5 BS offset to S7 mapping
S5 BS offset (CPU 928B/948) ISTACK content S7 equivalent
0–1 Block type / block number Block type from OB/FB/FC header; use SFC 6 / SFC 7
2–3 Return address (block-relative) Not directly exposed; use SFC 35/36/37 for interrupt control
34 Active DB number (last OPN DB) No direct instruction; query via SFC 24 "TEST_DB" or maintain own variable
36 Active DI number (last OPN DI) Same as above; instance DB
40 Status word at call time Read via STW / SAVE / CLR; not stack-restorable in S7

6.3 S7 Replacement Pattern

Because the S7 operating system does not expose the L-stack as a readable memory area, the canonical S7 replacement pattern is to capture the equivalent context at the time the block is called and pass it as IN/IN_OUT parameters on the FB/FC interface. The S7 FB becomes self-contained and the dependency on stack state is removed.

// S7 FB interface (replaces BS-offset 34 reads inside an FB/FC)
FUNCTION_BLOCK FB_DBContext
VAR_INPUT
    iCallSource   : INT;   // caller identifier (0=OB1, 1=OB35, etc.)
END_VAR
VAR
    sDiag         : STRUCT
        dbNum   : INT;     // mirrors active DB at call
        diNum   : INT;
        stw     : WORD;    // status word at call
    END_STRUCT;
END_VAR
BEGIN
    // Save the caller's DB context into instance fields
    sDiag.stw := STW;                          // current status word
    sDiag.dbNum := DB_NUMBER;                  // requires SFC 24 in SCL
    // ...
END_FUNCTION_BLOCK

To make the migration auditable, store the BS-replacement fields in the FB's instance DB; this keeps the diagnostic data available to HMI / WinCC via the standard tag list. If the original S5 program was reading BS for error reporting (e.g., before transitioning to STOP), the S7 equivalent is to populate the OB1x error OBs (OB80 through OB87) with the equivalent SFC 6 / SFC 7 reads of the local-data area at the time of the fault.

7. Step-by-Step Migration Procedure

7.1 Prerequisites

  • STEP 7 V5.5 SP4 or later (or TIA Portal V15.1+ for the re-export path).
  • The official "S5 to S7 Converter" optional package installed under SIMATIC Manager.
  • Manual "S5-135U/155U CPU 928/928B/948 List of Operations" for reference.

7.2 Procedure

  1. Identify the original S5 CPU. Open the S5 program header in STEP 5 and confirm the CPU model. Record the firmware version if the hardware is still in operation.
  2. Run the S5-to-S7 converter. From SIMATIC Manager, choose Options > S5 to S7 Converter. Select the source S5 program, the target S7 project, and the mapping rules. Click "Convert". The tool produces a S7 project with a conversion report listing all operations that require manual rework.
  3. Open the conversion report. The report file S5_to_S7.LOG lists every line that failed automatic conversion. Locate OB181, LIR, TIR, and BS references; they will be flagged as NOT_CONVERTED with the source line number.
  4. Replace OB181 calls. For each call to OB181, decide whether the S5 program used the OB as a runtime DB test or as a debugging hook. In runtime tests, replace with the STL pattern in section 3.3. In debug-only references, simply delete the call; the S7 OS validates DBs at download time.
  5. Replace LIR and TIR instructions. For each occurrence, classify the target S5 address by the table in section 4.1. Apply the STL pattern from section 4.4 (cross-area) or section 4.3 (DB-internal). Update the surrounding logic to clear the result word before the call (the S5 LIR always returned a word, but if the load failed the ACCU1-L was 0000h — S7 will leave the prior value untouched on an OB121).
  6. Replace BS reads. For each L BS nn instruction, identify which ISTACK offset is being read. Substitute the corresponding FB instance field or a local temporary initialized at block entry. If the read was part of an error handler, route the diagnostic data to the appropriate OB80–OB87.
  7. Re-compile in STEP 7. Use the "Check block consistency" tool to verify all blocks compile. The S7 compiler will flag any unresolved references with line numbers.
  8. Download to the S7 CPU. Use a S7-300 CPU 315-2 PN/DP, S7-400, or ET 200S with adequate work memory. Confirm the CPU is in STOP before download.
  9. Verify the migration (see section 9).

8. Worked Example — Migrating FB175 Caller to OB181

The original S5 program (as reported in the field report) contained the call pattern:

// S5 source (illustrative)
      L     DB   100
      LIR                            // load word from absolute address in ACCU1
      T     MW   202
      L     DB   200
      TIR                            // write MW204 to absolute address in ACCU1
      L     BS   34                  // read active DB from ISTACK
      T     MW   206
      SPA   OB 181                   // call system OB to validate DB structure

After conversion, the S7 STL equivalent is:

// S7 STL — migrated body of the original S5 routine
      OPN   DB  100
      L     DBB  0                   // equivalent of LIR at offset 0
      T     MB     203
      OPN   DB  200
      L     MW     204
      T     DBB  0                   // equivalent of TIR at offset 0
      CALL  SFC  24                  // TEST_DB – equivalent of OB181 runtime check
      L     DB#    200
      T     MW     206               // store returned DB number
      L     W#16#0
      ==I                            // TEST_DB returns "DB does not exist" = 0
      JC    ERR_DB200
      // ... success path ...
ERR_DB200:
      // S7: raise OB121 via "L DW#16#0 / T DBW 0" on a non-existent DB
      L     DB#    32766
      OPN   DB  [MW206]              // forces OB121 if DB# is not loaded

9. Verification

Verification of a migrated S5/S7 program combines a static analysis pass, a dynamic test pass on the target CPU, and a long-duration soak test to expose the S5 LIR/TIR silent-zero cases that no off-line tool can detect.

9.1 Static Analysis Checklist

  • All LIR / TIR sites have a corresponding S7 cross-area or DB-internal replacement.
  • No call to OB181 remains in the S7 source (other than the documented runtime pattern using SFC 24).
  • No L BS nn instructions remain; equivalent state is stored in the FB instance DB.
  • OB121, OB80, OB85, OB121, and OB122 error handlers are installed in the S7 program.

9.2 Dynamic Test on the S7 CPU

  1. Force the CPU to RUN-P (run with programming device attached). Open the S7 diagnostic buffer and confirm no OB80–OB87 entries appear after a 10-minute idle period.
  2. Use a watch table to force the DB number used in the runtime-DB test to 0 and to 32767; verify the SFC 24 returns the expected error code and the OB121 handler routes the fault to the HMI.
  3. For each LIR/TIR replacement, force the address high word to a non-existent area selector and confirm the OB121 path is exercised.
  4. Compare the cyclic I/O image against the S5 program reference trace for at least 1000 scans.

9.3 Soak Test

Run the migrated program for a minimum of 24 hours with the original S5 test vectors replayed at the digital and analog I/O level. Capture every OB entry and every PLC stop event. The acceptance threshold is zero unjustified OB entries (OB1x raised for reasons that the original S5 program did not produce).

10. Common Pitfalls and Edge Cases

10.1 The Silent Zero

S5 LIR returned 0000h on an out-of-range address without setting any status flag. S7 raises OB121 on a similar access. If the original S5 program depended on the silent zero, the S7 program must explicitly handle the OB121. A common bug is a LIR whose address pointer was momentarily uninitialized during startup; the S5 program would read 0, the S7 program will raise OB121 and the CPU will go to STOP if OB121 is not loaded.

10.2 Cross-Area Pointer Truncation

S5 LIR/TIR operated on a 16-bit address. S7 cross-area instructions use a 32-bit pointer (DWORD). When migrating, the 16-bit S5 address must be sign-extended or zero-extended to 32 bits depending on whether the original S5 program treated the top bit as a flag-area selector. Inspect the original S5 source for any conditional logic on bit 15 of the address; if present, the S7 code must reproduce that conditional bit-test.

10.3 BS Offset 34 Active DB

The S5 BS offset 34 reads the active DB number. In S7, after an OPN DB [MW_n], the S7 OS internally tracks the active DB but does not expose it as a readable register. Two practical approaches: (a) maintain a shadow variable updated every time OPN DB [...] is executed, or (b) use SFC 24 (TEST_DB) to look up a specific DB number. Approach (a) is faster, approach (b) is more robust against missed updates.

10.4 L Stack Depth in S7

The S7 L stack is sized per OB; an OB that calls many nested FBs may run out of L stack if the S5 program used BS reads at deep call depths. The S7 configuration tool warns about L stack overflow at the block compile step. Increase the L stack size in HW Config > CPU Properties > Local Data, or flatten the call chain.

10.5 OB181 Default Behaviour in S5

If the original S5 program did not load a custom OB181 and relied on the Siemens default, no further action is required; the default behaviour is to validate the DB and return without side-effect, which is now provided automatically by the S7 OS. If the original S5 program overrode OB181 with custom code, the S7 replacement must reproduce the custom logic in a user-installable FC and call it explicitly.

11. Replacement CPU Selection

The S5-135U/155U program target was almost always a CPU 928, 928B, or 948. The recommended S7 replacements are:

Table 3 — CPU migration map for S5-135U/155U
S5 CPU Recommended S7-300 CPU Recommended S7-400 CPU Notes
CPU 928 CPU 315-2 PN/DP (6ES7315-2EH14) CPU 412-2 PN (6ES7412-2EK06) Standard scan time, 256 KB work memory
CPU 928B CPU 317-2 PN/DP (6ES7317-2EK14) CPU 414-3 PN/DP (6ES7414-3EM06) Floating-point heavy, 1 MB work memory
CPU 948 CPU 319-3 PN/DP (6ES7318-3EL01) CPU 416-3 PN/DP (6ES7416-3ES06) Bit-heavy, 2 MB work memory, multi-rack

For the I/O side, the S5-135U/155U rack was typically replaced with an ET 200S or ET 200SP distributed I/O station; the S5 IM 300/IM 310 interface modules are replaced with PROFIBUS or PROFINET masters. The Siemens migration manual "SIMATIC S5 to S7 Renewal" (see the additional research) provides rack-by-rack replacement tables.

12. Standards and References

What does the S5 instruction LIR do, and what is its S7 STEP 7 equivalent?

The S5 LIR instruction loads a 16-bit word from the absolute memory address contained in ACCU 1. In S7 STEP 7, the equivalent is a cross-area word read using a pointer in AR1, e.g. L W [AR1,P#0.0] after loading the byte offset into AR1. For DB-internal access, use L DBW [MD_offset] inside an opened DB.

How do I replace the S5 OB181 "Test Data Block" call in a S7 program?

For runtime DB validation, replace OB181 with SFC 24 (TEST_DB), which returns a status word indicating whether the DB is loaded, valid, or absent. If the S5 program invoked OB181 only for the S5 debugger, delete the call; the S7 OS validates DBs at download time. Wrap the access with an OB121 handler if the original code relied on the S5 silent-zero fallback.

What is the S5 BS operand and how do I migrate L BS 34 to S7?

BS reads a field from the S5 interrupt stack (ISTACK). BS offset 34 holds the active DB number. The S7 operating system does not expose the L stack as a readable memory area; maintain a shadow variable updated on every OPN DB, or query the DB number via SFC 24 (TEST_DB). Store the value in the FB instance DB for HMI diagnostics.

Why does my migrated S7 program raise OB121 on addresses the S5 program accepted?

S5 LIR and TIR return 0 silently on out-of-range addresses. S7 raises OB121 (programming error) on out-of-range cross-area access. Install an OB121 error handler that sets a diagnostic flag and continues, matching the S5 silent-zero behaviour. Without OB121 the CPU will go to STOP on the first bad access.

Which Siemens S7 CPU should I use to replace a S5-135U/155U CPU 928B?

For a S5-135U/155U CPU 928B replacement, use a SIMATIC S7-300 CPU 317-2 PN/DP (6ES7317-2EK14) for compact applications, or a S7-400 CPU 414-3 PN/DP (6ES7414-3EM06) for rack-distributed plants. Verify the work-memory footprint of the migrated S7 program does not exceed the CPU's load memory and work memory specifications.

Back to blog