PDP-11 MUL命令を、8086のアセンブリ言語に変換したメモ
作成中の、PDP-11アセンブリ -> 8086アセンブリ のトランスレーター(https://github.com/kusabanachi/p11trans)で、 MUL命令の変換部分を書いた
PDP-11 MUL命令
mul src, dest
- destがR0,R2,R4(偶数)の場合
- destがR1,R3,R5(奇数)の場合
- dest レジスタ = src * destの下位16bit
- 上位16bitは格納されない
8086 IMUL命令
符号付き乗算命令なので、x86ではIMUL命令が相当する
imul src
大まかな違い
どちらも同じ目的で使われる命令だが、PDP-11のmul命令がsrcとdestの2つのオペランドを指定するのに対して、8086のimul命令はdestがAXレジスタに固定される。
PDP-11のmul命令はdestレジスタの番号が偶数か奇数かで動作が変わるが、8086のimul命令は1パターン。
PDP11 mul --> 8086 imul の変換
PDP11 mulのdest(以下'dest'と表記)の値により、大きく4パターンに場合分けする
レジスタは
* R0 --> AX * R1 --> DX * R2 --> CX * R3 --> SI * R4 --> DI * R5 --> BP * --> BX(余り)
の変換割り当て。
'dest'がR0の場合
imul src ! ちょうどAX(R0)の位置なのでそのまま計算できる xchg ax, dx ! 'dest'+1がDX(R1)なので、8086計算結果の、上位16bitと下位16bitを交換すればOK
'dest'がR1の場合
mov tmp, ax ! tmpという名の領域に元のAXの値を退避 mov ax, 'dest' ! 'dest'の値をAXにコピーする imul src ! AXに'dest'の値が入ったので計算 mov 'dest' ax ! 計算結果の下位16bitを'dest'(R1)に入れる mov ax, tmp ! 元のAXの値を復元
- 8086IMUL命令で計算結果がAXとDXに入る。
- DX(R1)は計算結果の下位16bitが最終的に入るので、元の値は消えて良い
- AX(R0)の値は変化して欲しくないので、退避/復元する
'dest'がR2,R4の場合 (R0以外の偶数レジスタ)
mov tmp, ax ! tmpという名の領域に元のAXの値を退避 mov tmp2, dx ! tmp2という名の領域に元のDXの値を退避 mov ax, 'dest' ! 'dest'の値をAXにコピーする imul src ! AXに'dest'の値が入ったので計算 mov 'dest' dx ! 計算結果の上位16bitを'dest'に入れる mov 'dest+1' ax ! 計算結果の下位16bitを'dest+1'に入れる mov ax, tmp ! 元のAXの値を復元 mov dx, tmp2 ! 元のDXの値を復元
- 計算結果がAXとDXに入るので、AXとDXの元の値の退避/復元をする
計算結果を'dest'と'dest+1'に格納する
元の'dest'と'dest+1'の場所の値は、計算結果で上書きされてどうせ消えるので、AXとDXの退避場所に使ってxchg命令を使うと、命令数を減らせられる
xchg 'dest', ax ! 'dest'の場所に元のAXの値を退避させ、'dest'の値をAXに入れる mov 'dest+1' dx ! 'dest+1'の場所に元のDXの値を退避 imul src ! AXに'dest'の値が入ったので計算 xchg 'dest' dx ! 計算結果の上位16bitを'dest'に入れる。DXには元AXの値。 xchg 'dest+1' ax ! 計算結果の下位16bitを'dest+1'に入れる。AXには元DXの値。 xchg ax, dx ! 元のAXとDXの値が逆になっているので交換する
'dest'がR3,R5の場合 (R1以外の奇数レジスタ)
mov tmp, ax ! tmpという名の領域に元のAXの値を退避 mov tmp2, dx ! tmp2という名の領域に元のDXの値を退避 mov ax, 'dest' ! 'dest'の値をAXにコピーする imul src ! AXに'dest'の値が入ったので計算 mov 'dest' ax ! 計算結果の下位16bitを'dest'に入れる mov ax, tmp ! 元のAXの値を復元 mov dx, tmp2 ! 元のDXの値を復元
1つ上の偶数レジスタの場合と比べて、'dest+1'に値を格納しないという違いのみ
同様にして命令数を減らすと、
mov tmp, dx ! tmpという名の領域に元のDXの値を退避 xchg 'dest', ax ! 'dest'の場所に元のAXの値を退避させ、'dest'の値をAXに入れる imul src ! AXに'dest'の値が入ったので計算 xchg 'dest' ax ! 計算結果の下位16bitを'dest'に入れる。AXには元AXの値。 mov dx, tmp ! 元のDXの値を復元