4

our course exercise asks us to create a delta = b2 - 4ac function in GNU assembly, and access it from C. Since this is a course about compilers, and not about assembly, the professor chose to only demonstrate integer capabilities, and expects an integer function.

However I would like for personal learning to go a little beyond the call of duty, and create a usable function returning floating points rather than integers.

I came up with this C (dont't mind the globals, the purpose of the next exercise is to have a proper function with parameters):

# include <stdio.h>

extern float delta();
float a, b, c;

int main() {
    a = 3;
    b = 5;
    c = 4;
    printf("δ = %f\n", delta());
    return 0;
}

and this GNU GAS:

.globl a
.globl b
.globl c
.globl delta
.f4: .float 4.0     # constante 4

.text
delta:
    fld b           # b sur la pile
    fmul b          # b2 sur la pile
    fld .f4         # 4 sur la pile 
    fmul a          # 4a sur la pile
    fmul c          # 4ac sur la pile
    fsubp           # b2 - 4ac sur la pile
ret

From Google I was led to believe that I should leave a floating point result at the top of the floating point stack, however this doesn't work, and the result printed in the C caller is invariably 0.0000000.

I must miss a very small something, but no amount of googling brings it up, can anyone point me in the right direction? Thanks for your attention.

pouzzler
  • 1,800
  • 2
  • 20
  • 32

1 Answers1

3

It does work for me. Make sure you are not accidentally using 64 bit mode, because calling convention is different there. That is, use gcc -g -m32 foo.c bar.s to compile.

That said, I also see some potential problems that should be fixed.

  • Since your globals are defined in the C code, you should not use .globl in the assembly. If anything, you should use .extern, but GAS does not require that.
  • You should not rely on default operand size. You should explicitly use s suffix for floats and l suffix for doubles when you have memory operands. For example, flds b to make sure it's loaded as a float.
  • You should use fsubrp because the top of stack is your 4ac, so what you calculate using fsubp is 4ac-b^2.
Jester
  • 56,577
  • 4
  • 81
  • 125
  • thanks, the m32 option is what I missed, I will now read the rest of your useful comments in a less stressed out way. Thank you very much. – pouzzler Oct 20 '14 at 14:15
  • If you use `as` to assemble, the corresponding flag is `--32` as in the command `as --32 -o delta.o delta.s` – Edward Oct 20 '14 at 14:28