Ut Video Codec Suite の x64 版をアセンブラ化するために、Intel のドキュメント等で勉強してたわけですが、一般的な注意点とか自分が遭遇した落とし穴とかについて書いておきます。対象読者狭すぎw

汎用レジスタやSSEレジスタは16本になるが、MMXレジスタは8本のまま。
そのまんま。x64 でわざわざ MMX 命令を使うこともあまりないでしょうけど。
汎用レジスタにおいて、32bitレジスタに結果を格納すると、対応する64bitレジスタの上位32bitはゼロになる(つまりゼロ拡張される)。一方、16/8bitレジスタに結果を格納しても、対応する64bitレジスタの他の部分(上位32bitを含む)は保存される。
たとえば、

mov rax, 0123456789abcdefh
mov eax,         01234567h

とすると rax = 0000000001234567h になるが、

mov rax, 0123456789abcdefh
mov  ax,             0123h

とすると rax = 0123456789ab0123h になる。よく忘れる。

REX プレフィックスが付くと、ah, bh, ch, dh は使えない。
「オペランドサイズが64bitになっている」「r8 以降のレジスタを使う」「bpl, spl, sil, dil を使う」のいずれかをすると REX プレフィックスが付き、ah, bh, ch, dh は使えない。つまり、以下は全てダメ。

movzx rbx, ah
movzx r8w, ah
mov sil, ah

以下は一見64bitレジスタを使っているが、オペランドサイズは64bitではないので大丈夫。

mov byte ptr [rdi], ah
movzx reg64, r/m32 は存在しない。(movsxd reg64, r/m32 は存在する)
32bit レジスタに結果を格納すると暗黙的にゼロ拡張されるので、そもそもこの命令は必要ない。参ったことに、手元にある「インテル エクステンデッド・メモリ64 テクノロジ・ソフトウェア・デベロッパーズ・ガイド リビジョン1.1」には誤植があって、movzx reg64, r/m32 ではなく movzx reg64, r/m16 が存在しないことになっていた。(これのせいでアセンブルエラーを直すのに30分ほどかかった)
movsxd の方は movsxd で、なんでニーモニックを movsx から変更しているのか不明である。変更しなくても不都合は無いと思うのだが…?
ml64 (x64 用のオブジェクトファイルを出力する MASM)では、r8 の下位 8bit を表すレジスタは r8l ではなく r8b である。r8l を使うとアセンブルエラーになる。
Intel のドキュメントでは r8l であるが、x64 を定義した AMD のドキュメントでは r8b になっているから。だがしかし、AMD のドキュメントでも sil は sil なんである。一貫性どこー?
ところで、gas とかだとどうなるんでしょうかね?

とりあえずこんなところでしょうかねー。

Trackback

no comment untill now

Add your comment now