valores una todas tipos retornan que programacion parametros llamar las funciones funcion estructura ejemplos con como c++ visual-c++ x86 nasm fpu

una - Usar valores de retorno FPU en código c++



tipos de funciones en c (1)

El problema principal no es que haya un error al devolver un valor en el registro de coma flotante ST0 , sino en la forma en que intenta cargar el parámetro de flotación de 32 bits (precisión simple) de la pila. El problema está aquí:

fld dword[esi-8] ;loads the given value into st0

Esto debería decir:

fld dword[esp+4] ;loads the DWORD parameter from stack into st0

fld dword[esi-8] solo funciona a veces debido a la forma en que la función de llamada usa ESI internamente. Con diferentes compiladores de C y optimizaciones habilitadas, es posible que el código no funcione del todo.

Con los parámetros de código C / C ++ de 32 bits se pasan en la pila de derecha a izquierda. Cuando realiza una instrucción CALL en código de 32 bits, la dirección de retorno de 4 bytes se coloca en la pila. La dirección de memoria esp+0 contendría la dirección de retorno y el primer parámetro estaría en esp+4 . Si tuviera un segundo parámetro, estaría en esp+8 . Una buena descripción de la convención de llamadas CDECL de 32 bits de Microsoft se puede encontrar en esta entrada de WikiBook . De importancia:

  • Los argumentos de función se pasan en la pila, en orden de derecha a izquierda.
  • El resultado de la función se almacena en EAX / AX / AL
  • Los valores de retorno del punto flotante se devolverán en ST0
  • Los argumentos enteros de 8 y 16 bits se promocionan a argumentos de 32 bits.

Cuando se trata de instrucciones de FPU x87, es muy importante que el único valor en la pila al devolver un FLOTADOR sea ​​el valor en ST0 . Si no se libera (apareciendo / liberando) cualquier otra cosa que coloque en la pila de FPU, es posible que su función falle cuando se la llame varias veces. La pila de FPU x87 solo tiene 8 ranuras (no muchas). Si no limpia la pila de FPU antes de que la función regrese, puede conducir a desbordamientos de pila de FPU cuando las instrucciones futuras necesiten cargar un nuevo valor en la pila de FPU.

Una implementación de ejemplo de su función podría haber parecido a:

use32 section .text ; _arsinh takes a single float (angle) as a parameter ; angle is at memory location esp+4 on the stack ; arcsinh(x) = ln(x + sqrt(x^2+1)) global _arsinh _arsinh: fldln2 ; st(0) = ln2 fld dword[esp+4] ; st(0) = angle, st(1)=ln2 fld st0 ; st(0) = angle, st(1) = angle, st(2)=ln2 fmul st0 ; st(0) = angle^2, st(1) = angle, st(2)=ln2 fld1 ; st(0) = 1, st(1) = angle^2, st(2) = angle, st(3)=ln2 faddp ; st(0) = 1 + angle^2, st(1) = angle, st(2)=ln2 fsqrt ; st(0) = sqrt(1 + angle^2), st(1) = angle, st(2)=ln2 faddp ; st(0) = sqrt(1 + angle^2) + angle, st(1)=ln2 fyl2x ; st(0) = log2(sqrt(1 + angle^2) + angle)*ln2 ; st(0) = asinh(angle) ret

Tengo un programa NASM x86 que parece funcionar perfectamente. Tengo problemas para usar los valores devueltos. Esto es Windows de 32 bits que usa MSVC ++. Espero el valor de retorno en ST0 .

Un ejemplo mínimo que demuestra el problema con los valores devueltos se puede ver en este código de ensamblado C ++ y NASM :

#include <iostream> extern "C" float arsinh(float); int main() { float test = arsinh(5.0); printf("%f/n", test); printf("%f/n", arsinh(5.0)); std::cout << test << std::endl; std::cout << arsinh(5.0) << std::endl; }

Código de ensamblaje:

section .data value: dq 1.0 section .text global _arsinh _arsinh: fld dword[esi-8] ;loads the given value into st0 ret

Sin embargo, no puedo descifrar cómo usar el valor de retorno, ya que siempre obtengo el valor incorrecto sin importar qué tipo de datos utilizo. En este ejemplo, se debe devolver el valor 5 y esperaría un resultado como:

5.000000

5.000000

5

5

En cambio, obtengo resultados similares a los siguientes:

-9671494178951383518019584.000000

-9671494178951383518019584.000000

-9.67149e + 24

5

Solo el valor final parece ser correcto. ¿Qué está mal con este código? ¿Por qué no siempre devuelve el valor del punto flotante que estoy esperando de mi función? ¿Cómo puedo arreglar este código?