У меня есть основной вопрос о блоке.
Почему мы потрудились делать арифметические операции только на регистрах, если они могут работать над памятью также?
Например, обе из следующей причины (по существу) то же значение, которое будет вычислено как ответ:
Отрывок 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
Из того, что я вижу большинство текстов, и учебные руководства делают арифметические операции главным образом на регистрах. Это просто быстрее для работы с регистрами?
Править: Это было быстро :)
Несколько больших ответов были даны; лучший ответ был выбран на основе первого хорошего ответа.
Регистры работают намного быстрее, а операции, которые вы можете выполнять непосредственно с памятью, гораздо более ограничены.
Мы используем регистры, потому что они быстрые. Обычно они работают со скоростью процессора.
Регистры и кэш ЦП изготавливаются с использованием различных технологий / структур, и
они дороги. С другой стороны, оперативная память дешевая и в 100 раз медленнее.
Да, регистры использовать намного быстрее. Даже если вы учитываете только физическое расстояние от процессора до регистра по сравнению с процедурой до памяти, вы экономите много времени, не отправляя электроны так далеко, а это означает, что вы можете работать с более высокой тактовой частотой.
Да - также обычно вы можете легко вставлять / извлекать регистры для вызова процедур, обработки прерываний и т. Д.
Доступ к регистрам происходит быстрее, чем к оперативной памяти, поскольку вам не нужно обращаться к «медленной» шине памяти!
Если вы посмотрите на компьютерные архитектуры, вы обнаружите ряд уровней памяти. Те, которые расположены близко к процессору, являются быстрыми, дорогими (на бит) и, следовательно, маленькими, в то время как на другом конце у вас есть большие, медленные и дешевые устройства памяти. На современном компьютере это обычно примерно следующее:
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)
Со временем добавлялось все больше и больше уровней кеш-памяти - я могу вспомнить время, когда у ЦП не было встроенных кешей, а я даже не старый! В наши дни жесткие диски поставляются со встроенными кешами, и Интернет кэшируется в любом количестве мест: в памяти, на жестком диске и, возможно, на прокси-серверах кэширования.
Наблюдается резкое (часто на порядки) уменьшение полосы пропускания и увеличение задержки на каждом шаге от ЦП. Например, жесткий диск может читать со скоростью 100 МБ / с с задержкой 5 мс (эти числа могут быть неточными), в то время как ваша основная память может читать со скоростью 6,4 ГБ / с с задержкой 9 нс (шесть порядков величина!). Задержка - очень важный фактор, поскольку вы не хотите заставлять ЦП ждать дольше, чем нужно (это особенно верно для архитектур с глубокими конвейерами, но это обсуждение на другой день).
Идея состоит в том, что вы часто будете повторно использовать одни и те же данные снова и снова, поэтому имеет смысл поместить их в небольшой быстрый кеш для последующих операций. Это место называется временным местом .Другим важным принципом локальности является пространственная локальность , который гласит, что ячейки памяти, расположенные рядом друг с другом, вероятно, будут считываться примерно в одно и то же время. Именно по этой причине чтение из ОЗУ приводит к тому, что гораздо больший блок ОЗУ будет считан и помещен в кэш процессора. Если бы не эти принципы локальности, то любое место в памяти с равной вероятностью было бы прочитано в любой момент времени, поэтому не было бы способа предсказать, к чему будет осуществляться доступ дальше, и все уровни кеша в мире не улучшится скорость. Вы также можете просто использовать жесткий диск, но я уверен, что вы знаете, каково это, когда компьютер останавливается при подкачке страниц (что в основном использует жесткий диск в качестве расширения ОЗУ). Концептуально возможно не иметь памяти, кроме жесткого диска (а многие небольшие устройства имеют только одну память), но это будет мучительно медленно по сравнению с тем, с чем мы знакомы.
Еще одно преимущество регистров (и лишь небольшого количества регистров) состоит в том, что они позволяют иметь более короткие инструкции . Если у вас есть инструкции, содержащие два (или более) 64-битных адреса, у вас будут длинные инструкции!
Вообще говоря, регистровая арифметика намного быстрее и предпочтительнее. Однако есть некоторые случаи, когда полезно использовать прямую арифметику памяти. Если все, что вы хотите сделать, это увеличить число в памяти (и ничего больше, по крайней мере, в течение нескольких миллионов инструкций), то одна инструкция прямой арифметики памяти обычно немного быстрее, чем load/add/store.
Кроме того, если вы выполняете сложные операции с массивами, вам обычно требуется много регистров, чтобы отслеживать, где вы находитесь и где заканчиваются ваши массивы. На старых архитектурах регистр мог закончиться очень быстро, поэтому возможность сложения двух битов памяти вместе без использования текущих регистров была очень полезной.
Просто набор инструкций не позволяет выполнять такие сложные операции:
add [0x40001234],[0x40002234]
Приходится обращаться к регистрам.