N.Y.Cityのまちかど
CASL_vs_Z80
CASL IIとZ80
はじめに
私のアセンブラ言語歴は、高校の授業で学んだZ80アセンブラ(と、趣味でちょこっとだけ本を読んだIntelアセンブラ)だけなのだが、専門学校の教員になって、CASL IIを教えるようになった。(CASL IIは基本情報技術者試験のために作られた仮想言語なので、これをアセンブラ言語歴と言っていいのかはやや疑問ではあるが・・・)
高校で学んだZ80を思い出しながらCASL IIの授業をしていたら、設計思想が異なるために微妙に異なる挙動をしていたり、うっかりミスするポイントがあったので、反省がてらこのページに記録しておく。(他にもあったら教えてください)
シフト演算の扱い
シフト演算を用いると、乗算器・除算器を持たないCPUで乗除演算を高速化することができる。なぜならば二進数を1ビット左シフトすることは値を2倍することに相当し、1ビット右シフトすることは値を半分にすることに相当するからで、シフト命令を使えば2のべき乗倍(2,4,8,…倍)または2のべき乗分の1(2,4,8,…分の1)の計算を高速に処理することができる。
対象レジスタの全ビットを左右にシフトする命令を「論理シフト命令」と言い、符号なし数のみを扱う場合にはこれだけで話は済む。例えば(100)10=(01100100)2を左1ビット論理シフト・右1ビット論理シフトすると
(100)100=(01100100)2
(01100100)2 ← 1 = (11001000)2=(200)10
(01100100)2 → 1 = (00110010)2=(50)10
となり、たしかに2倍・半分になっている。
ところが、符号付数を利用して、負の数に右論理シフトを行うと矛盾が生じる。符号付数は最上位ビットを符号ビットとして、符号ビットが1の値は二の補数で表現された負の数と解釈するから、(-32)100を半分にして(-16)100を得るつもりで右シフトすると
(-32)100=(11100000)2
(11100000)2 → 1 = (01110000)2 = (112)100
となってしまう。この現象の原因は負の数を半分にしても負のままであるはずなのに、符号ビットに0が入ってきた(=正の数として解釈される)ためである。
そのため、単純に全ビットを左右にシフトするのではなく、符号ビットを保護する機能を備えた「算術シフト命令」が存在する。この算術シフト命令の扱いが、CASLとZ80で異なっている。
CASL IIの場合
CASL IIは、算術/論理および左/右をそれぞれ組み合わせた、4つのシフト命令を持っている。
左(Left) | 右(Right) | |
論理(Logical) | SLL [Shift Left Logical] 左論理シフト 《符号ビット残さない》 |
SRL [Shift Right Logical] 右論理シフト 《符号ビット残さない》 |
算術(Arithmetic) | SLA [Shift Left Arithmetic] 左算術シフト 《符号ビット残す》 |
SRA [Shift Right Arithmetic] 右算術シフト 《符号ビット残す》 |
左算術シフトでは、最上位ビット(符号ビット)は動かさず、残りの0番ビット~14番ビットまでを左シフトする。この時、空いた最下位ビットには0が入る。
右算術シフトでは、最上位ビット(符号ビット)は動かさず、残りの14番ビット~0番ビットまでを右シフトする。この時、空いた上位ビットには、「符号ビットがコピー」される。そのため、元の値が正の値(=符号ビットが0)なら0が埋まり、元の値が負の値(=符号ビットが1)なら1が埋まって、常に演算後の符号が正しく残るようになっていて、「値をいくら倍・半分にしても符号は元の値と同じ」という原則を維持している。
Z80の場合
Z80の場合、CASL IIと違って「SLL[Shift Left Logical]=左論理シフト」が存在しない。その代り、SLA[Shift Left Arithmetic]=左算術シフト」が符号ビットを考慮しない「左論理シフト」と同じ動きをする。
左(Left) | 右(Right) | |
論理(Logical) | ―― | SRL [Shift Right Logical] 右論理シフト 《符号ビット残さない》 |
算術(Arithmetic) | SLA [Shift Left Arithmetic] 左算術シフト 《符号ビット残さない》 |
SRA [Shift Right Arithmetic] 右算術シフト 《符号ビット残す》 |
その結果、Z80で負の値を左算術シフト(SLA)していくと、計算結果が突然正の値に変わる可能性がある。逆に左算術シフト(SLA)していくと、計算結果が突然負の値に変わる可能性がある。これは「値をいくら倍・半分にしても符号は元の値と同じ」という原則に反している。その代わり、左算術シフトした結果符号が反転してしまった時、それは計算結果がオーバフローして正しく表現できなくなってしまったことを意味する。
現在ご覧のページの最終更新日時は2018/03/11 21:09:32です。
Copyright (C) N.Y.City ALL Rights Reserved.
Email: info[at]nycity.main.jp