0 #z80 Aレジスタの0x00~0x0Fを16進数変換 みんなに公開

https://mechaag.tumblr.com/post/115002824017/daa命令の��%8# 0

daa命令の技 
2015-03-30
※初出2010-02-25
頭が8bitのアセンブラモードになってるので、ちょうどいいので書いておく。ある意味究極の「技法」。
 adda #$90
 daa
 adca #$40
 daa
この4行のプログラムが何をやっているかというと、16進数への変換。aレジスタに入っている0x000x0fの値を'0''9'ないし'A''F'に変換する。'9'は文字コードで0x39'A'は文字コードで0x41だから、不連続部分があり、0x0a以上と以下で場合分けするのが普通だ。
 cmpa #$0a
 bcs  L01
 adda #$07
L01
 adda #$30
行数は同じ4行だが、冒頭のプログラムは6バイトなのに対して、こちらは8バイト要する。Cで書けば
  if (a < 10) {
    a += ‘0’;
  } else {
    a += 'A’ - 10;
  }
になる。余談だが
  a = “0123456789ABCDEF”[a & 0x0f];
というトリッキーな書き方もしばしば紹介される。しかし冒頭のアセンブリプログラムは条件分岐なしにそれを実現している。

daa命令がポイントで、これはもともとbcd演算(2進化10進数)のための補正命令。命令自体はこんな動作をする。
  下位4bitの処理: 0x0a以上か、ハーフキャリーフラグが立っていれば、0x06を加える。
  上位4bitの処理: 0xa0以上か、キャリーフラグが立っていれば、0x60を加える。
キャリーフラグとハーフキャリーフラグは今回の処理では関係ないので考えなくていい。おおざっぱにいえば上位と下位のそれぞれ4bitの値が10以上なら桁上がりさせる。0x0aなら0x10に、0xa0なら0x100にする。4bitずつ見た時に10進数として10100と読めるようにするわけだ(これが2進化10進数)。
たとえば最初のaレジスタの値が0x00なら(daaの動作は複雑なので説明も2段階にしてある)、
  adda #$90  0x00→0x90
  daa     0x900x90 (下位4bitの処理) 変わらず
         0x900x90 (上位4bitの処理) 変わらず
  adca #$40 0x90→0xd0
  daa     0xd00xd0 (下位4bitの処理) 変わらず
         0xd00x30 (上位4bitの処理) 0x60を加える
で、最終的に'0'の文字コード0x30になる。
最初のaレジスタの値が0x0aなら、
  adda #$90  0x0a→0x9a
  daa     0x9a0xa0 (下位4bitの処理) 0x06を加える
         0xa00x00 (上位4bitの処理) 0x60を加える。桁上がり発生
  adca #$40 0x00→0x41
  daa     0x410x41 (下位4bitの処理) 変わらず
         0x410x41 (上位4bitの処理) 変わらず
で、最終的に'A'の文字コード0x41となる。adcaでキャリーフラグを足し込んでいるので0x40ではなく0x41になるところがすばらしい。

ちなみに上記は6809を前提としているがZ80の場合こうも書ける。
  cp 0ah
  ccf
  adc a,30h
  daa
バイト数も行数も同じだが、こっちの方がわかりやすいかもしれない。ccfはキャリーフラグを反転する命令で、要は10以上の場合に次のadc命令で+1させるのが目的だ。そして結果が0x3a以上(実際は必ず+1されるから0x3b以上)になればdaa命令の働きで0x06が加算されるので、0x41以上の値になる。
6809にはキャリーフラグ反転命令がないので冒頭のような書き方になる。また一見、
 adda #$f6
 adca #$3a
 daa
で出来そうな気がするのだが(1行目は10以上の場合に桁上がりさせるため)、adcaでキャリーフラグが立ってしまい、daaの動作が変わってしまうのでうまくいかない。
これらテクニックはBresenham’s algorithmとして紹介している本もあるけれど、この人が考案したのかは定かではない。Bresenhamという人はdda(デジタル微分)による直線描画などでよく出てくる先生。よもやdaaとddaでごっちゃにされているなんてことはないと思うが(苦笑)。


* #programming



Newer
2015-03-30
Older
© 20152020 MechaAG 
0

メモを他の人に見せる

このメモを見せたい人に、このURL(今開いているページのURLです)を教えてあげてください

コメント(0)

  • someone

  • someone