• ベストアンサー

アセンブラで教えてください

富士通のFRマイコンをつかってます。 演算結果で分岐するようにしたいのですが、うまくいきません。 R1にいれたFFから、-1引いて、Z=1になったら, STRARTに飛びたいのですが、Aにしか飛んでいないようです どこがまずいでしょうか? その前の命令(NOP)が長すぎると計算できないことはありますか? ; START: LDI:32 #000000FFH,R1 A: NOP (NOPは1000行) NOP ・ ・ ADD2 #-1,R1 BNE A BRA START ; END:

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

ANo.1 です。 >R1にいれたFFから、-1引いて、Z=1になったら, というのは、 >ADD2 #-1,R1 の結果が zero ならば、ということですよね? towa2005 さんのやろうとしていることが、-1 - (-1) であるのならば、 >LDI:32 #000000FFH,R1 ではなく、 LDI:32 #FFFFFFFFH,R1 とするべきなのでしょうね。

towa2005
質問者

お礼

たびたびお世話になります。 すいません、書き方が悪かったです。”-1引いて”ではなくて 1引いての間違いでした・ R1にFFを代入し、そこから、1を引いていって、演算結果がゼロになったら(Z=1),STARTにもどりたいです すいませんが、よろしくおねがいします

その他の回答 (4)

  • php504
  • ベストアンサー率42% (926/2160)
回答No.5

BRAも分岐条件がないだけの相対ジャンプですので範囲はBNEと同じです -128~+127(の2倍?)以上の分岐は出来ません

towa2005
質問者

お礼

そうですね。修正して見ます。 ありがとうございました

回答No.4

ANo.1 です。誤解をしていたようです。 For ループを書きたいのですね? A にしか飛んでいないということは確実なのでしょうか? ANo.2 さんの回答された内容が問題になってくる可能性が高いですね。 NOP が 1000 個というのは符号付き 8 ビットの範囲を超えています。 ・相対アドレスでジャンプするのではなく、絶対アドレスでジャンプする ・NOP の個数を減らして試してみる。 などを試してみてはいかがでしょうか。

towa2005
質問者

お礼

そうですね。nopが1000個はちょっと多かったです。 もう少し考えて見ます。ありがとございました

  • php504
  • ベストアンサー率42% (926/2160)
回答No.2

http://edevice.fujitsu.com/jp/manual/MANUALp/ja-pdf/CM71-00101-4.pdf の175ページを見るとBNE等の相対ジャンプ範囲は符号付き8ビットのようです。 NOPが長すぎると届かなくなりますね。

towa2005
質問者

お礼

BNEは理解しました。修正して飛ぶようになりましたが、 Z=1の分岐先には飛びません。 NOPが長いとゼロにならないとかあるんでしょうか?

回答No.1

>富士通のFRマイコンをつかってます。 これの仕様はわからないのですが、 もし、すべて 32 ビットで処理をしているのなら、 >R1にいれたFFから、-1引いて、Z=1になったら, この計算は zero にはならないはずです。 ここが問題なのではないでしょうか。

towa2005
質問者

お礼

すいません、どうすればゼロになりますでしょうか? 減算しても最終的にゼロにはならないんですか?

関連するQ&A

  • アセンブラに関する質問

    アセンブラに関する質問 現在アセンブラの勉強をしている者ですが2つ質問があります (1)以下のサイトの分岐とジャンプ命令の説明にPC+4という記述があるのですがこれはメモリアドレスを指しているのですか?そうだとしたら、4というのはデータ語長が4バイトだとだからという意味だと思うのですがPCというのは何なんでしょうか? R3000 URI:http://ja.wikipedia.org/wiki/R3000#.E5.91.BD.E4.BB.A4.E3.82.BB.E3.83.83.E3.83.88.E3.81.AE.E6.A6.82.E8.A6.81 (2)レジスタr1がレジスタr2の値より小さいとき処理Aと処理Bをさせる方法はどうしたらいいでしょうか?自分が思うに addi r2, r2, 100 ?←ループの始まりを知らせる命令を用意する 処理A 処理B addi r1, r1, 1 ble r1, r2, ?←ループの始まりに行く値をセットする という命令を書けばいいと思うのですが?の部分の書き方が分かりません。 使用できる無条件、条件分岐命令は以下のものが指定されています。 無条件分岐:j, jr, jal 条件分岐:beq, bne, blt, ble

  • アセンブラの練習で困ってます

    下記のようなアセンブラのプログラムの勉強をしています。初心者。 (ベクターテーブルとかは省略してます) この状態であれば、tablに書いたデータどおりにLEDが順番に点灯します。 しかしtablの内容を書き換えると、点灯しなくなります。命令語の意味を 調べたりしたのですが、わかりません。どなたか理由を教えてください。 (例えば) 10000000 01000000 00100000 00010000 10000000 01000000 00100000 ・・・・ プログラム抜粋 reset: mov.l #stack,sp bsr initio begin: mov.l #tabl,er1 ; 点灯データ表 mov.w #14,r2 ; 点灯データ表のデータ数 loop: mov.b @er1+,r0l not.b r0l mov.b r0l,@p1dr bsr wait dec.w #1,r2 bne loop bra begin ; tabl: .data.b b'10000000 .data.b b'01000000 .data.b b'00100000 .data.b b'00010000 .data.b b'00001000 .data.b b'00000100 .data.b b'00000010 .data.b b'00000001 .data.b b'00000010 .data.b b'00000100 .data.b b'00001000 .data.b b'00010000 .data.b b'00100000 .data.b b'01000000 ; initio: mov.b #h'ff,r0l ; ポート1を出力に設定 mov.b r0l,@p1ddr rts ; wait: mov.l er0,@-sp mov.l #h'100000,er0 wait1: nop dec.l #1,er0 bne wait1 mov.l @sp+,er0 rts

  • H8マイコン アセンブラ言語の乱数ルーチンについて

    H8マイコンでアセンブラ言語を使用しております。 アセンブラ言語で、ランダムに分岐するようにしたいのですが、乱数ルーチンをどのように作ればよいかわかりません。 下記は現在のメインプログラムです。ポート4の4の状態を調べ、真ならHYOJIに分岐するようにし、真でないならSTARTに戻るという風にしています。 START: MOV.B @P4DR,R0L MOV.B R0L,@SW_D MOV.B @SW_D,R0H BTST #4,R0H BEQ HYOJI JMP @START 5行目のBEQから乱数ルーチンにひとまず飛んで、そこからさらにランダムに選ばれた分岐に飛ぶというようにしたいです。 乱数ルーチンは現在時刻などから値を取得し、それからランダムな値を作ったりするのでしょうか? どなたかご協力お願いいたします。 ちなみに、下記は自分が参考にしている本です。 H8マイコン入門 堀桂太郎著 東京電機大学出版局発行

  • アセンブラのタイマー割り込み

    ちょと長いですがプログラムおいときます 下のプログラムでは割り込みをスイッチで行うのですが スイッチを使わない割り込みをするにはタイマーがいいのではと聞きましたが 私にはわからなかったので教えていただきたいです どこをどう変えたら起動できるでしょうか? 使っているものはマイコン(R8C15)です 内容とか足らないのかもしれませんが何でも言ってください すみませんがよろしくお願いします .INCLUDE sfr_r815.inc ;プログラム部分 .SECTION PROGRAM, CODE .ORG 0D000h Start: LDC #0500h, isp LDINTB #VarVector JSR SetClock20MHz JSR InitPort JSR InitKeyInputIntr MOV.B Dummy, r0h FSET i Loop: BCLR p1_1 JSR Wait2s BSET p1_1 JSR Wait2s JMP Loop ;外部クロックに切り替えるサブルーチン SetClock20MHz: BSET prc0 BSET cm13 BSET cm15 BCLR cm05 BCLR cm16 BCLR cm17 BCLR cm06 NOP NOP NOP NOP BCLR ocd2 BCLR prc0 RTS ;ポートの初期化を行なうサブルーチン InitPort: MOV.B #00000110b,drr MOV.B #00000110b,p1 MOV.B #00000110b,pd1 RTS ;キー入力割り込みの初期化を行なうサブルーチン InitKeyInputIntr: BCLR ki0pl BSET ki0en MOV.B #01h, kupic RTS ;2秒待ちサブルーチン Wait2s: MOV.W #200, r1 Wait2s_1: JSR Wait10ms SBJNZ.W #1, r1, Wait2s_1 RTS ;10m秒待ちサブルーチン Wait10ms: PUSH.W r0 MOV.W #28571,r0 Wait10ms_1: SBJNZ.W #1,r0,Wait10ms_1 POP.W r0 RTS ;キー入力割り込み処理ルーチン KeyInput: Start1: MOV.B #10001001b,pd1 MOV.B #00000000b,p1 MOV.B #10111000b,pd3 MOV.B #00000000b,p3 Syoki01: MOV.W #2,r1 BSET p1_3 ;M BCLR p3_3 ;SDI Loop1: MOV.W #2,a1 GYOU: MOV.W #9,a0 CP00: BSET p3_4 ;CP=H BCLR p3_5 JSR wait1 BCLR p3_4 ;CP=L JSR wait1 BSET p3_4 ;CP=H BCLR p3_5 JSR wait1 BCLR p3_4 ;CP=L JSR wait1 SBJNZ.W #1,r1,CP00 BNOT p3_3 ;SDI MOV.W #2,r1 SBJNZ.W #1,a0,CP00 LOAD0: BSET p3_4 ;CP=H ;BSET p3_5 ;LOAD JSR wait1 BCLR p3_4 ;CP=L BCLR p1_0 ;DIO BSET p3_5 ;LOAD JSR wait1 BNOT p3_3 ;SDI SBJNZ.W #1,a1,GYOU MandDIO: BSET p1_0 ;DIO BNOT p1_3 ;M JMP Loop1 wait1: MOV.W #30,r2 wait001: SBJNZ.W #1,r2,wait001 RTS REIT ;その他の割り込み処理ルーチン NOTUSE: REIT ;データ(作業領域)部分 .SECTION WORK,DATA .ORG 0400h Dummy: .BLKB 1 ;可変ベクタテーブル .section VARIABLEVECTOR, ROMDATA .org 0F000h VarVector: .lword NOTUSE .lword 0 .lword 0 .lword 0 .lword 0 .lword 0 .lword 0 .lword 0 .lword 0 .lword 0 .lword 0 .lword 0 .lword 0 .lword KeyInput .lword NOTUSE .lword NOTUSE .lword NOTUSE .lword NOTUSE .lword NOTUSE ;リセットベクタ部分 .SECTION FIXVECTOR, ROMDATA .ORG 0FFFCh Reset: .LWORD Start | 0FF000000h .END

  • 割り込みなしのタイマー

    以下のような割り込みを用いないタイマーを使うプログラムをH8マイコンで動かしたいのですが、上手くいきません・・・。表示を1秒間隔で切り替えていくものです。どこがよくないのでしょうか? MOV.L #FFFFD1,ER0      //PADDR MOV.B #FF,R1L //FF=11111111 MOV.B R1L,@ER0 //PADDR = FF MOV.L #FFFFD4,ER0      //PBDDR MOV.B #FF,R1L //FF=11111111 MOV.B R1L,@ER0 //PBDDR = FF MOV.L #FFFFD6,ER0      //PBDR MOV.B #5B,R1L //5B = "2" MOV.B R1L,@ER0 //PBDR = 5B MOV.L #FFFFD3,ER0      //PADR MOV.B #01,R1L //01 = 0KETA MOV.B R1L,@ER0 //PADR = 0KETA **128 MOV.L #FFFF64,ER2 //TCR0 MOV.B #83,R1H //83 = 1/8 MOV.B R1H,@ER2 //TCR0 = 1/8 MOV.L #FFFF6A,ER3      //GRA0 MOV.W #61A8,E1 //61A8 = 25000 MOV.W E1,@ER3 //GRA0 = 25000 MOV.W #3E8,E4 //3E8 = 1000 MOV.W #0,R4 // 0 MOV.B #F9,R5L // F9 MOV.L #FFFF67,ER0      //TSR0 MOV.L #FFFF60,ER6      //TSTR MOV.B #1,R5H MOV.B R5H,@ER6 //TSTR = 1 *158 MOV.B @ER0,R5H //TSR0の値 CMP.B R5L,R5H BNE FFF* MOV.B #F8,R5H //初期値に戻す MOV.B R5H,@ER0 INC.W #1,R4 CMP.W R4,E4 BNE FFF* MOV.B #0,R5H //ストップ MOV.B R5H,@ER6 MOV.L #FFFFD3,ER0      //PADR ADD.B R1L,R1L //表示桁の更新 MOV.B R1L,@ER0 BRA FFF**

  • Z80に関しての宿題なのですが、

    Z80に関しての宿題なのですが、 「コール命令を使った電子オルガン」 キーを入力したら対応する音が鳴るようにプログラミングする。(入力を 常に監視し、FFHでなかったらサウンド出力をする。)プログラムは4400H番地から書く。  キー入力:CALL 2018Hと呼ぶとAレジスタに押されたキーの内容が入ってくる。 押されないとFFHが入っている。(いずれかのキーが押されるとAレジスタには00Hから17Hまでの対応する値が格納される。)  サウンド出力:Aレジスタに00Hから17Hを入力してCALL 201BHと呼ぶと対応する音が鳴る。    (1)キー入力を行った.Aレジスタにキーの内容が入る。    (2)AレジスタがFFHの場合は(1)に戻る。そうでないときは(3)へ行く。    (3)Aレジスタの内容により、サウンド出力を行った。    (4)(1)に戻る。      ニーモニック                        CALL , 2018H SUB FFH JP Z , (4400H) ・・・・(ゼロフラグZが1の時、4400番地にジャンプする。) ADD FFH CALL , 201BH JP 4400H ↑のようにすればよいのですが、なぜなのかいまいちわかりません。異なるコードで実装せよ。とのことなので理解したいです。おしえてください。

  • C言語にて、XORの演算時間を取得するには?

    題名の通りです。 C言語で、XOR命令の演算時間を取得しようとしています。演算時間を取得する関数部分は下の通りで、a^=b, b^=aをひたすら繰り返すことで、命令の演算時間を取得する、というものです。この方法を使って、ADD命令については演算時間を取得できました。しかし、XORについては、計測時間がほぼゼロになり、XORが動いていないようです。 その理由は、同じ値をXORすると元に戻るというXORの原理のため、コンパイラの最適化によりfor文内のXOR命令が消えてしまったからだと考えられます。 かといって、t1とt2にvolativeを付けて宣言すれば、最適化によって消去はされませんが、volativeの性質上、メモリアクセスの時間を取得することになってしまいます。 どうすれば、XOR命令のみの演算時間を取得できるでしょうか。 アイディアや指摘がありましたら、どうかご教授下さい。 -------------------------------------------------------------- #define ADD(a, b) a+=b #define XOR(a, b) a^=b /* 10回反復するマクロ */ #define repeat10(S) S S S S S S S S S S /* 各命令の演算時間を計測する関数 */ void operation_test( unsigned int *out, unsigned int p1, unsigned int p2, int its) { /* volatileを付けた宣言だと、t1とt2はメモリに取られるため、目的を達成できない */ unsigned int t1 = p1; unsigned int t2 = p2; /* itsは反復回数 */ for(int i=0; i<its; i++){ /* いずれかの行を選択する。ADDはきちんと演算されているよ */ /* うだが、XORは最適化により消去されてしまっているらしい */ repeat10(ADD(t1, t2); ADD(t2, t1); ) //repeat10(XOR(t1, t2); XOR(t2, t1); ) } out[0]=t1+t2; } --------------------------------------------------------------

  • タイマーを用いたプログラム

    H8のマイコンを用いて、7セグメントLEDを 1秒間隔で表示を切り替えるプログラムを作りたい のですが、いまいち上手くいきません。。。 タイマー割り込みは用いずに行いたいのですが、以下のプログラムでどこが間違っているのでしょうか?? MOV.L #FFFFD1,ER0 //PADDR MOV.L #FFFFD4,ER1 //PBDDR MOV.B #FF,R2L //FF=11111111 MOV.B R2L,@ER0 //PADDR = FF MOV.B R2L,@ER1 //PBDDR = FF MOV.L #FFFFD6,ER0 //PBDR MOV.L #FFFFD3,ER1 //PADR MOV.B #5B,R2L //5B = "2" MOV.B R2L,@ER0 //PBDR = 5B MOV.B #01,R2L //01 = 0KETA MOV.B R2L,@ER1 //PADR = 0KETA *** MOV.L #FFFF64,ER3 //TCR0 MOV.B #83,R2H //83 = 1/8 MOV.B R2H,@ER3 //TCR0 = 1/8 MOV.L #FFFF6A,ER3 //GRA0 MOV.L #61A8,ER4 //61A8 = 25000 MOV.L ER4,@ER3 //GRA0 = 25000 MOV.W #3E8,E3 //3E8 = 1000 MOV.W #0,R3 // 0 MOV.B #F9,R4L // F9 MOV.L #FFFF67,ER5 //TSR0 MOV.L #FFFF60,ER3 //TSTR MOV.B #1,R2H //TSTR = 1 ** MOV.B @ER5,R4H //TSR0の値 CMP.B R4L,R4H //比較 BNE FFF** //ループ MOB.B #F8,R4H //初期値に戻す MOV.B R4H,@ER5 // INC.W #1,R3 //ループ数 CMP.W R3,E3 //比較 BNE FFF** //ループ MOV.B #0,R2H //タイマーのストップ MOV.B R2H,@ER3 // ADD.B R2L,R2L //表示桁の更新 MOV.B R2L,@ER1 // BRA FFF***

  • コンピューターシステム コンピューターへの命令 命令群

    コンピューターシステムの問題が解けなくて困っています。 (1)つぎの命令群を順に実行すると、どういう結果が得られるか。 CLRはオペランドをクリアする(0にする)という命令である。 CLR R0 CLR (R0)+ CLR (R0)+ CLR (R0)+ CLR (R0)+ という問題では、 CLR R0   R0を0にする CLR (R0)+ 0000番地を0に,R0を0002にする CLR (R0)+ 0002番地を0に,R0を0004にする CLR (R0)+ 0004番地を0に,R0を0006にする CLR (R0)+ 0006番地を0に,R0を0008にする CLR (R0)+ 0008番地を0に,R0を000Aにする って感じで進んでいくってわかるのですが、 (2)次の命令群を実行した結果を説明せよ。 CLR R0 ADD #1,R0 ADD #2,R0 ADD #3,R0 ADD #4,R0 (3)次の命令群を実行した結果を説明せよ。 MOV #100,R1 CLR -(R1) CLR -(R1) CLR -(R1) CLR -(R1) (4)次の命令群を実行した結果を説明せよ。 CLR @#100 というこの(2)(3)(4)が解けなくて困っています。 誰か教えてください。 よろしくお願いします。 できれば(1)の解答のような感じで書いていただけるとありがたいです。

  • 1~10まで足すプログラム

    H8のマイコンを使い始めた初心者です。 1~10まで足すプログラムを作りたいのですが、自分なりに以下のように組んでみました。合っているか分からないので、詳しい方いたら教えていただきです。 (アドレスは適当です。) FFF100 > MOV.L #200100,ER1 FFF106 > MOV.B #00,R0L FFF108 > MOV.B #0A,ROH FFF10A > INC.B #1,R0L FFF10C > CMP.B R0L,ROH FFF10E > BNE FFF10A FFF112 > MOV.B R0L,ER1