Author Topic: Problem with assembly for C  (Read 24031 times)

Offline tomix

  • Jr. Member
  • *
  • Posts: 3
Problem with assembly for C
« on: January 08, 2011, 06:14:57 PM »
Hi, I have small function for C in the NASM, that return float value (4.2). This function but return integer value into EAX (0).

Function in NASM:
Code: [Select]
global _fce
section .text

_fce:

push ebp
mov ebp,esp

finit
fld qword [b]
xor eax,eax
leave
ret

section .data

b: dq 4.2



C program
Code: [Select]
#include <stdio.h>

extern double _fce();

int main(void)
{
double a=fce();
printf("%lf",a);
return 0;

}

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Problem with assembly for C
« Reply #1 on: January 09, 2011, 03:08:09 AM »
What's the problem? With one minor tweak, it "works for me". I had to spell "fce" as "_fce" in the body of "main". It displays more decimal places than intended(?), but it works. Changing the format string to "%.1f" fixes that...

The "xor eax, eax" is probably useless - a function returning "float" or "double" returns the value on the top of the FPU stack, not in eax. (is this "standard"?)

The use of underscores is definitely "non-standard"! For Linux/gcc, we don't need 'em at all. In most cases, you'd want to spell it "fce" in the C file, and "_fce" in the asm file. For WatCom C, you'd spell it "fce_" in the asm file! Nasm provides a feature whereby you can spell it "fce", and add "--prefix _" to the command line, and Nasm will put an underscore on anything "extern" or "global". ("-- postfix _" for WatCom).

If you can't get it working, you may need to tell us exactly what happens... and perhaps "what kind of C" as well.

Best,
Frank


Offline tomix

  • Jr. Member
  • *
  • Posts: 3
Re: Problem with assembly for C
« Reply #2 on: January 09, 2011, 11:48:36 AM »
You're right. I had try program in the linux and program works correctly (output is 4.2 from st0). But in the windows is problem (output is 0.0 from EAX).

In the windows I use:

MinGW - gcc version 4.4.1
NASM 2.10rc1

I use prefix for elf file in Windows OS, because gcc (under win32) isnt add "_" prefix.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Problem with assembly for C
« Reply #3 on: January 09, 2011, 01:55:29 PM »
Well... I can't help ya with Windows. Ask MS. That's really strange! Returning a single-precision float in eax is... possible, at least. Returning a double in eax just isn't possible. edx:eax maybe... I doubt it. Are you sure that's what's happening? What happens if you return -1 in eax?

I observe that scanf() takes the address of a float/double as a parameter. You could try modifying your files to do it that way...

Code: [Select]
#include <stdio.h>

extern int fce(double *);

int main(void)
{
double a;
fce(&a);
printf("%.1f\n",a);
return 0;

}

Code: [Select]
; this version takes a "place to put it" as a parameter
; for Linux:
; nasm -elf32 myfile.asm
; for Windows:
; nasm -f win32 --prefix _ myfile.asm
; ?

global fce
section .text

fce:

push ebp
mov ebp,esp

mov eax, [ebp + 8]
finit
fld qword [b]
fstp qword [eax]
xor eax,eax
leave
ret

section .data

b: dq 4.2

As you see, I eliminated the underscores entirely. You can put 'em back in, if you want. I don't know if this would be "appropriate" for you or not. Works for Linux, "should" work for Windows(?)...

Best,
Frank


Offline tomix

  • Jr. Member
  • *
  • Posts: 3
Re: Problem with assembly for C
« Reply #4 on: January 09, 2011, 03:10:32 PM »
I try your code,now return value is very strange:1.$

For compile I used your argument: nasm -f win32 --prefix _ pr3.asm

When I try compile with: nasm -f elf --prefix _ pr3.asm
return value is good !!! 4.2

But why dont use this function for return direct float (double) (without pointer) ?

When I try return in the eax (-1) in my first program, return this value -1 (again in eax).

Program in C absolutely ignore return value in stack top (st0).




Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Problem with assembly for C
« Reply #5 on: January 09, 2011, 04:51:36 PM »
The "xor eax, eax" is probably useless - a function returning "float" or "double" returns the value on the top of the FPU stack, not in eax. (is this "standard"?)

In 32-bit mode, st0 (top of stack) will contain the return value - eax is not used and in this case is "useless"

The use of underscores is definitely "non-standard"! For Linux/gcc, we don't need 'em at all. In most cases, you'd want to spell it "fce" in the C file, and "_fce" in the asm file. For WatCom C, you'd spell it "fce_" in the asm file! Nasm provides a feature whereby you can spell it "fce", and add "--prefix _" to the command line, and Nasm will put an underscore on anything "extern" or "global". ("-- postfix _" for WatCom).

If you can't get it working, you may need to tell us exactly what happens... and perhaps "what kind of C" as well.

As Frank points out, don't add the underscore in your C file.  Using different compilers results in various naming conventions depending on the compiler used.  As I normally use VC or gcc I usually prepend the underscore to my global assembly function.  I probably should get into the habit of not doing that and let nasm handle the prefix/postfix issue from the command line for code that could possibly be used in conjunction with WatCom.  But old habits die hard...

You're right. I had try program in the linux and program works correctly (output is 4.2 from st0). But in the windows is problem (output is 0.0 from EAX).

Pay close attention to your prototype:

Instruct the compiler to return an int value in EAX
Code: [Select]
   extern int fce();

Instruct the compiler to return a double in st0
Code: [Select]
   extern double fce();

Remember that fstp will pop the fpu stack in your assembly code.  Don't issue this opcode as your last floating point operation in a function that is defined to return a double as the compiler will expect the function result there! ;)