Насколько я знаю, инструкция 8086 имеет 3 типа набора инструкций по перемещению данных:
Однако вчера я нашел набор инструкций, таких как мовсб и аутсб,
При использовании этих инструкций возможна операция память в память(M2M)!
В это время мне любопытно, почему существуют инструкции M2M.
Я обнаружил, что существует множество ограничений на их использование.
И эти операции M2M также можно выполнять с комбинацией вышеперечисленных 1,2,3 типов инструкций.
Вопрос:
Мне трудно согласиться с существованием этих M2M-инструкций.
Они существуют только для создания более коротких ассемблерных кодов?
Обратите внимание, что у 8088/8086 есть перемещение памяти, чип 8237 DMA со времен первых ПК включает функцию передачи памяти в память, используя канал 0 для источника и канал 1 для назначения.
@rcgldr Ого, я этого не знал. Кто-нибудь реально использовал эту функцию?
@fuz - я не использовал его. Кажется, я припоминаю, что его тестировали в компании, в которой я работал, возможно, проверяя перемещение памяти dma и/или перемещение памяти процессора на различных настольных компьютерах еще в 1980-х, чтобы получить представление о пропускной способности памяти.
@fuz Нет, это было слишком медленно. Обычно контроллер DMA для ПК использовался только для гибких дисков и звуковых карт, для всего остального он был слишком медленным.
Все операнды памяти имеют сегментный регистр, указанный явно или неявно.
Инструкции movs*
и cmps*
очень удобны, поскольку позволяют выполнять такие распространенные задачи, как копирование данных и сравнение данных.
ins*
и outs*
по своей природе аналогичны movs*
, они просто перемещают данные между памятью и устройствами ввода/вывода. Они особенно полезны для чтения/записи на диск целыми секторами (обычно 512 байт). Конечно, DMA стирают их, поскольку ввод-вывод на основе DMA даже более эффективен, но раньше они не были так распространены, как сегодня.
Моделирование этих инструкций (особенно их повторяющихся форм (ищите префикс rep
)) потребовало бы больше кода и было бы медленнее. Отсюда их существование.
Кстати, инструкция xchg
и любая другая инструкция чтения-изменения-записи (например, add
) с местом назначения в памяти также эффективно являются инструкциями памяти в память. Не все ЦП имеют их, многие в основном предлагают инструкции, которые либо читают из памяти, либо записывают в память, но не оба (исключение составляют инструкции, которые используются для реализации монопольного/атомарного доступа к памяти, подумайте xchg
, xadd
, cmpxchg8/16
). Процессоры с такими наборами инструкций относятся к так называемым архитектурам загрузки-сохранения.
Кроме того, инструкции push
и pop
могут иметь свой явный операнд, обозначающий ячейку памяти. Это еще одна форма инструкций памяти в память.
Что касается сегментов, почти все инструкции, которые читают или записывают память, включают сегменты (некоторые системные инструкции работают по-другому), поэтому управление сегментами и накладные расходы — это не то, чего вы могли бы каким-то образом избежать, если бы решили не использовать инструкции, которые вы упоминаете, и выбрали некоторые другие инструкции вместо этого.
Связано: Какие инструкции x86 требуют двух (или более) операндов памяти? перечисляет инструкции с двумя операндами памяти отдельный, а не RMW того же операнда.
Некоторые ISA с загрузкой и хранением также имеют атомарную подкачку (например, Устаревшая инструкция swp
для 32-битных ARM) и/или CAS, но большинство ISA RISC поддерживают только Связанный с загрузкой / Store-Conditional, поэтому lock add
преобразуется в цикл повторных попыток. (Только для compare_exchange_weak не требуется цикл, потому что допускается сбой из-за конкуренции, а не только из-за различий в данных).
LL/SC имеет преимущества для задержки прерывания, потому что в основном делает атомарную транзакцию прерываемой. Вы можете реализовать любую атомарную операцию (в одном месте), но вы можете сделать то же самое с циклом повторных попыток CAS. LL/SC помогает избежать проблем с ABA... В любом случае, отойдем от темы. LL/SC — это по-прежнему 2 отдельные инструкции, каждая из которых только загружает или только сохраняет. Но они связаны вместе для фиксации как транзакция RMW, поэтому да, они решают ту же проблему, что и 8086 xchg
или более поздняя версия x86 lock cmpxchg
/ lock add
/ lock xadd
/ и т. д.
Сегменты: строковые инструкции пишутся es:di
, что упрощает работу с двумя сегментами одновременно, не загромождая код префиксами переопределения сегментов. Размер кода был критическим для производительности 8086.
Архитекторы рассудили, что некоторые общие функции более высокого уровня могут поддерживаться аппаратно. Таким образом,
movsb
предназначен для реализацииmemcpy
и друзей, аoutsb
очень полезен при выполнении ввода-вывода на тупых устройствах, которым не хватает вспомогательного оборудования (что было обычным случаем в те далекие времена). Конечно, это не было оригинальной идеей или чем-то подобным - до появления RISC-движения такого рода инструкции были довольно распространены повсюду (кроме действительно маленьких 8-битных "микро").