前回はx86命令(16bit)のうち「8086レベル」のシフト、ローテイト命令の動作を復習。コマケーところがメンドイものどもでした。前回は実機(実際はQEMUのエミュレーションだけれども)での動作確認をしなかったので、今回はデバッガで動かしながらの動作確認です。メンドイのでサラっと流していくぜ。いいのか?
※「ぐだぐだ低レベル プログラミング」投稿順indexはこちら
※実機動作確認には以下を使用させていただいております。
今回動かしてみるアセンブリ言語ソース
上記の7種(ニーモニック的には8種)の命令を「テキトーに見繕ったオペランドにて」動作させてみるものが以下に。
org 100h section .text start: mov sp, stacktop mov bx, workb mov si, workw mov bp, sworkw mov word [bp], 0ABCDh mov ax, 1234h mov cx, 0004h mov dx, 0A5A5h test: shl dx, 1 mov dx, 0A5A5h sar dx, 1 mov dx, 0A5A5h shr dx, 1 nop rcl byte [bx], cl mov al, [bx] rcr word [si], cl mov ax, [si] rol word [bp], cl mov ax, [bp] ror al, cl fin: mov ax, 0x4c00 int 0x21 section .data align=16 workw: dw 5678h workb: db 12h section .bss align=16 sworkw: resw 4 resb 2048 stacktop:
なお、上記はMS-DOS超上位互換の FreeDOS 上の NASMアセンブラ用のソースです。NASMアセンブラはインテル式表記を受け付け、マイクロソフト社のMASMとも似てないこともない(微妙)アセンブラ(かなり強力)デス。
動作確認
上記のソースは、NASMだけでオブジェクトファイルを作れる .COM モデル用なので、以下のコマンドライン一発で実行可能なオブジェクトが得られます。
nasm sft.asm -fbin -o sft.com
動作確認は、FreeDOS上の debug コマンド(御本家 マイクロソフト社のdebugと同名で「互換」のデバッガだが、何気に超拡張されている)を使って行っております。
まずは、シフト系3兄弟から。着目すべきところに下線を引いてあります。
まず赤線が、左論理シフトSHL命令です。実際には左算術シフトSAL命令と同じ動作となりますが。DXレジスタの値を1ビット左シフトしてます。その際、CY(キャリーフラグ)がNC(0)からCY(1)へと変化していることをご確認くだされ。
お次は青線の算術右シフト命令です。これまた1ビットシフト形式。DXレジスタの値を右シフトしていますが、算術右シフトなので、DXレジスタのMSBの値は1のまま維持されます。LSBからシフトアウトされた値はCYに入りますが、元が1だったので変化なしです。
3つ目黄色は論理右シフト命令です。上の算術右シフトと同じ値に対して作用していますが、MSBには0がシフトインされてくるので結果のDXの値は異なることになります。
CISCらしく、メモリオペランドをとる命令としてあります。またシフト回数はCLレジスタに格納されている値を使う形式です。
赤線のRCL命令は、DS:0142h 番地に置かれた値 0x12 をキャリーフラグを含めた左ローテイトする命令です。0x12の下ニブルの0x2が結果の上位ニブルとなり、0x12の上位の0x1の1がCYフラグに追い出されることになります。また、ローテイト開始時点でCY=1であったので、その値が巡り巡ってメモリ上の0x28のビット3を立てることになってます。
青線のRCR命令は、ワード(繰り返しますがx86では16ビットです)幅であること、右ローテイトであることを除けば動作は「以上と」同文っす。
ここで注意するのは、「キャリーを含めない」のはローテイトするデータに対してであって、CYフラグとOV(オーバフロー)フラグは影響を受けることです。x86に精通されている姉貴兄貴の皆さんはよくご存じのとおり、x86で何か演算すれば漏れなくフラグに影響するのです。その辺の副作用を抑えたモダンなRISCとは設計思想が異なります。
上記の上の赤字は左ローテイトのROL命令です。メモリ上におかれた0xABCDを4ビット左ローテイトしているので結果が0xBCDAになってます。この処理の副作用としてCYがクリアされ、OVがセットされておると。
青地の方はレジスタALに対するバイト幅の右ローテイトです。4ビットのローテイトなので、ちょうど上下のニブル(4ビット)が入れ替わった形。
アセンブラ書いている分には何やらいろいろ使えそうな命令どもだが、C書いていたら<<と>>くらいしかないからなあ。活用はライブラリやコンパイラにお任せ?他の命令もお任せっちゃお任せか。