web-dev-qa-db-ja.com

64ビットモードはプッシュおよびPOP命令をサポートしていません

NASMは「命令は64ビットモードではサポートされていません」のようなエラーを返し、何をすべきか理解できませんでした。

対象の命令はpop ecxおよびPush ecx手順。それらの代わりに何を使用できますか、この問題を修正する他の方法はありますか?

11
Konko

一般的な考え方は、通常、フルレジスタ、つまり64ビットモードの64ビットレジスタをプッシュおよびポップすることです。 Pushのデフォルトのオペランドサイズは64ビットであり、32ビットのオペランドサイズは使用できません。 各プッシュ命令はx64で8バイトの倍数をプッシュしますか? (はい、特に16ビットプッシュを使用する場合を除きますが、32ビットは使用できません)。

64ビットモードでは32ビットレジスタをプッシュできません。代わりに、必要な32ビット値を含む64ビットレジスタ全体をプッシュしてポップできるため、Push raxではなくPush eaxになります。メモリ参照についても同様です。Push qword ptr[rax]はできますが、Push dword ptr[rax]はできません。

しかし:64ビットモードでもプッシュできます:

  • 8または32ビットの即値符号が64に拡張されました。これは通常、最適化としてアセンブラーによって自動的に処理されます(Push 1を実行すると、最もコンパクトなエンコードでエンコードされます。これは6A01になります。つまり、imm8オペランド)。これは アセンブラが選択する幅の幅に関係なく、Push Word 1 を明示的に指定しない限り、常に64ビットのプッシュです。

  • fsおよびgsセグメントレジスターレジスターcsdsesssレジスター(64ビットモードでは重要ではなく、 movではなく Push で読み取られ、将来の使用のためにこれらのプッシュ/ポップオペコードが解放されます)。

    例外として、セグメントレジスタはzeroで拡張されるか、16ビットの移動でスタックにプッシュされます(つまり、スタックの他の48ビットは未変更のまま); pop fsおよびpop gsはこれらの余分なビットを破棄するだけなので、これはそれほど問題ではありません。

Push imm64Push low32/mov dword [rsp+4], high32でエミュレートできます。またはmov r64, imm64/Push r64; (メモリではなく)movは、64ビットの即値を取得できる唯一のx86-64命令です。


16ビットのオペランドサイズ(66h接頭辞)を使用すると、RSPを8ではなく2に調整する16ビットのプッシュを実行できますが、通常は、これを行わないでください。 16ビットポップまたはその他の方法で修正します。

  • 16ビットレジスタ(Push ax)およびメモリ参照(Push Word ptr[rax]);
  • 8ビット符号拡張または16ビット即値。

8ビットレジスタはどのモードでもプッシュできません(より広いレジスタの一部を除く)。64ビットモードでは32ビットは使用できません プレフィックスREX.W=0を付けても

18
Matteo Italia