Определение чисел с плавающей точкой в ​​сборке X86 - C Перевод - PullRequest
0 голосов
/ 08 января 2020

В данный момент учусь C. Когда я определяю, например, вектор, такой как:

float var1[2023] = {-53.3125}

Как будет выглядеть соответствующий перевод сборки X86? Я ищу точную часть кода, где определяется переменная, где упоминаются ".type" и ".size" и значения выравнивания.

Я видел в inte rnet, что при работе с числом с плавающей точкой преобразование сборки X86 будет просто «.long». Однако я не уверен, в какой точке это правильно.

1 Ответ

5 голосов
/ 08 января 2020

Один простой способ выяснить это - попросить компилятор показать вам:

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

, затем скомпилировать его:

$ gcc -S float.c

, а затем изучить вывод:

        .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

Обратите внимание, что это просто реализация G CC; clang делает это по-другому:

        .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 - Чтобы ответить на комментарий ниже, использование long просто устанавливает определенный c битовый шаблон, который кодирует идею компилятора о Формат с плавающей запятой.

Значение 3260366848 совпадает с шестнадцатеричным 0xC2554000, то есть 11000010010101010100000000000000 в двоичном формате, и это двоичное значение, которое заботит процессор. Если вы хотите, вы можете получить свою IEEE с плавающей запятой spe c и расшифровать ее, есть знак, это показатель степени, и т. Д. c. но все детали кодирования с плавающей запятой обрабатывались компилятором, а не ассемблером.

Я не специалист по компиляции, но десятилетия go я выслеживал ошибку в C поддержка компилятора с плавающей запятой, и хотя я не помню деталей, в глубине души мне кажется, что компилятор может сделать это, было бы полезно, избавив меня от необходимости использовать дизассемблер, чтобы выяснить, что бит шаблон был на самом деле закодирован.

Конечно, здесь будут весить другие.

EDIT2 Биты - это биты, и эта небольшая C программа (которая полагается на размер int и sizeof float одинакового размера ), демонстрирует это:

// 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;
}

Запуск показывает, что биты - это биты:

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

Это просто представление дисплея для 32 бит в зависимости от того, как вы на них смотрите.

Теперь, чтобы ответить на вопрос, как бы вы самостоятельно определили 3260366848 по значению с плавающей запятой, вам нужно взять свой стандарт IEEE и вытащить все биты вручную (рекомендую крепкий кофе), затем читать эти 32 бита как целое число.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...