В архитектуре Intel IA32 такие инструкции, как movl, movw, не разрешают операнды, которые являются обеими ячейками памяти. Например, инструкция movl (% eax), (% edx) не разрешена. Почему?
Почему IA32 не позволяет память переместить в память?
Ответы (4)
Ответ предполагает более полное понимание RAM. Проще говоря, ОЗУ может находиться только в двух состояниях: в режиме чтения или записи. Если вы хотите скопировать один байт из ОЗУ в другое место, вы должны иметь область временного хранения вне ОЗУ, когда вы переключаетесь с чтения на запись.
Конечно, архитектура может иметь такую инструкцию RAM to RAM, но это будет инструкция высокого уровня, которая в микрокоде будет транслироваться в копирование данных из RAM в регистр, а затем обратно в RAM. В качестве альтернативы, можно было бы расширить контроллер RAM, чтобы иметь такой временный регистр только для этого копирования данных, но это не принесет большого преимущества из-за дополнительной сложности взаимодействия CPU / оборудования.
РЕДАКТИРОВАТЬ: Стоит отметить, что последние достижения, такие как куб гибридной памяти и память с высокой пропускной способностью, представляют собой архитектуры, в которых топология ОЗУ стала больше похожа на PCI-e, и теперь возможна прямая передача ОЗУ в ОЗУ, но это связано с логикой поддержки технологий, а не с самой оперативной памятью. В архитектуре ЦП это будет в форме огромных блоков ОЗУ за раз, например, DMA, а не в виде одной инструкции, плюс кеш ЦП ведет себя как традиционная ОЗУ, поэтому архитектура должна абстрагировать его как согласно моему первоначальному объяснению
РЕДАКТИРОВАТЬ2: Согласно комментарию @PeterCordes, мое первоначальное понимание было не совсем правильным; На самом деле x86 имеет несколько инструкций из памяти в память. Настоящая причина, по которой они недоступны для большинства инструкций (таких как movl и movw), состоит в том, чтобы снизить сложность кодирования инструкций, но они могли бы их реализовать. Однако основная идея в моем первоначальном ответе о том, что существует временное хранилище вне ОЗУ в виде защелки или регистра, верна, но идея о том, что это причина, по которой эти инструкции не существуют, - нет. Даже более старые микросхемы 1970-х годов, такие как 6502 и 8086, имеют инструкции из памяти в память, и вы можете легко выполнять такие операции, как INC, непосредственно в области ОЗУ. Это было достигнуто путем фиксации выборки из памяти непосредственно в ALU и повторного возврата в память без прохождения через регистр, используемый набором команд.
movs
), но она использует два неявных операнда. Также есть push/pop [mem]
для чтения с действующего адреса, закодированного в insn, и записи в [rsp]
. (или наоборот, push vs. pop). У оригинального 8086 были эти insns, и у него был довольно маленький бюджет транзистора (но, очевидно, достаточно большой, чтобы зафиксировать 16 бит между чтением и записью). В современных процессорах rep movs
действительно эффективен для блочных копий больших выровненных буферов.
- person Peter Cordes; 21.04.2016
inc byte [mem]
, выполняют чтение-изменение-запись в память. Это по тому же адресу, но это все еще две отдельные команды. Это неплохая догадка, но она практически не связана с правильным ответом.
- person Peter Cordes; 17.07.2016
inc dword [eax]
существует в IA-32. (Или синтаксис AT&T, incl (%eax)
. Похоже, ваш последний абзац утверждает, что 6502 и 8086 имеют это, а IA-32 нет.
- person Peter Cordes; 21.03.2018
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 георадаров + ПК + указатель стека + коды состояния
- • Размеры данных: 8, 16, 32, 64, 128 бит, десятичные, строковые.
- • Инструкции память-память для всех размеров данных.
- • Специальные insns: crc, insque, polyf и cast of 100
Это исходный код OpenBSD memcpy для VAX (руководство по набору инструкций http://h20565.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c04623178):
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.
Насколько мне известно, как правило, в этой архитектуре разрешен только один доступ к памяти для каждой инструкции. Это связано с тем, что обработка двух обращений к памяти на инструкцию усложнила бы конвейер выполнения процессора.
ОЗУ поддерживает ввод и вывод, но не копирование. Следовательно, перемещение из памяти в память на самом деле будет перемещением из памяти в процессор в память. Теоретически такую инструкцию можно было бы реализовать, но, вероятно, этого не произошло, потому что это было бы не очень практично.
Вот некоторые из вещей, которые необходимо учитывать при реализации такой инструкции:
Какое временное хранилище мы используем? Регистр?
Если мы используем реестр, какой из них мы взламываем?
Отсутствие такой инструкции оставляет вышеуказанные вопросы на усмотрение программиста.
movsb
и его семью. И, конечно же, регистр не обязательно должен быть архитектурным.
- person harold; 14.08.2012
movsb
,movsw
,movsd
,movsq
) имеет два аргумента памяти, но они неявны. - person harold   schedule 14.08.2012base + index + disp16
) потребовалось бы два AGU (блоки генерации адресов), и это сильно усложнило бы формат двоичного машинного кода. (какое переопределение сегмента применяется к какому операнду? Как разрешить кодирование двух адресов памяти без увеличения размера кода для общего случая, когда один или оба операнда являются регистрами?) - person Peter Cordes   schedule 21.04.2016