2007年01月16日

cmpの怪

 VRM4スクリプトの数値比較系の命令を使ってみたんですけど、ちゃんと動いてくれません。数値比較系の命令ってのは、cmpeq、cmp>、cmp<、cmp>=、cmp<=の5つのことです。

 これらは全部、

 cmpなんとか 変数A 変数B 変数C

 というかたちをとり、変数Bと変数Cの大小を比較して、その結果を変数Aに入れる(正しければ1、誤りなら0)命令らしいです。
 でも自分が試した限りでは、変数Aに返ってくる答えは合っていたり間違っていたり不定になってしまいました。

 そこで次のようなスクリプトを書いて、変数Bと変数Cの値を変えつつ、5つ全ての命令を試してみました。

===ここから===
Var a
Var b
Var c

set a 0
set b [ここにいろいろな整数を入れる]
set c [ここにいろいろな整数を入れる]

cmpなんとか a b c
DrawVar a
===ここまで===

0701cmpexpgraph.jpg

<実験結果>

 赤太字の箇所が、間違った答えを返した箇所です。

 つーか要するに、cmp>とcmp<は全部0、cmp>=とcmp<=とcmpeqは全部1を返しているだけじゃないっすかコレ。

 自分はこの命令の使い方を何か誤解してるんでしょうか?

(追記)2月3日のアップデータ4.0.5.4で直りました。


posted by 45-50s at 23:38| Comment(10) | TrackBack(0) | 改善済 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
こんな感じ

乱数を乱数で割る。
少数第1位に1か2が出たらcmp>
少数第1・2位に3か4が出たらcmp<
少数第1・2・3位に5か6が出たらcmp>=
少数第1・2・3・4位に7か8が出たらcmp<=
少数第1・2・3・4・5位に9か0か少数が出なかったら
cmpep
また乱数を2個作り、
cmp*を実行し、
間違った答えなら1、合ってたら0で部品を動かす。


長くなりましたがこんな感じでしょうか?
Posted by qwerty at 2007年01月22日 17:01
「また」ってのは2回めです。
Posted by qwerty at 2007年01月22日 17:08
うーんすみません、よく意味がわかりません。
cmpなんとかっていうのはどれもスクリプトの命令の名前で、何らかの計算結果から導き出すものではないんですが。
Posted by 45-50s at 2007年01月22日 22:37
これでランダムに動かせると思いますが。
Posted by qwerty at 2007年01月23日 17:03
qwertyの人が何を語っているのかは、ボクにもさっぱりわかりません。

それはさておき、ご参考までにボクの見解を開陳しておきますね。>45-50s殿

CPUってヤツは、数値の大小比較をするときに伝統的に減算をおこなうんです。AとBの大小比較をする場合、まずA-Bをする。
で、CPUの内部に計算の答えと同時に「ゼロになったか」「桁あふれをしたか」が記録されます。前者をゼロフラグ、後者をキャリーフラグといい、これは0または1の数値として表現されます。
たとえば、ゼロフラグが1でキャリーフラグが0だと、これはAとBが等しかったことがわかります。ゼロフラグが0でキャリーフラグが1だと、BがAより大きかったので、減算結果がマイナスになった(CPU内部では-1はビット幅に応じた最大値に対応し、一周してつながっています)ことを意味します。

おそらく、cmp命令はそれが物理CPUかVRMが内包する仮想CPUかはともかく、このゼロフラグとキャリーフラグの値のどちらか、あるいは両者の論理積または論理和を返す命令です。この組み合わせが、キミが書いた大小関係の表に対応します。

で、結果がキミが調べたようになるってことは、中の人が命令毎に参照すべきフラグであるとか論積/和のどちらを使うのか、の組み合わせを変えるのを忘れたまま(あるいは別の修正を加えた際に、そのコードを壊して)コンパイルしちゃって、かつ、テストせずに出荷した可能性が大です。

実はif系命令も内部では同じことをやっているはずで、フラグの結果に応じてelse/endif以降へ実行位置がジャンプするかどうかで分岐してるだけなんですが、少なくともifeq命令に異常は見られないので、VRM的にcmp系とif系は、ロジックが独立だってことがわかりますね。んな非効率なことするかバグが出る。いや、ネイティブコード直結なんだとすると、しゃーないのかも。

以上、役に立たない薀蓄でした。あでゅ。
Posted by ghost at 2007年01月23日 18:01
あ。比較減算前の型判定が滑ってるって可能性を忘れてますね。VRMは内部で小数型、整数型、その他を自動判別しているので、この処理がおかしいと、当然演算結果も狂います。
Posted by ghost at 2007年01月23日 18:04
どうもです。
確かにif命令はちゃんと動いてるっぽいですね。でないとVRMゲーセン系のレイアウトはみんな動かなくなっちゃうはずですから。
会議室では、すぐには対応できないなんて言われちゃいましたし、しばらくはsubとifで代用するしかなさそうっすね。
Posted by 45-50s at 2007年01月24日 00:58
もうあのブログ見るのやめよ。(VRM入道)
Posted by qwerty at 2007年01月24日 18:15
見なくていいよ。まぁ、無理だと思うけど。自分で削除/訂正できないところに、そういう強がりは書かない方がいい。>qwerty殿

それはさておき。

cmp系命令は、つまるところ2つの変数の大小関係を0/1の値で取得したいケースしか利用価値がないワケで。VRMスクリプトでは、一般的なプログラミング言語がサポートする・・・

X = X + ( S > 0 )

みたいな論理演算式が使えません。ちなみに、上の式は、Sが0を超える場合、Xに1加算する、の意になります。モノによっては論理式真が-1として評価されるため、減算になることもありますが。

こういう記述は、昔のコンピューターでは分岐によるアドレスジャンプよりも演算の連鎖の方がコストが低かったので有用だったんですが、VRMスクリプトではそういうテクニックを使う積極的な理由がないので、たとえばcmp命令の結果を変数Rに収めたかったのだとすれば、if系命令の分岐部にset R 1/0でも結果は同じじゃん、みたいな気がしています。

あるいは、45-50s殿には、何かcmp系命令を有効活用する秘策がおありで?
Posted by ghost at 2007年01月24日 19:40
>ghostさん
>if系命令の分岐部にset R 1/0でも結果は同じじゃん

そうっすよね、それ自分も思いました(笑

>秘策がおありで?

いえ、この記事は、せっかくだからVRMスロットの当たり判定に使ったことがなかったcmp系命令を使おうと思ったのに、全然使い物にならなくて残念だったから書いただけっす。
強いて言えば、結果を使うのがライトの点灯/非点灯みたいに1/0が直接使える場合なら、if系命令よりずっと行数が少なくてすっきりしますよね。
Posted by 45-50s at 2007年01月25日 00:33
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。