dポイントプレゼントキャンペーン実施中!

ワンボードマイコンMP-Z80のプログラムを勉強しているのですが、
次の二つの問題がわかりません。
1)8100(H)番地~813F(H)番地に格納されているデータを
8200(H)番地以降にコピーせよ。
2)8100(H)番地から810F(H)番地に格納されているデータを8ビットの
符号付絶対値表現とみなしたとき、各データを2の補数表現に変換し、
8200(H)番地から格納せよ。

1)は
LD HL,8100
LD DE,8200
LD A,40H
LD BC,A
LDI
LDIR
HALT
でいいのでしょうか。2)はまったくわかりません。
お願いします。

A 回答 (8件)

回答者の方は今までのやりとりでもうほとんど解を得ていると思うのですが、なんか楽しそうなので一言。


nda23さんのCPI命令の使い方はシブいですね。私もZ80は30年選手ですが初めて見たかも。

私ならここは
LD HL,8100H
LD DE,8200H
LD B,16
LOOP:
LD A,(HL)
; ここで符号付き絶対値から2の補数表現に変換(後述)
LD (DE),A
INC HL
INC DE
DJNZ LOOP
HALT
とします。INC HL, INC DEで(オリジナルZ80なら)6クロック×2、DJNZは14クロック(13かも)で合計26(25)クロック、CPIとJP PEの組み合わせだと16+10で同じく26クロックですがDJNZを使うのだとCレジスタが空きます。データ量が256バイト以内と少ないならこちらのほうが素直かと思いました。

符号付き絶対値から2の補数表現への変換ですけれど、これはTacosanさんのが良さそうですね。

あるいは、ちゃんと考えてないのでしくじっているかもしれませんがこんな方法ではどうですか。
符号付き絶対値というのは、ある値の2の補数表現をAとして
A (A=0~127)
128-A (A=-0~-127)
ですから、(HL)に符号付き絶対値が入っているとして
LD A,(HL)
RLCA
SBC A,A  ; (HL)が正だったとき0, 負だったとき255(0FFH)が入る
LD C,A
AND 7FH  ; (HL)が正だったとき0、負だったとき127(7FH)
ADD A,(HL) ; (HL)が正だったとき(HL)、負だったとき(HL)+127
XOR C   ; (HL)が正だったとき(HL)、負だったとき255-((HL)+127) = 128-(HL)
というコードはどうでしょう。オリジナルZ80で37クロック、8バイト、分岐なしです。レジスタを一個使いますし、速くもないからイマイチですか。
もう一ひねりできるとマシなコードになりそうですけれど。
(Tacosanさんのは値が正の時27クロックで済みますし、負の時でも37クロックで8バイトですね。LD A,(HL)のところから数えて。)
    • good
    • 0

>JP  NZ,LOOP ;BC≠0ならLOOPへ分岐


>ではだめでしょうか

ダメです。
CPIは INC HL、INC、DEC BC とすべきところを横着して、1命令で
やっているのです。比較結果を云々するためではありません。
最後の DEC BC の結果、BC=0だとP/VがEvenになり、そうでなければOddになります。
それを条件に分岐するのです。命令(ニモニック)の意味が書かれている参考書をお持ちでしょ?
そういうの無しで、プログラムできませんし、勉強にもなりませんよ。
    • good
    • 0

A に符号付き絶対値表現が入っているとして, これを 2の補数に直すなら


BIT 7, A
JR Z, isPositive
NEG
XOR A, 80H
isPositive:
になる... のかな? フラグ変化が今一つわからん....
    • good
    • 1

(1)LDIRの動作は知っているんでしょ?


だったら、正直にやればいいと思うんですけど。
  LD  HL,8100H  ;HL←8100H 転送元データのアドレス
  LD  DE,8200H  ;DE←8200H 転送先データのアドレス
  LD  BC,0040H  ;BC←0040H 転送バイト数
  LDIR         ;(DE++)←(HL++)×BCが示す回数
(2)少しひねった問題だけど、同じでしょう。
  LD  HL,8100H
  LD  DE,8200H
  LD  BC,0010H
LOOP:
  LD  A,(HL)   ;A←(HL) HLの示すアドレスからAに代入
  NEG        ;A←Aの「2の補数」
  LD  (DE),A   ;(DE)←A DEの示すアドレスへAを格納
  CPI         ;HL++,DE++,BC--
  JP  PE,LOOP ;BC≠0ならLOOPへ分岐

間接アドレス指定が理解できないと苦労します。というか、ここが
コンピュータプログラムのセンスなんですが、これは勉強しても
なかなか身に着かない。(だから個人的センスなんですが…)
もし、どうしようもなく理解できない時は、アドレス感覚の無い
言語(Java、Basic、COBOL等)を勉強すべきです。
私の30年以上の経験から言いますと、世にSEですと威張っている人で
間接アドレス指定の何たるかが分かっている人は3割くらいです。
    • good
    • 1
この回答へのお礼

回答ありがとうございます。
最後の
JP  PE,LOOP ;BC≠0ならLOOPへ分岐

JP  NZ,LOOP ;BC≠0ならLOOPへ分岐
ではだめでしょうか?

お礼日時:2008/05/15 18:27

(1)


LD HL, 8100H
LD DE, 8200H
LD BC, 0040H
LDIR
(2)
LD HL, 8100H ; src
LD DE, 8200H ; dst
LD B, 10H ; counter
LD C, FFH ; ビット反転用
LOOP:
LD A, (HL) ; srcから
XOR C   ; ビット反転して1加えると2の補数
INC A
LD (DE), A ; dstへ
INC HL
INC DE
DJNZ LOOP ; Bレジスタの数だけ繰り返し

でいいと思います。
確認できる環境がないので未検証ですが。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

お礼日時:2008/05/15 18:22

BC と (BC) では意味が全く違います. 今は「BC レジスタの内容」なので (BC) はますますダメです.


で, なんですが.... BC に 40H を入れたいのに, A を使う必要があるんでしょうか?
    • good
    • 0
この回答へのお礼

BCに0040という16ビットの値を直接入れればいいのでしょうか?

お礼日時:2008/05/15 18:03

2の補数というのは、例えばどんなときに使うかという一例をあげますと・・・



引き算命令がないような小規模マイコン減算をするときや、マイコン無しで減算器を作ったりするときは・・・

引く数を2の補数にして、引かれる数に加算する。

とか、します。

論理演算の否定論理とか分かりますか?

論理演算とか2の補数の解説は、電子技術の文部検定教科書なんかにも書いてあります。
    • good
    • 0

1)


LD BC, A
なんてことはできません (レジスタの大きさが異なっているので). あと, LDI してから LDIR をする意味がわからん.
2)
「符号付き絶対値表現」とか「2の補数表現」でどのように数値を表すかは理解できてますか?
    • good
    • 0
この回答へのお礼

1)は
LD HL,8100
LD DE,8200
LD A,40H
LD (BC),A
LDIR
HALT
でいいのですか?

お礼日時:2008/05/15 16:40

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!