Estoy empezando a aprender a ensamblar en mi clase de informática y tengo una tarea para redondear un valor de punto flotante usando un modo de redondeo especificado . Intenté implementar esto usando fstcw
, fldcw
y frndint
. Modifico los bits de control de redondeo, redondeo el número y luego restauro los bits de control previos (un requisito de la asignación).Trabajando con números de precisión doble en ensamblado en línea (GCC, IA-32)
El problema actual pendiente es que la instrucción fld %1
parece cargar el valor incorrecto en el registro de coma flotante st(0)
(por ejemplo, si llamo a la función con un valor de 2.6207, el número -1.9427 (...) e-29 se carga en el registro). Esto puede ser debido a un mal uso de gcc
en línea asm()
, o algo más, pero no estoy seguro de por qué sucede.
Esto es lo que tengo:
double roundD (double n, RoundingMode roundingMode)
{
// control word storage (2 bytes for previous, 2 for current)
char *cw = malloc(4*sizeof(char));
char *cw2 = cw + 2;
asm("fstcw %3;" // store control word in cw
"mov %3,%4;" // copy control word into cw2
"and $0xF3FF,%4;" // zero out rounding control bits
"or %2,%4;" // put new mode into rounding control bits
"fldcw %5;" // load the modified control word
"fld %1;" // load n into st(0)
"frndint;" // round n
"fstp %0;" // load st(0) back into n
"fldcw %3;" // load the old control word from cw
: "=m" (n)
: "m" (n), "m" (roundingMode),
"m" (cw), "r" (cw2), "m" (cw2) // mov requires one argument in a register
);
free(cw);
return n;
}
lo agradecería cualquier punteros a lo que está mal con ese código, específicamente relacionado con la línea fld %1
y los asm
entradas/salidas. (Por supuesto, si puede encontrar otros problemas, no dude en comunicármelos también). No quiero que nadie haga mi tarea, solo apúnteme en la dirección correcta. ¡Gracias!
Guau, eso es bastante rudo. Ojalá pudiera ayudar, ¡pero no puedo! :) –
¿Puede mostrarnos el resultado de ensamblaje de esta función? y los bytes de código también si no es demasiado problema. –
@John: El código que se ensamblará no es sorprendente; todo está en un bloque asm gigante opaco (a gcc). :-P Mientras que dividirlo en muchas declaraciones de asm pequeñas (como mi publicación) le daría a gcc más latitud para hacer algo diferente. –