2011-07-26 8 views
1

現代のマシンで古いプロジェクトをコンパイルしようとしています。私はこの古いプロジェクトがGCC/GASの古い(2.x)バージョンを使用していたので、最新のバージョンでコンパイルできるように、それをクリーンアップする必要があることを知っています。古い32ビットGASコードを現在のGASアセンブラに変換する必要があります(pushfl/popl)

問題のコード:

__get_flags: 
    pushfl 
    popl %eax 
    ret 

gaspushflは命令ではないと文句を言い。私が読んだところでは、これは廃止予定の古いGNUニーモニックですが、確かにx86_64相当のものがなければなりませんか?

このコードをx86_64に変換する方法に加えて、pushflpushfqなどのニーモニックがどこに記述され、定義され、文書化されているかを説明できるのは素晴らしいことです。私は、ガスの作品であることはかなり確信しています...

注:私は2.21

答えて

2

にはgcc 4.6.1およびガスで次のようにこれをコンパイルしたい:

static inline u16 __get_flags(void) { 
    u16 flags; 
    asm ("pushf\n\t" 
     "pop %0" : : "+r"(flags) : "cc"); 
    return flags; 
} 

が実際にポータブルする必要があります両方の64/32bit、x64/x86。しかし、それはあなたに条件コードを与え、状態レジスタの上位部分ではありません。 64ビット(ロング)モードで実行するときにフラグレジスタの内容全体が必要な場合は、(またはその他の64ビット数)オペランドを使用してPUSHFQ命令名を使用してください。

+0

私は厳密にこれを行うには、元の例では 'eax'でしたが、ここで(pushfの後で)これを試してみると、エラー:'エラー: 'pop 'のオペランドタイプの不一致。ありがとう! –

+0

私はx86_64のすべてのスタック操作が暗黙的に64ビットであるため、32ビットの対応は利用できませんが、16ビットのものは使用できます。 http://www.x86-64.org/documentation/assembly.html –

+1

はい、あなたは正しいですか?x86_64の 'push /' pop'は64bitであるか、明示的に16bitに上書き可能です。これは主な違いです。32bitプッシュ/ 64ビットモードで動作しているときにポップアップする。 gccインラインアセンブリを使用する場合は、レジスタ名を指定する必要はなく、プレースホルダを使用できるため、レジスタの幅/名前に依存しない特定の状況でコードを作成することができます。あなたのコードが上記の関数をどのように使用するかについてもう少し詳しく知ることは役に立ちます。 –

0

評判が50でないため、回答にコメントを追加できません。とにかく:答えで

"pop %0" : : "+r"(flags) : "cc"); 

次のようになります。

"pop %0" : "=r"(flags) : : "cc"); 

を構文はasm(code : outputs : inputs : clobbers)で、何がしたいことは、ASMブロックからの出力ですレジスタであることをフラグではありませんので入力として使用されます。 (私はこれを試して、それは私のために働いた、私も64ビットのintを使用して)

関連する問題