Ассамблея: Почему мы беспокоимся о реестрах?

У меня есть основной вопрос о сборке.

Зачем нам делать арифметические операции только на регистрах, если они могут работать и с памятью?

Например, обе следующие причины (по существу) одинаковое значение, которое должно быть рассчитано как ответ:

Фрагмент 1

.data
    var dd 00000400h

.code

    Start:
        add var,0000000Bh
        mov eax,var
        ;breakpoint: var = 00000B04
    End Start


Фрагмент 2

.code

    Start:
        mov eax,00000400h
        add eax,0000000bh
        ;breakpoint: eax = 0000040B
    End Start



 Из того, что я вижу, большинство текстов и руководств делают арифметические операции в основном на регистрах. Разве быстрее работать с регистрами?

Изменить: это было быстро:)

Было дано несколько отличных ответов; лучший ответ был выбран на основе первого хорошего ответа.

Ответы

Ответ 1

Регистры намного быстрее, а операции, которые вы можете выполнять непосредственно в памяти, гораздо более ограничены.

Ответ 2

Если вы посмотрите на компьютерные архитектуры, вы найдете ряд уровней памяти. Те, которые близки к процессору, являются быстрыми, дорогими (за бит) и, следовательно, небольшими, а на другом конце у вас большие, медленные и дешевые устройства памяти. В современном компьютере это обычно что-то вроде:

 CPU registers (slightly complicated, but in the order of 1KB per a core - there
                are different types of registers. You might have 16 64 bit
                general purpose registers plus a bunch of registers for special
                purposes)
 L1 cache (64KB per core)
 L2 cache (256KB per core)
 L3 cache (8MB)
 Main memory (8GB)
 HDD (1TB)
 The internet (big)

С течением времени все больше и больше уровней кеша были добавлены - я помню время, когда у процессоров не было встроенных кешей, и я даже не старый! В наши дни на жестких дисках есть встроенные кеши, а интернет кэшируется в любом количестве мест: в памяти, на жестком диске и, возможно, при кешировании прокси-серверов.

В каждом шаге от CPU происходит резкое (часто на порядок) уменьшение полосы пропускания и увеличение латентности. Например, жесткий диск может быть прочитан со скоростью 100 Мбайт/с с задержкой в ​​5 мс (эти цифры могут быть не совсем точными), в то время как ваша основная память может считываться со скоростью 6,4 ГБ/с с задержкой в ​​9 нс (шесть порядков величина!). Задержка - очень важный фактор, так как вы не хотите, чтобы процессор ожидал дольше, чем он должен (это особенно верно для архитектур с глубокими конвейерами, но это обсуждение на другой день).

Идея состоит в том, что вы часто будете повторно использовать одни и те же данные снова и снова, поэтому имеет смысл помещать их в небольшой быстрый кеш для последующих операций. Это называется временной локалью. Другим важным принципом локальности является пространственная локальность, в которой говорится, что места памяти рядом друг с другом, вероятно, будут считаться примерно в одно и то же время. Именно по этой причине считывание из ОЗУ приведет к тому, что считываемый многомерный блок RAM будет считываться и помещаться в кеш-процессор. Если бы не эти принципы локальности, то любое место в памяти имело бы равную вероятность быть прочитанным в любой момент времени, поэтому не было бы способа предсказать, к чему будет обращаться дальше, и все уровни кеша в мире не улучшит скорость. Вы могли бы просто использовать жесткий диск, но я уверен, что вы знаете, как он хочет, чтобы компьютер остановился при пейджинге (который в основном использует жесткий диск в качестве расширения для ОЗУ). Концептуально невозможно иметь память, кроме жесткого диска (и многие небольшие устройства имеют одну память), но это было бы очень медленным по сравнению с тем, с чем мы знакомы.

Еще одно преимущество наличия регистров (и только небольшого числа регистров) заключается в том, что он позволяет иметь короткие инструкции. Если у вас есть инструкции, содержащие два (или более) 64-битных адреса, у вас будут длинные инструкции!

Ответ 3

Регистры получают доступ быстрее, чем оперативная память, так как вам не нужно обращаться к "медленной" шине памяти!

Ответ 4

Мы используем регистры, потому что они быстры. Обычно они работают со скоростью процессора.
Регистры и кеш процессора производятся с использованием различных технологий/тканей и
они дорогие. ОЗУ с другой стороны дешево и в 100 раз медленнее.

Ответ 5

Вообще говоря, арифметика регистра намного быстрее и предпочтительнее. Однако есть случаи, когда арифметика с прямой памятью полезна. Если все, что вы хотите сделать, это увеличить число в памяти (и не более того, по крайней мере, для нескольких миллионов инструкций), то одна арифметическая инструкция прямой памяти обычно немного быстрее, чем load/add/store.

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

Ответ 6

x86, как и любой другой "нормальный" процессор, для которого вы можете изучить сборку, является "регистратор" . Существуют и другие способы разработки чего-то, что вы можете запрограммировать (например, машину Тьюринга, которая движется вдоль логической "ленты" в памяти), но машины регистрации оказались в основном единственным способом перехода на высокопроизводительные.

Так как x86 был разработан для использования регистров, вы не можете полностью их избежать, даже если хотите и не заботитесь о производительности.

Текущие процессоры x86 могут считывать/записывать еще много регистров за такт, чем ячейки памяти.

Например, Intel Skylake может выполнять две загрузки и один магазин из/в свой 32-байтовый 8-портовый ассоциативный кэш L1D за цикл (наилучший вариант), но может читать вверху 10 регистров за такт и писать 3 или 4 (плюс EFLAGS).

Построение кэша L1D с таким количеством портов чтения/записи, как файл регистра будет непомерно дорогостоящим (в количестве транзисторов/области и мощности использование), особенно если вы хотите сохранить его настолько большим, насколько это возможно. Вероятно, просто невозможно физически построить что-то, что может использовать память так, как x86 использует регистры с одинаковой производительностью.

Кроме того, запись регистра, а затем его повторное считывание имеет по существу нулевую задержку, потому что CPU обнаруживает это и передает результат непосредственно с выхода одного исполнительного блока на вход другого, минуя этап обратной записи. (См. https://en.wikipedia.org/wiki/Classic_RISC_pipeline#Solution_A._Bypassing).

Эти пересылки для пересылки между исполнительными модулями называются "обходной сетью" или "сетью переадресации", и CPU намного проще сделать это для дизайна регистров, чем если бы все должно было войти в память и отступить. ЦП должен только проверять номер регистра 3 - 5 бит вместо 32-битного или 64-битного адреса, чтобы обнаружить случаи, когда сразу требуется выход одной инструкции в качестве входа для другой операции. (И эти номера регистров жестко закодированы в машинный код, поэтому они доступны сразу.)

Как отмечали другие, 3 или 4 бита для обращения к регистру делают формат машинного кода более компактным, чем если бы каждая инструкция имела абсолютные адреса.


См. также https://en.wikipedia.org/wiki/Memory_hierarchy: вы можете думать о регистрах как о небольшом небольшом пространстве фиксированной памяти, отделенном от основной памяти, где только поддерживается прямая абсолютная адресация. (Вы не можете "индексировать" регистр: если в одном регистре задано целое число N, вы не можете получить содержимое регистра N th с одним insn.)

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

Наличие фиксированного количества регистров является частью того, что позволяет процессорам register-renaming для исполнения вне порядка. Наличие номера регистра, доступного сразу после декодирования, также делает это проще: никогда не читается или не записывается в еще не известный регистр.


Переименование памяти возможно, но очень редко в реальных процессорах. (Текущие процессоры x86 этого не делают). Преимущества намного ниже, чем переименование регистра, потому что одни и те же регистры очень часто используются для независимых инструкций. Повторное использование того же места памяти для чего-то независимого реже.

Переименование памяти помогло бы в таком случае: записать что-нибудь в маленький буфер, затем прочитать его, а затем написать что-то другое, не зависящее от того, что вы читаете. Без переименования памяти вторая запись должна будет ждать выполнения первого чтения.

Ответ 7

Да, гораздо быстрее использовать регистры. Даже если вы считаете физическое расстояние от процессора до регистрации по сравнению с proc в память, вы сохраняете много времени, не отправляя электроны до сих пор, а это означает, что вы можете работать с более высокой тактовой частотой.

Ответ 8

Да - также вы можете легко нажимать/записывать регистры легко для вызова процедур, обработки прерываний и т.д.

Ответ 9

Просто, что набор команд не позволит вам выполнять такие сложные операции:

add [0x40001234],[0x40002234]

Вам нужно пройти через регистры.