パスワードを忘れた? アカウント作成
78521 journal

L.Entisの日記: Intel64 アセンブラプログラミングメモ 1

日記 by L.Entis
私が Intel64/AMD64 用アセンブラを書く日はまだしばらく先のような気がしますが、とりあえず現存する32ビット用 MASM コードを64ビットに書き換える場合、及び今後書く32ビット用MASMコードを64ビットへ移行する際にあらかじめ気をつけておいたらよさそうなことを洗いなおすために、IA32(32ビットネイティブモード)と IA32e(64ビットモード)の主な違いをまとめてみる。


・オペランドサイズは、従来の32ビット/16ビット移行時と同じようにプリフィックス命令で切り替える。オペランドサイズを64ビットに切り替える新しい REX プリフィックス命令は、従来のエンコーディングで INC/DEC 命令に相当するため、同命令は使用できない。
・REX プリフィックスには、レジスタ番号を拡張するフィールドが存在し、続く従来命令エンコーディングの reg, r/m フィールド, 及び SIB(Scale/Index/Base)バイトのレジスタ番号にそれぞれ上位1ビットを追加し、最大16個の汎用レジスタ及び SSE レジスタ表現を可能にする。
・64ビットモードのデフォルトのオペランドサイズは32ビット、アドレスサイズは64ビットである。
・暗黙にRSP(64ビットスタックポインタ)を参照する命令(PUSH,POP,PUSHF,POPF,ENTER,LEAVE)のオペランドサイズは64ビットとなり、32ビットは不可となる。
・SIB バイトの特殊なエンコーディング(従来ESPがインデックスに使用できない等)が変更された。
・32ビットオペランドサイズの演算は、上位32ビットが0拡張された形で出力レジスタに格納される。
・すべての汎用レジスタ(GPR)への下位16ビット、及び下位8ビット表現が可能で、この場合のレジスタ出力は上位ビットを変更しない。(また、32ビットモードまでの変則的な8ビットレジスタ表現(AH,BH,CH,DH)は64ビットモードでは別のレジスタの下位8ビットに置き換えられるため存在しない)。
・メモリオペランドを [disp32] 形式で指定する場合、実効リニアアドレスは、最上位ビットを64ビットまで符号拡張したものを RIP(64ビット命令ポインタ)に加算して求める。但し SIB バイトを指定する場合には32ビットモード(レガシーモード)と同じになる。



ん~~~~、と言うことは、32ビットの MASM コードでアドレスに関連するレジスタ操作の部分を rax, rbx, rcx, rdx,... などの64ビットレジスタの名前で書いておいて、32ビットでは

rax TEXTEQU <eax>
...


などと取りあえずしておいて、64ビット化したときに TEXTEQU を外して、ポインタ変数のサイズ(型)を変更するなどの対応をしてあげれば比較的スムースかな?
inc/dec 命令はマクロで対応できるだろうし…
まあ、それだけじゃないというか、もう少し面倒な部分はあるけれど(アドレスの計算と32ビットの計算が混在しているような場合など)、まあそう言うところはあらかじめ

IF _INTEL64_
    .ERR ここは云々かんぬんであれこれなので注意!
ENDIF


みたいなのを該等箇所に埋め込んどけば後々楽かな?
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • by Anonymous Coward on 2009年08月26日 13時10分 (#1629440)

    x86-64でもINC/DECは使えますよ。REXで潰されたものとは別の2バイト表現があるので、アセンブラを使っているなら問題ありません。また、AHなどもREXと併用できないだけで、32ビットで可能だったものは64ビットでも平気です。movsx rax,dlは可能ですが、movsx rax,dhやmov dil,ah(dilはediの下位8ビット)はダメという具合です。

    #結構前の日付なので文字通りコソコソとACで

typodupeerror

UNIXはただ死んだだけでなく、本当にひどい臭いを放ち始めている -- あるソフトウェアエンジニア

読み込み中...