Есть ли аппаратный блок, который называется «2-е дополнение»? - PullRequest
1 голос
/ 06 июня 2011

Я понимаю, что для вычитания вы должны выполнить преобразование дополнения в 2 до второго числа.Есть ли выделенное Аппаратное обеспечение для проверки MSB, и, если установлено, что оно равно 1, оно выполняет преобразование?

Кроме того, эта система используется для вычитания с плавающей запятой ?

Ответы [ 3 ]

2 голосов
/ 06 июня 2011

Операция дополнения двоих реализована на большинстве языков с помощью унарного оператора -. Используется только со знаковыми целочисленными типами. Он может быть реализован в ALU как отдельная инструкция отрицания (например, NEG) или свернут в другую операцию, например, когда вы используете инструкцию вычитания (например, SUB) вместо инструкции сложения (например, ADD) .

Ваш первый вопрос неясен, поскольку «последний бит» может относиться либо к старшему значащему биту (MSB), либо к младшему значащему биту (LSB). В целом числе со знаком MSB указывает знак; проверка отрицательного значения обычно реализуется в виде бита N в регистре кода состояния, который обновляется на основе результата последней выполненной инструкции (хотя некоторые инструкции не изменяют регистр кода условия). Вычисление дополнения к двум, только если исходное число является отрицательным, является операцией абсолютного значения (например, ABS). Проверка LSB просто говорит вам, является ли целое число четным или нечетным.

Числа с плавающей запятой используют отдельный знаковый бит, поэтому 0 и -0 являются разными значениями. Комплимент Two не работает со значениями с плавающей запятой; необходимо использовать другой подход.

РЕДАКТИРОВАТЬ: Пример. Рассмотрим следующий код C:

#include <stdlib.h>

int do_math(int a, int b)
{
    return a - b;
}

int main(int argc, char* const argv[])
{
    if(argc < 2)
        return 0;
    return do_math(atoi(argv[1]), atoi(argv[2]));
}

Это можно запустить с помощью:

$ gcc -O0 foo.c -o foo
$ ./foo 20 10; echo $?
10

На x86_64 функция do_math() содержит следующий код:

_do_math:
    pushq   %rbp
    movq    %rsp, %rbp
    movl    %edi, -4(%rbp)
    movl    %esi, -8(%rbp)
    movl    -8(%rbp), %edx
    movl    -4(%rbp), %eax
    subl    %edx, %eax
    leave
    ret

Первые две строки - это преамбула, задающая стек для функции. Следующие четыре строки извлекают входные параметры из стека (так как оптимизация была отключена, параметры не были переданы в регистрах).

Затем ключевая инструкция: subl, которая принимает второй параметр (%eax, регистр Extended AX в x86, размер 32 бита) и вычитает его из первого параметра (%edx, регистр Extended DX в x86) также размером 32 бита), сохраняя результат обратно в %edx. В ALU инструкция subl принимает первый параметр как есть и добавляет дополнение двух ко второму параметру. Он вычисляет дополнение двух, инвертируя биты второго параметра (аналогично оператору ~ в C), а затем используя специальный сумматор для добавления 1. Этот шаг может быть конвейерным, его можно оптимизировать, чтобы завершить и окончательное сложение за один цикл, или они могли бы пойти дальше и свернуть логику дополнения двух в цепочку сумматора АЛУ.

Последние две строки очищают стек и возвращаются. (Соглашения о вызовах x86 сохраняют результат в %edx.

РЕДАКТИРОВАТЬ 2: Используйте параметр -S для gcc для создания файла сборки (то же имя, что и у входного файла, за исключением суффикса .c, замененного на .s). Например: gcc -O0 foo.c -S (Если бы я не выключил оптимизатор с помощью -O0, вся функция do_math() могла бы быть встроена в main(), что значительно усложняло бы ее видеть.)

0 голосов
/ 06 июня 2011

Слушай, тебе не нужно проверять номер никогда.Если число равно -ve, оно сохраняется в дополненной форме 2 в памяти.И вы используете это число, ЦП меняет число на ваши расчеты.Вам не нужно ничего проверять.Вы должны выполнить операции

0 голосов
/ 06 июня 2011

Нет и нет.

Преобразование выполняется с помощью кода, работающего на CPU.

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