zeval
zeval

Reputation: 187

Definition floating-point numbers in X86 Assembly - C Translation

Currently studying C. When I define, for example, a vector, such as:

float var1[2023] = {-53.3125}

What would the corresponding X86 Assembly translation look like? I'm looking for the exact portion of code where the variable is defined, where the ".type" and ".size" and alignment values are mentioned.

I've seen on the internet that when dealing with a floating-point number, the X86 Assembly conversion will simply be ".long". However, I'm not sure to what point that is correct.

Upvotes: 0

Views: 1253

Answers (1)

Steve Friedl
Steve Friedl

Reputation: 4247

One easy way to find out is to ask the compiler to show you:

// float.c
float var1[2023] = { -53.3125 };

then compile it:

$ gcc -S float.c

and then study the output:

        .file   "float.c"
        .globl  var1
        .data
        .align 32
        .type   var1, @object
        .size   var1, 8092
var1:
        .long   3260366848
        .zero   8088
        .ident  "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-39)"
        .section        .note.GNU-stack,"",@progbits

Note that this is just GCC's implementation; clang does it differently:

        .file   "float.c"
        .type   var1,@object            # @var1
        .data
        .globl  var1
        .align  16
var1:   
        .long   3260366848              # float -5.331250e+01
        .long   0                       # float 0.000000e+00
        .long   0                       # float 0.000000e+00
        // thousands of these
        .size   var1, 8092

        .ident  "clang version 3.4.2 (tags/RELEASE_34/dot2-final)"
        .section        ".note.GNU-stack","",@progbits

EDIT - To answer the comment below, the use of long simply lays down a specific bit pattern that encodes the compiler's idea of floating point format.

The value 3260366848 is the same as hex 0xC2554000, which is 11000010010101010100000000000000 in binary, and it's the binary value that the CPU cares about. If you care to, you can get out your IEEE floating point spec and decode this, there's the sign, that's the exponent, etc. but all the details of the floating point encoding were handled by the compiler, not the assembler.

I'm no kind of compiler expert, but decades ago I was tracking down a bug in a C compiler's floating point support, and though I don't remember the details, in the back of my mind it strike me as having the compiler do this would have been helpful by saving me from having to use a disassembler to find out what the bit pattern was actually encoded.

Surely others will weigh in here.

EDIT2 Bits are bits, and this little C program (which relies on sizeof int and sizeof float being the same size), demonstrates this:

// float2.c
#include <stdio.h>
#include <memory.h>


int main()
{
    float f = -53.3125;
    unsigned int i;

    printf("sizeof int = %lu\n", sizeof(i));
    printf("sizeof flt = %lu\n", sizeof(f));

    memcpy(&i, &f, sizeof i); // copy float bits into an int

    printf("float = %f\n", f);
    printf("i     = 0x%08x\n", i);
    printf("i     = %u\n", i);

    return 0;
}

Running it shows that bits are bits:

sizeof int = 4
sizeof flt = 4
float = -53.312500
i     = 0xc2554000
i     = 3260366848   <-- there ya go

This is just a display notion for 32 bits depending on how you look at them.

Now to answer the question of how would you determine 3260366848 on your own from the floating point value, you'd need to get out your IEEE standard and draw out all the bits manually (recommend strong coffee), then read those 32 bits as an integer.

Upvotes: 5

Related Questions