0

I have a small program written in AT&T assembler for the x64 processor in linux and compiled it using Gnu Assembler using the fpatan function. I know I can get the atan value other ways. I am not able to understand how to move floating point values created in the st0-st7 registers into a C++ program.

In this example, I can view the result value using GDB.

My code is as follows:

# trigtest1.s - An example of using the FPACOS instructions
.section .data
y: 
    .float 1.625
x: 
    .float .25

.section .bss
   .lcomm result, 4

.section .text
.globl _start
_start:
   nop
   finit
   flds y
   flds x
   fpatan
   fsts result

   movl $1, %eax
   movl $0, %ebx
   int $0x80

I can compile and link it with:

as -gstabs trigtest1.s -o trigtest.o ld trigtest.o -o trigtest

With GDB after stepping through the program with a breakpoint set at movl $1, %eax I get: (gdb)x/f &result 0x6000e0 : 1.41814697

This is what I was expecting. The problem comes when I try to use it in a C++ program. First here is the function.

# asm.s - An example of using the FPATAN function
.global ArcTan
.section .data
y: 
    .float 1.625
x: 
    .float .25

.section .bss
   .lcomm result, 4

.section .text
ArcTan:
   nop
   finit
   flds y
   flds x
   fpatan
   fsts result
   nop

   ret

And here is the C++ program that calls the assembler function:

#include <iostream>

using namespace std;

extern "C" float ArcTan();

int main()
{

cout<<"Arctan is "<<ArcTan()<<endl;

cout<<endl;

return 0;
}

I compile and link using: as -gstabs asm.s -o asm.o g++ -gstabs -O0 main.cpp asm.o -o runme

When I use GDB to view what is going on, the value in result is never updated and stays at 0. I would like to use the value calculated with fpatan in the C++ program but have not been successful in returning the value. Any help will be greatly appreciated.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Eric
  • 3
  • 1
  • Thank you very much. I had to add the -32 flag to the "as" command as well. Now it is working. – Eric May 24 '20 at 01:35

1 Answers1

1

x86-64 returns float in XMM0, not legacy x87 st0. Build your code with
g++ -m32 asm.s main.cpp -o runme to build 32-bit code that uses the 32-bit calling convention if you want to use legacy x87 for FP math.

Note that your C++ code isn't reading result, it's reading the return value of the function which it expects in a register. If you did use extern float result; in your C++ code, you could read it just fine.

(turns out Michael Petch has already written a full answer on Return a float from a 64-bit assembly function that uses x87 FPU, closing this as a duplicate.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    It's [frowned upon](https://meta.stackoverflow.com/q/286072/7509065) to dupehammer a question right after you answer it. – Joseph Sible-Reinstate Monica May 24 '20 at 01:34
  • @JosephSible-ReinstateMonica: Yeah, it's not something I make a habit of. I should have left my comment as a comment and gone looking for a duplicate first, before turning it into a minimal answer. At this point though I'm not going to re-post as a comment and/or delete this answer, though. I guess I could make this answer community-wiki if anyone's really bothered, but I don't feel too bad about getting some rep for doing the work of looking for duplicates in general, although this one in particular was easy to find. – Peter Cordes May 24 '20 at 01:38