命令コード

このページでは「MC4000」、「MC4000x」、「MC6000」など
マイコンでプログラミングする際に利用する命令コードについて説明します。



プログラミングについて

構造

プログラムは必ず以下の形式で記述しなければなりません。
(マニュアルを参照)

[ラベル:] [条件+/-] [命令] [#コメント]

全てのコードは省略可能ですが、必ずこの順序で記述する必要があります。
以下の例は構文的に有効です。

#This line is a comment.
loop: #until ACC is ten
  teq acc 10
+ jmp end
  mov 50 x2
  add 1
  jmp loop
end:
  mov 0 acc # reset counter


ラベル

ラベルを使用する場合は必ず行の最初に記述します。
ラベル名の最後には : (コロン)が必要です。

ラベルを付けてもそれ自体は何の処理も行いませんが、
基本命令である jmp L によって、
ラベルを付けた行に処理を移動させる事ができます。


条件付き実行

命令の直前に + や - の接頭語を付けることで、
その命令を条件付きで実行します。

この条件は後述のテスト命令の結果によって有効化され、
有効化されていない接頭語の命令は実行されず無視します。
(無視した命令は電力を消費しない)

この条件付き実行を行う事で可能な限り実行する無駄を削り、
消費電力を削減する事も可能な場合があります。


レジスタ

レジスタは様々な命令でオペランドとして利用されます。
オペランドについては後述。

レジスタの種類は次の通りです
nullレジスタを除く一部のレジスタは、
整数値(-999~999)を扱えます。
p0、p1のピンレジスタは自然数(0~100)となります。

accレジスタ

acc は多目的レジスタです。様々な用途に利用する事ができ、
全てのマイコンに実装されています。算術命令による計算処理は、
自動的に全てこの accレジスタ で行われます。

演算命令を使うことで必ずこのレジスタの値が操作されてしまう点に注意してください。

このレジスタに値を送ればその数値を保存しておく事ができます。

datレジスタ

dat は副次レジスタとして、MC6000のマイコンに実装されています。
MC4000 には実装されていないので注意してください。
このレジスタは acc と同じ様に使用することができますが、
算術命令で使用されるのはあくまで acc である点に注意してください。

このレジスタに値を送ればその数値を保存しておく事ができます。

ピンレジスタ

ピンレジスタは MCxxxx系 のマイコンにおける他の装置と接続する端子部分の事です。
それぞれのマイコンによって存在するピンレジスタが異なります。
またピンレジスタは p で始まるものがシンプル、x で始まるものが XBus となり、
それぞれ互換性を持つ装置と同期し、その接続先装置にデータを送ります。
自身のマイコンに対してデータを一時的に保存する目的で使用できません。

MC4000 : p0、p1、x0、x1
MC4000x : x0、x1、x2、x3
MC6000 : p0、p1、x0、x1、x2、x3

nullレジスタ

nullレジスタは擬似レジスタです。
実際は存在しませんがレジスタとして指定する事ができます。
このレジスタにデータを送った場合、そのデータは破棄され、
このレジスタにデータを読みに行った場合、必ず 0 が返ってきます。

オペランド

オペランドは命令の対象のことです。
命令は、なにを、どうするか、で成り立っており、
この「なにを」の部分がオペランドになります。
(命令によってはオペランドが複数必要な場合もあります)

このゲームにおけるオペランドには以下の種類があります。

省略 意味
R/I 全てのレジスタと整数値(-999~999)
R 全てのレジスタ
I 整数値(-999~999)
P ピンレジスタのみ
L ラベル

ラベルを指定する場合は同一マイコン内に、
そのラベルが存在している必要があります。

コメント

コメントは # で始まります。
コメントに指定された文字列はメモのようなもので、
実行、または処理される事はありません。

プログラムが複雑になったときのメモに使うと良いでしょう。

命令コード一覧

基本命令

使用頻度が非常に高い命令です。
これを使わないマイコンなど存在しない、と言うくらい、
使用頻度が高いと思います。

mov R/I R

第一オペランドの値を第二オペランドにコピーします。
最もよく使う命令の一つです。

slp R/I

指定されたオペランドの値だけCPUを停止させます。
停止中は電力を消費しませんが、slp命令を実行する際には電力を 1 使います。

slpは状態を維持するものではありません。
単純にCPUの動作をオペランドTU分だけ停止させるだけです。
状態を維持しているように見えたのなら、
それは恐らくシンプル回路の特徴です。

slx P

指定されたオペランドのピンレジスタに接続された先の装置が
通信準備状態になるまでスリープさせます。
XBusによる同期プロトコルで通信を行う場合に、非常に重宝します。

jmp L

指定されたオペランドのラベルまで処理をスキップします。
指定されたラベルが存在しないとエラーとなります。

?????

この命令はゲームの進行(ステージ10くらい)によって開放されます。
既存の一部の命令を省略する事ができる命令です。
最初から利用する事もできますが、利用するかどうかはあなた次第です。

...


算術命令

値の計算を行う際に利用します。
計算の際は暗黙的に accレジスタ が使用され、
それ以外のレジスタで算術を行う事はできません。
実行する事で accレジスタ の値が必ず変化してしまう事に気を付けましょう。
算術結果の値がオーバーフロー(-999以下や999以上)してしまった場合は、
それぞれの上限、下限値に修正されます。

例:
acc が 800 の時に add 500 を実行すると、
acc の値は 999 となる。

add R/I

accレジスタに指定したオペランドの値を加算します。
acc = ( acc + オペランド[R/I] )

sub R/I

accレジスタに指定したオペランドの値を減算します。
acc = ( acc - オペランド[R/I] )

mul R/I

accレジスタに指定したオペランドの値を乗算します。
acc = ( acc * オペランド[R/I] )

not

accレジスタの値が 0 ならば 100 にします。
0 以外の値の場合は 0 にします。

dgt R/I

多分「digit」の略。指定したオペランドの桁を acc の値から抜き出して acc に格納します。
オペランドの値は、0→1桁目、1→2桁目、2→3桁目、となります。

例:
acc が 456 の時、dgt 1 を実行すると
acc には 5 が格納されます。

dst R/I R/I

多分「digit set」の略。指定した第1オペランドの桁に存在する値を
第2オペランドの値に書き換え、その値を acc に格納します。
(第1オペランドの桁数は 0 が 1桁目、1 が 2桁目、2 が 3桁目である事に注意)

例:
acc が 77 の時、dst 0 3 を実行すると
acc には 73 が格納されます。(accレジスタの 1桁目 を 3 に書き換える)

acc が 77 の時、dst 2 7 を実行すると
acc には 777 が格納されます。(accレジスタの 3桁目 を 7 に書き換える)

この時、第2オペランドの値に2桁以上の数字を入れてもエラーは出ませんが、
結果として1桁目の値に書き換えられます。
また第2オペランドが負数だった場合結果は負数になり、
第2オペランドが正数だった場合結果は正数に書き換わります。

例:
acc が 456 の時、dst 1 9 を実行すると
acc には 496 が格納されます。

acc が 456 の時、dst 1 47 を実行すると
acc には 476 が格納されます。(第2オペランドは1桁目しか反映されない)

acc が 456 の時、dst 1 -9 を実行すると
acc には -496 が格納されます。(第2オペランドが負数なら結果も負数になる)

acc が -456 の時、dst 1 -9 を実行すると
acc には -496 が格納されます。(元々負数なら第2オペランドで負数を指定しても負数)

acc が -456 の時、dst 1 9 を実行すると
acc には 496 が格納されます。(元々負数の時第2オペランドで正数を指定すると正数になる)

テスト命令(条件)

指定した条件をテストする命令です。
この結果によって接頭語を指定している条件付き実行の命令が有効化されます。

接頭語を指定している条件付き実行の命令については、
直前のテスト命令の結果によって有効化される訳ではない点に注意。
これを理解していないと嵌ります。

条件付き実行の命令が有効化されるのは、
直前までの最後に実行されたテスト命令の結果です。
(直前にテスト命令があっても実行されていない場合は、最後に実行されたテスト命令の結果で動いてしまう)

例えば acc に 50 が格納されている時、
acc の値が 40以上で60よりも小さい かをチェックするとします。
そして40以上60よりも小さいが満たされた時、p1 に acc を送信する事を想定します。

  tlt acc 40
- tlt acc 60
+ mov acc p1

  slp 1

上から見ていくと、
1. acc は 40 よりも小さいか(acc は 50 なので - が有効化される)
2. もし40以上だったら、acc が 60 よりも小さいかをチェックする(acc は 50 で 60 より小さいので + が有効化される)
3. acc が 60よりも小さいので acc を p1 に送る
4. このTUにおける処理終了

となっており一見問題ないように見えます。
実際、通常のプログラミングならば 条件→○○だったらさらに条件 とすれば、
その次に来る条件付き命令は、ふたつの条件をクリアしているはずです。

こんなつもりで上のコードを読んでいませんか?

if(acc < 40) { break;}
else {
  if(acc < 60) {
    echo acc; //mov acc p1の代わり
  }
}

だとしたら大きな間違いです。
このゲームにおける条件付き命令は「最後に実行されたテスト命令の結果」で有効化されます。
その為、先程の…

  tlt acc 40
- tlt acc 60
+ mov acc p1

  slp 1

のコードだと、確かに acc が40以上の時は正常に動作しますが、
acc が 40 よりも小さな値をとってしまうと正常に動作しません。
acc が 35 だったとすると…

1. acc は 40 よりも小さいか(小さいので + が有効化される)
2. acc は 60 よりも小さいかのチェックは - の条件付き命令で有効化されていないのでスキップ
3. + が有効化されているので p1 に acc の値が送信されてしまう

必ずしも直前のテスト命令に対する接頭語ではありません。
接頭語の有効化、無効化はテスト命令が実行される度に切り替わります。
割りと重要なので気を付けましょう。


teq R/I R/I

所謂 IF A == B とかそう言うの。
多分「test equal」の略。ふたつのオペランドの値が等しいかどうかをチェックします。
等しい場合は + の条件付き命令が有効化され、
等しくない場合は - の条件付き命令が有効化されます。

tlt R/I R/I

所謂 IF A < B とかそう言うの。
多分「test less than」の略。第1オペランドは第2オペランドよりも小さい、をチェックします。
よりも小さい場合は + の条件付き命令が有効化され、
以上の場合は - の条件付き命令が有効化されます。

tgt R/I R/I

所謂 IF A > B とかそう言うの。
多分「test greater than」の略。第1オペランドは第2オペランドよりも大きい、をチェックします。
よりも大きい場合は + の条件付き命令が有効化され、
以下の場合は - の条件付き命令が有効化されます。

tcp R/I R/I

多分「test compare」の略。第1オペランドと第2オペランドを比較します。
よりも大きい場合は + の条件付き命令が有効化され、
等しい場合はどちらも有効化されず、
よりも小さい場合は - の条件付き命令が有効化されます。

  • 最終更新:2017-10-26 22:10:13

このWIKIを編集するにはパスワード入力が必要です

認証パスワード