Почему IA32 не позволяет памяти в память перемещаться?

В архитектуре Intel IA32 такие инструкции, как movl, movw, не разрешают операнды, которые являются обеими ячейками памяти. Например, инструкция movl (%eax), (%edx) недопустима. Зачем?

4 ответа

Решение

Ответ предполагает более полное понимание оперативной памяти. Проще говоря, ОЗУ может находиться только в двух состояниях: режиме чтения или записи. Если вы хотите скопировать один байт оперативной памяти в другое место, у вас должна быть временная область памяти вне ОЗУ, когда вы переключаетесь с чтения на запись.

Архитектура, безусловно, может иметь такую ​​инструкцию ОЗУ в ОЗУ, но это будет инструкция высокого уровня, которая в микрокоде преобразуется в копирование данных из ОЗУ в регистр, а затем обратно в ОЗУ. Альтернативно, можно было бы расширить контроллер ОЗУ, чтобы иметь такой временный регистр только для этого копирования данных, но это не принесло бы большой пользы для дополнительной сложности взаимодействия ЦП и аппаратного обеспечения.

РЕДАКТИРОВАТЬ: Стоит отметить, что недавние усовершенствования, такие как Hybrid Memory Cube и High Bandwidth Memory, являются архитектурами, в которых топология RAM стала больше похожа на PCI-e, и теперь возможны прямые передачи RAM в RAM, но это связано с логикой поддержки для технологий, а не самой оперативной памяти. В архитектуре ЦП это будет происходить в виде огромных блоков ОЗУ за раз, например, DMA, а не в виде одной инструкции, плюс кэш ЦП ведет себя как традиционная ОЗУ, поэтому архитектуре придется абстрагировать ее как согласно моему оригинальному объяснению

РЕДАКТИРОВАТЬ 2: Согласно комментарию @PeterCordes, мое первоначальное понимание не было полностью правильным; x86 на самом деле имеет несколько инструкций памяти к памяти. Реальная причина, по которой они недоступны для большинства инструкций (таких как movl и movw), заключается в том, чтобы сохранить сложность кодирования команд на низком уровне, но они могли бы их реализовать. Тем не менее, основная идея в моем первоначальном ответе о том, что вне ОЗУ имеется временное хранилище в виде защелки или регистра, верна, но идея о том, что это причина, по которой эти инструкции не существуют, не верна. Даже старые чипы 1970-х годов, такие как 6502 и 8086, имеют инструкции памяти к памяти, и вы можете легко выполнять такие операции, как INC, непосредственно в ячейке ОЗУ. Это было достигнуто путем фиксации выборки памяти непосредственно в АЛУ и возврата обратно в память без прохождения через регистр, используемый набором команд.

ia32 - это x86, а x86 - это эволюция от Intel 8086 (iAPX 86). Это был небольшой и дешевый чип, основанный на 8-битных наборах команд, и не имел "mov" с двумя явными операндами памяти.

Автор Википедии дает такое объяснение о кодировке инструкций 8086:

Из-за компактного кодирования, основанного на 8-битных процессорах, большинство инструкций являются одноадресными или двухадресными операциями, что означает, что результат сохраняется в одном из операндов. Максимум один из операндов может находиться в памяти, но этот операнд памяти также может быть адресатом, в то время как другой операнд, источник, может быть регистровым или непосредственным. Одна и та же ячейка памяти также часто может использоваться как в качестве источника, так и места назначения, что, помимо других факторов, дополнительно способствует плотности кода, сравнимой (и часто лучше, чем) с большинством восьмибитных машин того времени.

Существовали некоторые CISC с инструкциями память-память (одна инструкция для работы с двумя операндами памяти). В лекции https://www.cis.upenn.edu/~milom/cis501-Fall05/lectures/02_isa.pdf говорится, что VAX может кодировать инструкции память-память:

DEC VAX (расширение виртуального адреса до PDP-11): 1977

  • • Инструкции переменной длины: 1-321 байт!!!
  • • 14 GPR + ПК + указатель стека + коды условий
  • • Размеры данных: 8, 16, 32, 64, 128 бит, десятичные, строковые
  • Память-память инструкции для всех размеров данных
  • • Специальные insns: crc, insque, polyf и сотня актеров

Это источник OpenBSD memcpy для VAX (руководство по набору инструкций http://h20565.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c04623178):

https://es.osdn.jp/projects/openbsd-octeon/scm/git/openbsd-octeon/blobs/master/src/sys/lib/libkern/arch/vax/memcpy.S

         movq    8(ap),r1        /* r1 = src, r2 = length */
         movl    4(ap),r3        /* r3 = dst */
... 
 1:      /* move forward */
         cmpl    r2,r0
         bgtru   3f              /* stupid movc3 limitation */
         movc3   r2,(r1),(r3)    /* move it all */

Инструкция "movc3" здесь имеет два операнда памяти, адреса которых хранятся в регистрах.

В x86 есть несколько "строковых" инструкций, которые будут выполнять операции с памятью (*s, особенно movs - http://x86.renejeschke.de/html/file_module_x86_id_203.html), но эта инструкция будет использовать предопределенные регистры SI и DI в качестве адресов (неявные операнды), и два операнда памяти все еще не могут быть закодированы в x86.

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

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

Вот некоторые вещи, которые необходимо учитывать для реализации такой инструкции:

  • Какое временное хранилище мы используем? Регистр?

  • Если мы используем регистр, какой из них мы угоняем?

Отсутствие такой инструкции оставляет программисту вышеуказанные вопросы.

Другие вопросы по тегам