Как целочисленное сравнение работает внутри?

18

Например, при сравнении двух целых чисел в C-подобном языке:

if (3 > 2) {
    // do something
}

Каким образом решение о том, больше ли 3 больше 2 (верно) или нет (ложно), принято внутри страны?

Niek
источник
19
Текущий ответ в порядке для случая , когда Comparation о вариабельной экспрессией, но отсутствие заявления об отказе , что многие современные компиляторы будут смотреть на ваш кусок кода, обнаружить , что выражение всегда будет истинным (из литералов) и просто игнорировать ifполностью Идем прямо к кодированию do something.
SJuan76
3
Возможный дубликат Как работают компьютеры?
3
@ Снеговик, я не согласен. Любой программный запрос «как это работает» может быть сведен к этому вопросу, но это не делает их дубликатами.
user1643723
1
@ user1643723 Используется, когда рассматриваемая функция представляет собой определенный код операции.
Хрилис - на забастовку -
1
@ user1643723 Вопрос состоит в том, как компьютер выполняет основную операцию, а в верхнем ответе обсуждаются логические элементы и логические таблицы. Две темы, которые подробно освещены в верхнем ответе цели dupe target, которая также отвечает на ваш вопрос.

Ответы:

61

Весь путь вниз по кроличьей норе, а? Хорошо, я попробую.

Шаг 1. От C до машинного языка

Компилятор C преобразует ваше сравнение в коды операций, хранящиеся на машинном языке . Машинный язык - это серия чисел, которые процессор интерпретирует как инструкции. В этом случае будет два кода операции: «вычитать с переносом» и «прыгать, если переносить». Другими словами, 2 вычитается из 3 в одной инструкции, а следующая команда проверяет, не переполнена ли она. Им должны предшествовать две инструкции для загрузки чисел 2 и 3 в места, где их можно сравнивать.

MOV AX, 3    ; Store 3 in register AX
MOV BX, 2    ; Store 2 in register BX
SUB AX, BX   ; Subtract BX from AX
JC  Label    ; If the previous operation overflowed, continue processing at memory location "Label"

Каждое из вышеперечисленных имеет двоичное представление; например, код SUBявляется 2Dшестнадцатеричным или 00101101двоичным.

Шаг 2. Опкоды для АЛУ

Арифметические опкоды нравится ADD, SUB, MULи DIVвыполнять основные целочисленную арифметику с использованием ALU или арифметико - логическое устройство , встроенный в CPU. Числа хранятся в регистрах некоторыми кодами операций; другие коды операций инструктируют микросхему вызывать ALU для выполнения математических операций в отношении всего, что хранится в регистрах в данный момент.

Примечание. На данный момент мы намного превосходим все, о чем беспокоится любой разработчик программного обеспечения, работая с 3GL, например C.

Шаг 3. АЛУ, полусуммер и полный сумматор

Знаете ли вы, что все известные вам математические операции могут быть сведены к серии операций NOR ? И именно так работает АЛУ.

ALU знает только, как работать с двоичными числами, и может выполнять только логические операции, такие как OR, NOT, AND и XOR. Реализация двоичного сложения и вычитания осуществляется с помощью последовательности логических операций, организованных определенным образом, в подсистеме, известной как сумматор . Эти подсистемы состоят из сети «полусумметров», которые работают с двумя битами и определяют их однобитную сумму и флаг переноса одного бита. Соединяя их вместе, ALU может выполнять операции с числами с 8, 16, 32 и т. Д. Битами.

Полусумматор

Как насчет вычитания? Вычитание - это просто еще одна форма сложения:

A - B = A + (-B)

ALU вычисляет -B, взяв с дополнением до двух из B. Как только оно будет преобразовано в отрицательное, отправка значения сумматору приведет к операции вычитания.

Шаг 4: Последний шаг: встроенные транзисторы

Операции сумматоров реализуются с использованием комбинации электрических компонентов, которые взаимодействуют для создания «логических вентилей», таких как те, которые находятся в транзисторно-транзисторной логике или TTL, или в CMOS . Нажмите здесь для нескольких примеров, чтобы увидеть, как они связаны.

Конечно, на микросхеме эти «схемы» реализованы в миллионах мельчайших кусочков проводящего и непроводящего материала, но принцип такой же, как если бы они были полноразмерными компонентами на макете. Посмотрите это видео, которое показывает все транзисторы на микрочипе через объектив электронного микроскопа.

Некоторые дополнительные заметки:

  1. Код, который вы написали, на самом деле был бы предварительно вычислен компилятором и не выполнялся во время выполнения, потому что он составлен исключительно из констант.

  2. Некоторые компиляторы не компилируются в машинный код, но представляют еще один уровень, такой как байт-код Java или промежуточный язык .NET. Но в конце концов все это выполняется через машинный язык.

  3. Некоторые математические операции фактически не вычисляются; они ищутся в больших таблицах на арифметическом блоке сопроцессора или содержат комбинацию поиска и вычисления или интерполяции. Примером может служить функция для вычисления квадратного корня . Современные ЦП каждого ПК имеют блок сопроцессора с плавающей запятой, встроенный в каждое ядро ​​ЦП.

Джон Ву
источник
3
FWIW, ссылка на TTL может сбивать с толку, поскольку практически ни один из современных процессоров не использует сигнализацию TTL, большинство из которых используют КМОП-транзисторы и более низкие напряжения вместо 5-вольтных BJT.
whatsisname
2
CMOS определенно будет лучшим эталоном, чем TTL, как предполагает @whatsisname, потому что он не только более точен в отношении того, что происходит в современных процессорах, но и концептуально намного проще.
Жюль
3
@JackAidley это то, что означает эта часть: «Другими словами, 2 вычитается из 3 в одной инструкции, а следующая команда проверяет, не переполнена ли она».
KutuluMike
1
Плохое предположение: я полагаю, CMPчто будет использовано, SUBно не более, но опять-таки это более или менее « SUBкогда результат игнорируется и устанавливаются только флаги»
Хаген фон
5
Ваши определения половинного и полного сумматора неверны. Половина сумматора берет два 1-битных ввода и возвращает сумму и перенос. Полное сумматор требует дополнительного ввода данных, но все еще только один бит. Существует много способов создания N-разрядного сумматора, самый простой из которых - сумматор с волновыми переносами, представляющий собой просто цепочку из N полных сумматоров. На практике для больших Ns это довольно плохая задержка, поэтому в современных процессорах используются более сложные конструкции.
Воо