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.
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.
.globl
in the assembly. If anything, you should use .extern
, but GAS does not require that.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.fsubrp
because the top of stack is your 4ac
, so what you calculate using fsubp
is 4ac-b^2
.