これは、第2巻からすべて Intel 64 and IA-32 Architectures Software Developer's Manualsです。
FCOMI
は、CMP
が実行するフラグの一部のみを設定します。あなたのコードは%st(0) == 9
と%st(1) == 10
です。 (スタックされているためスタックされています)、Volume 2Aの3-348ページの表を参照すると、これは "ST0 < ST(i)"であることがわかります。したがって、ZFとPFがクリアされ、 CF。一方、 3-544 Vol。図2Aを参照すると、JG
は「大きい場合は短くジャンプする(ZF = 0およびSF = OF)」を意味することが読み取れます。つまり、符号、オーバーフロー、ゼロフラグをテストしていますが、FCOMI
は符号またはオーバーフローを設定しません。
ジャンプする条件に応じて、可能な比較結果を見て、ジャンプするタイミングを決めてください。
+--------------------+---+---+---+
| Comparison results | Z | P | C |
+--------------------+---+---+---+
| ST0 > ST(i) | 0 | 0 | 0 |
| ST0 < ST(i) | 0 | 0 | 1 |
| ST0 = ST(i) | 1 | 0 | 0 |
+--------------------+---+---+---+
私はそれが簡単に把握できるように、この小さなテーブルを作った:
+--------------+---+---+-----+------------------------------------+
| Test | Z | C | Jcc | Notes |
+--------------+---+---+-----+------------------------------------+
| ST0 < ST(i) | X | 1 | JB | ZF will never be set when CF = 1 |
| ST0 <= ST(i) | 1 | 1 | JBE | Either ZF or CF is ok |
| ST0 == ST(i) | 1 | X | JE | CF will never be set in this case |
| ST0 != ST(i) | 0 | X | JNE | |
| ST0 >= ST(i) | X | 0 | JAE | As long as CF is clear we are good |
| ST0 > ST(i) | 0 | 0 | JA | Both CF and ZF must be clear |
+--------------+---+---+-----+------------------------------------+
Legend: X: don't care, 0: clear, 1: set
言い換えれば、条件コードは、符号なしの比較を使用するためのものと一致します。 FMOVcc
を使用している場合も同様です。
fcomi
のいずれか(または両方)のオペランドがNaNの場合は、ZF=1 PF=1 CF=1
に設定されます。 (FP比較には、>
、<
、==
、または順序付けられていない4つの結果があります)。あなたのコードがNaNで何をしているか気にするなら、余分にjp
またはjnp
が必要な場合があります。ただし必ずしもそうではありません。たとえば、ja
は、CF = 0およびZF = 0の場合にのみ真であるため、順序付けられていない場合は取り込まれません。順序付けされていないケースに同じかそれ以下のパスを使用させたい場合は、ja
だけ必要です。あなたがいない場合、あなたがそれを印刷したい場合は
ここでは、JA
を使用する必要があります(すなわち。if (!(f2 > f1)) { puts("hello"); }
)とJBE
(if (!(f2 <= f1)) { puts("hello"); }
に対応)。 (ジャンプしなければ印刷するという事実のため、少し混乱するかもしれないことに注意してください)。あなたの2番目の質問については
:デフォルトfcomi
で何をポップしません。あなたはその近くのいとこfcomip
がポップする%st0
をしたい。使用後は常にfpuレジスタスタックをクリアする必要があります。したがって、すべてのプログラムで、メッセージを印刷することを前提に、このようなメッセージが出力されます。
.section .rodata
msg: .ascii "Hallo\n\0"
f1: .float 10.0
f2: .float 9.0
.globl main
.type main, @function
main:
flds f1
flds f2
fcomip
fstp %st(0) # to clear stack
ja leb # won't jump, jbe will
pushl $msg
call printf
addl $4, %esp
leb:
pushl $0
call exit
非常に印象深い答えです。優れている。一つの小さなコメント: 'ja'の反対は' jb'ではなく 'jb'です。 –
@Ray Toal:あなたは絶対に正しいです。このケースでは何の違いもありませんが、私はそれをより意味をなすので、例を変更しました。 – user786653
nice!本当にありがとう! – JustMaximumPower