Это все из тома 2 Руководства разработчика программного обеспечения для архитектуры Intel 64 и IA-32 .
FCOMI
устанавливает только некоторые из флагов, которые CMP
делает.Ваш код имеет %st(0) == 9
и %st(1) == 10
.(Поскольку они загружаются в стек), обращаясь к таблице на стр. 3-348 в томе 2А, вы можете видеть, что это случай "ST0 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
имеет значение true, только если CF = 0 и ZF = 0, поэтому он не будет принят в неупорядоченном случае.Если вы хотите, чтобы в неупорядоченном случае использовался тот же путь выполнения, что и ниже, или равный, тогда ja
- это все, что вам нужно.
Здесь вы должны использовать JA
, если хотите, чтобы он печатался (т.е.. if (!(f2 > f1)) { puts("hello"); }
) и JBE
, если вы этого не сделаете (соответствует if (!(f2 <= f1)) { puts("hello"); }
).(Обратите внимание, что это может немного сбить с толку из-за того, что мы печатаем, только если мы не прыгаем).
Относительно вашего второго вопроса: по умолчанию 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