- ベストアンサー
8085系プログラミングについての質問
- 8085系プログラミングの質問について解説します。
- 要約文2
- 要約文3
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
Tacosanさんが#2で回答されていることを試してみてください。 問題となっているところは乗算をしている58行目から66行目までにあります。ほかは(概ね)問題ありませんのでこの部分に集中してください。 61行目のMOV C,Aまで実行したとき、各レジスタに入っている値の意味を整理しましょう。それぞれのレジスタにはどういう値が入っていてどういう役割を持っていますか。HLレジスタペアはどうですか。DEレジスタペアは?。そしてCレジスタには何が入っていますか? 63行目のループに入った後、66行目で結果を格納するまでこのプログラムはどうやってかけ算を実行していますか? 一ステップずつプロセッサの動きを追ってみましょう。 うまくいっているときの動きの追い方はこんな感じです。 うまくいっている例として、03 02を入力したときです。 61行目まで実行すると各レジスタはこんな値になっているはずです。 HL=0000, DE=0003, C=02 あなたが考えたのと一致していますか? 次に63行目にすすみ、DAD D命令を実行します。レジスタは HL=0003, DE=0003, C=02 (HLにDEの値が加算された) あなたの想定通りですか? 64行目に進んでDCR Cを実行します。 HL=0003, DE=0003, C=01 [NZ] Cレジスタの値が1減ります。フラグはNZです。 65行目に進むとZフラグが立っていないのでJNZ命令を実行してLOOP:ラベルに戻ります。 63行目に戻ってDAD Dを実行します。レジスタは HL=0006, DE=0003, C=01 64行目、DCR Cを実行 HL=0006, DE=0003, C=00 [Z} 65行目、フラグがZなのでJNZでのジャンプは行われず66行目へすすみます。 66行目、SHLDを実行してHLレジスタに入っている0006が9002H,9003H番地のメモリに書き込まれます。 どうですか?あなたが想定した動きでしょうか。 これと同じことを問題の「うまく動かない」という状況の時にどうなっているか考えてみてください。61行目に達したときレジスタの値はどうなっていますか?そこから63行目、64行目と実行を進めてください。 ところで、#1への返答で「01x00のとき0100と表示されてしまう(0000となって欲しいのに)」ということを書かれていますね。"0100"と表示されるのはなぜか、この値はいったいどこからやってきたのか、というところからデバッグするという考え方もあります。でも、今回はまず上に示したようなステップを追う方法で考えてみてください。 動作を丁寧に追っていけば、「なぜ0100と表示されるのか」もわかると思います。 ========= ここからkfd03077さんへ:(質問者の方済みません。ちょっと貸してください。) このアセンブリ言語で用いている"DB"命令は「カレントロケーション(メモリ)にオペランドで示す値を格納する」という疑似命令です。"DB 0"で、メモリ上に1バイトの空間を確保し、それをオペランドの値0に初期化します。 DB命令で確保した空間にaa:, bb:などといったラベル(アドレスを示す)をつけているわけですのでこのコードで問題ありません。 つまり、メモリのどこかの1バイトに0(DBのオペランド)が格納され、aaとかbbとかはそのアドレスの値になっています。 おそらくほかのプロセッサ(8086など)のアセンブリ言語にある型付き定数定義と混同されているのだと思います。
その他の回答 (6)
- dummyplug
- ベストアンサー率58% (134/230)
>教えてくださってありがとうございます。なぜ[01 x 00]=[0100]になってしまうのか、わかりました。 プログラムの動作は理解されたのだと考えてコメントします。 まず、 >bb(C)ループカウンタの値が-1できないのでできないということはわかった ということですが、正確には「-1(デクリメント)できない」のではなく、「(0から)デクリメントすると桁借りが起こって255になってしまう」ということは理解されていますか? このプログラムのかけ算の仕組みは、bbの値(61行目でCレジスタに入る)の数だけ63行目のDAD Dを繰り返すこと、にあります。それは理解していますね? では、bbの値が0のとき、63行目のDAD Dは何回繰り返されますか?そしてそれは本来何回になっているべきだと考えますか? それで、その本来の回数だけDAD Dを実行するようにするにはどうしたらよいでしょう。 これらの問いにわかる範囲でいいのであなたの考えを書いてください。それでピンとこないようでしたら、具体的な例を示します。
ANo.3,5 です。たびたびすみません。 思い出しました。完全に勘違いしてました。失礼しました。
ANo.3 です。 ANo.4 さん、解説ありがとうございます。 > "DB"命令は そうなんですか。私が触れてた頃のアセンブラは DB ; Define Byte (8bit の値定義) DW ; Define Word (16bit の値定義) だったので、あれ?と思ったのでした。 後には DEFB, DEFW だったりしますが。 ともあれ、私の心配は無用だったわけですね。 どうもお騒がせしてすみませんでした。
レジスタの値がどう変化していくか追うことになりますが、 多くて覚え切れない場合は Excel を利用するなどして横長に並べ 無駄気味でも全部のレジスタ値の追跡するとモレなく追えます。 尚、以下のサブルーチンの動作が不明確だったので 追うのはやめておきました。 DISP EQU 0040H DHEX1 EQU 0043H DHEX2 EQU 0046H KEYIN EQU 004FH ところで LDA bb STA bb について、この命令は「値が示すメモリ番地とレジスタAとの間の転送」 です、値 aa, bb, dd はバイト定義なのでアドレスにしては 変な気がしますけどこれは意図通りですか? すると 0番地付近に書き込んだりしてますが 開発システムがこれを許してるのでしょうか...? 8085 は 0 番地はリセットエントリですから、普通は変です。 (許すシステムもありますが)
- Tacosan
- ベストアンサー率23% (3656/15482)
#1 にある「その後LOOP:以降に進むとどういう動きになりますか?」というところを, 8085 の気持ちになって実行すればわかると思います. もっとはっきりいうと, C が 0 のときにこのループは何回実行されますか?
- dummyplug
- ベストアンサー率58% (134/230)
なかなかよく書けていると思います。 本題に入る前に2,3注文を。 まず「動かない」とはどう動かないのかを書くようにしてください。あなたがどうなることを期待しているのか(なのに違う結果になってしまう)がわからないと答えられないことがあります。例えば、このプログラムは01x00を計算しようとするとどうなりますか?暴走するのですか?それとも何か答えを返しますか? それからアセンブリ言語のコードは長くなりがちですから、コードの位置を示せるように行番号などをつけてもらうか、細かくラベルまたはコメントを入れるようにしてください。例えば9行目のあたりには"; 被乗数の入力"、32行目あたりには"; 乗数の入力"、53行目には"; STEPキーの入力待ち"、58行目には"; aaとbbの値を取り出して乗算(aa*bb)を計算する"などです。 私が昔いた会社では全ての行にコメントを書くこと、という決まりがあったらしいです。それはやり過ぎかもしれませんが初心者のうちは細かくコメントを書くのが考えの整理という意味でも望ましいです。 本題ですが、乗算をしている58行目から66行目までのどこかに問題があることは明らかです。大した長さのコードではないので頭の中(あるいは実機があればそれでもいいですが)で一命令ずつプロセッサがどう動いているかを考えて動作を(期待しているのと違わないか)確認してください。 特に問題は乗数が00のとき、とわかっているので61行目のMOV C,Aを実行した後にCレジスタの内容が00Hになっているケースです。その後LOOP:以降に進むとどういう動きになりますか? このくらいのヒントでどうでしょうか。まだピンとこないようでしたらもうちょっと細かく解説します。が、ここまでコードを書けるのならこれくらいでわかりそうかと思います。 ところで、乗算の仕方は非常に単純な方法でこれはこれで有用なケースもありますが一般的にはちょっと効率が悪いです。出題者の意向がわからないのでこれでOKなのかもしれませんが、「乗算 アルゴリズム」などとして検索してみるともうちょっと様々な(フツーにマトモなものからどうしてそうなるのかちょっと見ではわかりにくいものまで)計算方法が見つかります。 興味があればそういうのも勉強してみてください。
補足
結果を書きいてないという指摘をしてくださってありがとうございます。結果ですが、まず[00 x 01]は[0000]と表示されます。しかし [01 x 00]は[0100]と表示されてしまい、掛け算が行われません。そのほかの計算はすべて正常動作します。bの値が0のとき、動きません。 そこを詳しく教えてください
補足
教えてくださってありがとうございます。なぜ[01 x 00]=[0100]になってしまうのか、わかりました。bb(C)ループカウンタの値が-1できないのでできないということはわかったのですが、それをどう直したら良いのかわからないので、プログラムで直し方だけでもいいので教えてください