0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GX Works3のコンパイラの動作を見てみよう

0
Last updated at Posted at 2026-10-21

GX Works3でラベルやFBを使うとコンパイルしたコードが実行されます。
ではどのようなコードに変換されるのでしょうか。

コンパイルされたコードを見る方法

GX Works2ではこのようにしてコンパイル後のデータを観測することができます。

ではGX Works3の場合はどうやって見ることができるのでしょうか。

まずSTやFBでプログラムを書いてコンパイルします。

この説明ではFB/FUNともにわかりやすいように、下記のような回路にしています。
IN1 + IN2 = OUT3をするだけです。
image.png

MAINではこのように呼び出しています。
image.png

GX Simulator3に転送して実行します。
GX Works3とGX Simulator3でプログラムの比較を行います。

比較するとこのような画面になります。
ここで見るのはプログラムファイル、FBファイル、FUNファイルです。

スクリーンショット 2026-10-21 170941.png

下記はプログラムファイルの場合です。

スクリーンショット 2026-10-21 173854.png

FBのコンパイル結果
スクリーンショット 2026-10-21 173909.png

FUNのコンパイル結果
スクリーンショット 2026-10-21 173919.png

LFBCALL、FUNCALLのような、普段のラダーでは見かけない命令が出てきます。
LV:xxはローカルラベルの領域を表す表示です。

FBの場合は入力値をインスタンスのラベル領域に書き込み、LFBCALLで本体を呼び出します。演算後は出力ラベルの値を読み出します。
FUNの場合は入力値をTMP領域に書き込み、FUNCALLで本体を呼び出します。戻ってきたらTMP領域から出力値を読み出します。

インスタンスの有無で何が変わるのかというと、インスタンスがあると値をFBごとに記憶することができます。
例えばFBではタイマー、カウンター、パルス、自己保持を利用することができ、演算結果の記憶をすることが可能です。FBごとに専用の記憶エリアをシステムが割り当ててくれるからです。
一方FUNにはインスタンスがなく、入力値で演算して結果を返します。FUN内のローカルラベルの値は、次の呼び出しには保持されません。

なおマニュアルにはインスタンスに何が含まれどういう配置かまで詳しく書かれています。
SH-081225 MELSEC iQ-R プログラミングマニュアル(プログラム設計編)
image.png

FBのマクロ型・サブルーチン型

上記の例はFBをサブルーチン型でコンパイルしています。そもそもマクロ型・サブルーチン型とはなんでしょうか。

No03_v003_01_draft.png
No03_v003_02_draft.png

サブルーチン型ではFBFILEにFBの本体を格納して呼び出します。マクロ型では呼び出し元に同じロジックを埋め込みます。では確認してみましょう。

image.png

FBのコンパイル結果
image.png

FUNのコンパイル結果
image.png

FBFILEから対象のFBのロジックが消え、呼び出し元に演算するロジックが埋め込まれていることがわかります。
FUNにはFBのようなマクロ型への切り替えがないため、変わりません。

どちらを選ぶべきか

同じFBを何か所も呼び出す場合、サブルーチン型では本体を共用できるため、プログラムメモリを節約しやすくなります。またMX-Rの場合はサブルーチン型しか選べません。
また、マクロ型で下記のようにFB外から引数ラベルを直接参照すると、意図した値を読めない場合があります。FB外で値を使う場合は、引数に接続した実デバイスやラベルを参照します。サブルーチン型では下記のような使い方でも正しく動作します。

SH-081225 MELSEC iQ-R プログラミングマニュアル(プログラム設計編)
image.png

STはどのようにコンパイルされるのか

下記のようなコードをFBに貼り付けて呼び出します。

(* ===== 代入・算術演算 ===== *)
D0 := 2;
D1 := 10;

D2 := D1 + 3;
D3 := D1 - 3;
D4 := D1 * 3;
D5 := D1 / 3;       // 整数同士なので結果は3
D6 := D1 MOD 3;     // 余りは1


(* ===== 比較・論理演算 ===== *)
M0 := (D1 >= 5) AND (D1 < 20);
M1 := NOT M0;
M2 := M0 OR M1;


(* ===== IF / ELSIF / ELSE ===== *)
IF D1 < 0 THEN
    D7 := -1;
ELSIF D1 = 0 THEN
    D7 := 0;
ELSE
    D7 := 1;
END_IF;


(* ===== CASE:単一値・複数値・範囲 ===== *)
CASE D0 OF
    0:
        D8 := 100;
    1, 2:
        D8 := 200;
    3..5:
        D8 := 300;
ELSE
    D8 := -1;
END_CASE;


(* ===== FOR:1~5を加算 ===== *)
D20 := 0;

FOR D10 := 1 TO 5 BY 1 DO
    D20 := D20 + D10;
END_FOR;
// D20 = 15


(* ===== WHILE:条件を先に判定 ===== *)
D11 := 0;

WHILE D11 < 3 DO
    D11 := D11 + 1;
END_WHILE;
// D11 = 3


(* ===== REPEAT:処理後に終了条件を判定 ===== *)
D12 := 0;

REPEAT
    D12 := D12 + 1;
UNTIL D12 >= 3
END_REPEAT;
// D12 = 3


(* ===== EXIT:ループを途中で抜ける ===== *)
D21 := 0;

FOR D13 := 1 TO 10 BY 1 DO
    IF D13 > 3 THEN
        EXIT;
    END_IF;

    D21 := D21 + D13;
END_FOR;
// D21 = 6


(* ===== 関数呼出し ===== *)
D30 := ABS(-10);
// D30 = 10


(* ===== RETURN:現在の処理を終了 ===== *)
D31 := 0;

IF D0 = 2 THEN
    RETURN;
END_IF;

D31 := 999;         // この例では実行されない

IN/OUTも消しています。
image.png

MAINはこれだけになります。
image.png

FBのコンパイル結果
image.png

NOP K4
STPUSH
_TMALLOC H57

(* ===== 代入・算術演算 ===== *)
LD SM400
MOV K2 D0
MOV K10 D1
+ D1 K3 D2
- D1 K3 D3
* D1 K3 TMP:48
MOV TMP:48 D4
/ D1 K3 TMP:48
MOV TMP:48 D5
/ D1 K3 TMP:48
MOV TMP:49 D6

(* ===== 比較・論理演算 ===== *)
LD>= D1 K5
OUT TMP:56.0
LD< D1 K20
OUT TMP:55.0
LD TMP:56.0
AND TMP:55.0
OUT M0
LD SM400
CMLB M0 M1
LD M0
OR M1
OUT M2

(* ===== IF / ELSIF / ELSE ===== *)
LD SM400
IF
	LD< D1 K0
	OUT TMP:56.0
	LD TMP:56.0
THEN
	MOV K-1 D7
ELSIF
	LD= D1 K0
	OUT TMP:55.0
	LD TMP:55.0
THEN
	MOV K0 D7
ELSE
	LD SM400
	MOV K1 D7
ENDIF

(* ===== CASE:単一値・複数値・範囲 ===== *)
LD SM400
CASE
	MOV D0 TMP:51
CASEOF
CASEIF
	LD= TMP:51 K0
	OUT TMP:56.0
	LD TMP:56.0
CASETHEN
	MOV K100 D8
CASEIF
	LD= TMP:51 K1
	OUT TMP:55.0
	LD= TMP:51 K2
	OUT TMP:56.0
	LD TMP:55.0
	OR TMP:56.0
	OUT TMP:54.0
	LD TMP:54.0
CASETHEN
	MOV K200 D8
CASEIF
	LD<= K3 TMP:51
	OUT TMP:55.0
	LD<= TMP:51 K5
	OUT TMP:56.0
	LD TMP:55.0
	AND TMP:56.0
	OUT TMP:54.0
	LD TMP:54.0
CASETHEN
	MOV K300 D8
CASEELSE
	LD SM400
	MOV K-1 D8
ENDCASE

(* ===== FOR:1~5を加算 ===== *)
LD SM400
MOV K0 D20
STFOR
	MOV K1 D10
FORBY
	LD SM400
	+ D10 K1 D10
FORTO
	LD<= D10 K5
	OUT TMP:55.0
	LD TMP:55.0
FORDO
	+ D20 D10 D20
ENDFOR

(* ===== WHILE:条件を先に判定 ===== *)
LD SM400
MOV K0 D11
WHILE
	LD< D11 K3
	OUT TMP:56.0
	LD TMP:56.0
WHILEDO
	+ D11 K1 D11
ENDWHILE

(* ===== REPEAT:処理後に終了条件を判定 ===== *)
LD SM400
MOV K0 D12
REPEAT
	LD SM400
	+ D12 K1 D12
UNTIL
	LD>= D12 K3
	OUT TMP:54.0
	LD TMP:54.0
ENDREPEAT

(* ===== EXIT:ループを途中で抜ける ===== *)
LD SM400
MOV K0 D21
STFOR
	MOV K1 D13
FORBY
	LD SM400
	+ D13 K1 D13
FORTO
	LD<= D13 K10
	OUT TMP:55.0
	LD TMP:55.0
FORDO
	IF
		LD> D13 K3
		OUT TMP:56.0
		LD TMP:56.0
	THEN
		EXIT
	ENDIF
	LD SM400
	+ D21 D13 D21
ENDFOR

(* ===== 関数呼出し ===== *)
LD SM400
MOV K-10 TMP:53
AND< K-10 K0
NEG TMP:53
LD SM400
MOV TMP:53 D30

(* ===== RETURN:現在の処理を終了 ===== *)
MOV K0 D31
IF
	LD= D0 K2
	OUT TMP:54.0
	LD TMP:54.0
THEN
	CJ GLP0
ENDIF
LD SM400
MOV K999 D31
GLP0
_TMFREE H57
STPOP
FBRET

すると、このような命令が出てきます。

STPUSH STPOP _TMALLOC _TMFREE FBRET
IF THEN ELSIF ELSE ENDIF
CASE CASEOF CASEIF CASETHEN CASEELSE ENDCASE
STFOR FORBY FORTO FORDO ENDFOR
WHILE WHILEDO ENDWHILE
REPEAT UNTIL ENDREPEAT
EXIT

GX Works2では、STの分岐やループをポインタを使ったジャンプで制御していました。
そのため、STで分岐やループを多く書くと大量のポインタを消費していました。
今回のiQ-Rの結果では、IFやWHILEなどに対応する命令が使われており、分岐やループごとにポインタを消費しないので気にせず書くことができます。
この例ではRETURNの部分だけがポインタを使っており、CJ GLP0でFB末尾の終了処理へジャンプしています。

まとめ

GX Works3でも、シミュレータとの照合結果からコンパイル後の命令を見ることができました。
FBのマクロ型とサブルーチン型を切り替えると、同じ回路でもロジックが格納される場所や呼び出し方が変わることがわかります。

STも、すべてが普段使うラダー命令に置き換わるわけではなく、IFやWHILEなどに対応する命令が使われていました。
LFBCALLやFUNCALLなど、普段のラダーでは見かけない命令が出てくるのも面白いところです。

FBやSTは書いたとおりに動けば中身を気にする機会は少ないですが、コンパイル後の命令を見ると、引数の受け渡しや処理の流れを追うことができます。
気になった処理を小さなプログラムにして照合してみると、GX Works3が裏で何をしているのか見えてきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?