Todo esto proviene del Volumen 2 de Intel 64 and IA-32 Architectures Software Developer's Manuals.
FCOMI
establece solo algunos de los indicadores que CMP
hace. Su código tiene %st(0) == 9
y %st(1) == 10
. (Dado que se trata de una pila en la que se cargan), consulte la tabla de la página 3-348 del Volumen 2A y verá que este es el caso "ST0 < ST (i)", por lo que borrará ZF y PF y establecerá CF. Mientras tanto en la pág. 3-544 vol. 2A puede leer que JG
significa "salto corto si es mayor (ZF = 0 y SF = OF)". En otras palabras, está probando el signo, el desbordamiento y las banderas cero, ¡pero FCOMI
no establece el signo ni el desbordamiento!
Dependiendo de las condiciones en las que desea saltar, debería ver los posibles resultados de comparación y decidir cuándo desea saltar.
+--------------------+---+---+---+
| Comparison results | Z | P | C |
+--------------------+---+---+---+
| ST0 > ST(i) | 0 | 0 | 0 |
| ST0 < ST(i) | 0 | 0 | 1 |
| ST0 = ST(i) | 1 | 0 | 0 |
+--------------------+---+---+---+
que he hecho esta pequeña mesa para que sea más fácil de averiguar:
+--------------+---+---+-----+------------------------------------+
| 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
En otras palabras, los códigos de condición coinciden con los que para el uso de comparaciones sin firmar. Lo mismo ocurre si está usando FMOVcc
.
Si uno (o ambos) operando a fcomi
es NaN, establece ZF=1 PF=1 CF=1
. (Las comparaciones FP tienen 4 resultados posibles: >
, <
, ==
, o no ordenadas). Si le importa lo que hace su código con NaNs, es posible que necesite jp
o jnp
adicionales. Pero no siempre: por ejemplo, ja
solo es verdadero si CF = 0 y ZF = 0, por lo que no se tomará en el caso desordenado. Si desea que el caso desordenado tome la misma ruta de ejecución que la siguiente o igual, entonces ja
es todo lo que necesita.
Aquí se debe utilizar JA
si desea que se imprima (es decir. if (!(f2 > f1)) { puts("hello"); }
) y JBE
si no lo hace (corresponde a if (!(f2 <= f1)) { puts("hello"); }
). (Tenga en cuenta que esto puede ser un poco confuso debido al hecho de que solo imprimimos si no saltamos).
En cuanto a su segunda pregunta: por defecto fcomi
no aparecerá nada. ¿Quieres su primo cercano fcomip
que aparece %st0
. Siempre debe borrar la pila del registro fpu después de su uso, así que todo en todo su programa termina así asumiendo que desea que se imprima el mensaje:
.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
Respuesta muy impresionante. Excepcional. Un comentario menor: el opuesto de 'ja' es' jbe', no 'jb'. –
@Ray Toal: Tienes toda la razón. Aunque no hará ninguna diferencia en este caso, cambié el ejemplo, ya que tiene más sentido de esa manera. – user786653
¡agradable! ¡Muchas gracias! – JustMaximumPower