Есть несколько операций, которые вы можете выполнять только с DI / SI (или их расширенными аналогами, если вы не изучали ASM в 1985 году). Среди них
REP STOSB
REP MOVSB
REP SCASB
Это, соответственно, операции для повторного (= массового) сохранения, загрузки и сканирования. Что вы делаете, так это настраиваете SI и / или DI так, чтобы они указывали на один или оба операнда, возможно, помещаете счет в CX, а затем позволяете разорвать. Это операции, которые работают с кучей байтов за раз, и они как бы переводят процессор в автоматический режим. Поскольку вы явно не кодируете циклы, они выполняют свою задачу более эффективно (обычно), чем цикл, кодируемый вручную.
На всякий случай вам интересно: в зависимости от того, как вы настроили операцию, повторное сохранение может быть чем-то простым, например, вставкой значения 0 в большой непрерывный блок памяти; Я думаю, что MOVSB используется для копирования данных из одного буфера (ну, любой связки байтов) в другой; а SCASB используется для поиска байта, который соответствует некоторому критерию поиска (я не уверен, ищет ли он только равенство или что-то еще - вы можете найти его :))
Это большая часть того, для чего нужны эти регистры.
Совет по оптимизации из прошлого: rep stosw намного быстрее, чем rep stosb , поэтому, если копирование двух и двух байтов соответствует тому, что вы пытаетесь сделать, используйте это вместо этого в своем вручную оптимизированном 16-битном ассемблерном коде x86 ...
Александр
88
SI= Исходный индекс DI= Целевой индекс
Как указывали другие, они имеют особое применение со строковыми инструкциями. Для реального программирования режима, то ESрегистр сегмента должен быть использован с , DIи DSс , SIкак и в
movsb es:di, ds:si
SI и DI также могут использоваться в качестве индексных регистров общего назначения. Например, Cисходный код
где ebp+12содержит argv, ebxесть jи ediимеет srcidx. Обратите внимание, что в третьей инструкции используется ediумножение на 4 и добавление ebpсмещения на 0x54 (расположение srcp); скобки вокруг адреса указывают на косвенное обращение.
Хотя я не могу вспомнить, где я это видел, но это подтверждает большую часть этого, и это (слайд 17) другие:
Коды операций, такие как MOVSB и MOVSW, которые эффективно копируют данные из памяти, на которую указывает ESI, в память, на которую указывает EDI. Таким образом,
В дополнение к строковым операциям (MOVS / INS / STOS / CMPS / SCASB / W / D / Q и т. Д.), Упомянутым в других ответах, я хотел добавить, что есть также более «современные» инструкции по сборке x86, которые неявно используются в минимум EDI / RDI:
Инструкция SSE2 MASKMOVDQU(и предстоящий AVX VMASKMOVDQU) выборочно записывает байты из регистра XMM в память, на которую указывает EDI / RDI.
В дополнение к регистрам, используемым для массовых операций, они полезны тем, что их свойство сохраняется посредством вызова функции (сохранение вызова) в 32-битном соглашении о вызовах. ESI, EDI, EBX, EBP, ESP сохраняют вызовы, тогда как EAX, ECX и EDX не сохраняют вызовы. Регистры с сохранением вызовов соблюдаются библиотечной функцией C, и их значения сохраняются через вызовы функций библиотеки C.
Джефф Дантеманн в своей книге на ассемблере имеет пример кода ассемблера для печати аргументов командной строки. Код использует esi и edi для хранения счетчиков, поскольку они не будут изменены функцией printf библиотеки C. Для других регистров, таких как eax, ecx, edx, нет гарантии, что они не будут использоваться функциями библиотеки C.
См. Раздел 12.8 «Как C видит аргументы командной строки».
Обратите внимание, что 64-битные соглашения о вызовах отличаются от 32-битных соглашений о вызовах, и я не уверен, сохраняются ли эти регистры с сохранением вызовов или нет.
Я никогда не слышал, чтобы слово «священный» использовалось для описания того, что большинство людей называют «энергозависимым» / «энергонезависимым» или «сохраненным вызываемым» против «сохраненным вызывающим абонентом». Мне нравится "сохраненный вызов" / "закрытый вызов", поскольку это не означает, что они действительно где-либо сохраняются. В любом случае, вызовы ESI / RSI и EDI / RDI не сохраняются в x86-64 System V ABI.
Питер Кордес,
Кроме того, вы забыли указать EBP и ESP как сохраненные вызовы в общих 32-битных соглашениях о вызовах.
Питер Кордес,
1
В любом случае, это неплохой момент. В реальном коде вы с большей вероятностью выберете EDI / ESI для чего-то, основанного на причинах соглашения о вызовах, чем потому, что они являются специальными для любых инструкций.
Питер Кордес,
Мне нравится звонок-сохранен. Я обновил ответ таким же образом. Спасибо за обзор.
Ответы:
Есть несколько операций, которые вы можете выполнять только с DI / SI (или их расширенными аналогами, если вы не изучали ASM в 1985 году). Среди них
Это, соответственно, операции для повторного (= массового) сохранения, загрузки и сканирования. Что вы делаете, так это настраиваете SI и / или DI так, чтобы они указывали на один или оба операнда, возможно, помещаете счет в CX, а затем позволяете разорвать. Это операции, которые работают с кучей байтов за раз, и они как бы переводят процессор в автоматический режим. Поскольку вы явно не кодируете циклы, они выполняют свою задачу более эффективно (обычно), чем цикл, кодируемый вручную.
На всякий случай вам интересно: в зависимости от того, как вы настроили операцию, повторное сохранение может быть чем-то простым, например, вставкой значения 0 в большой непрерывный блок памяти; Я думаю, что MOVSB используется для копирования данных из одного буфера (ну, любой связки байтов) в другой; а SCASB используется для поиска байта, который соответствует некоторому критерию поиска (я не уверен, ищет ли он только равенство или что-то еще - вы можете найти его :))
Это большая часть того, для чего нужны эти регистры.
источник
SI
= Исходный индексDI
= Целевой индексКак указывали другие, они имеют особое применение со строковыми инструкциями. Для реального программирования режима, то
ES
регистр сегмента должен быть использован с ,DI
иDS
с ,SI
как и вSI и DI также могут использоваться в качестве индексных регистров общего назначения. Например,
C
исходный кодкомпилируется в
где
ebp+12
содержитargv
,ebx
естьj
иedi
имеетsrcidx
. Обратите внимание, что в третьей инструкции используетсяedi
умножение на 4 и добавлениеebp
смещения на 0x54 (расположениеsrcp
); скобки вокруг адреса указывают на косвенное обращение.Хотя я не могу вспомнить, где я это видел, но это подтверждает большую часть этого, и это (слайд 17) другие:
AX
= аккумуляторDX
= двойное слово аккумуляторCX
= счетчикBX
= базовый регистрОни выглядят как регистры общего назначения, но есть ряд инструкций, которые (неожиданно?) Используют один из них - но какая? - неявно.
источник
Коды операций, такие как MOVSB и MOVSW, которые эффективно копируют данные из памяти, на которую указывает ESI, в память, на которую указывает EDI. Таким образом,
источник
В дополнение к строковым операциям (MOVS / INS / STOS / CMPS / SCASB / W / D / Q и т. Д.), Упомянутым в других ответах, я хотел добавить, что есть также более «современные» инструкции по сборке x86, которые неявно используются в минимум EDI / RDI:
Инструкция SSE2
MASKMOVDQU
(и предстоящий AVXVMASKMOVDQU
) выборочно записывает байты из регистра XMM в память, на которую указывает EDI / RDI.источник
В дополнение к регистрам, используемым для массовых операций, они полезны тем, что их свойство сохраняется посредством вызова функции (сохранение вызова) в 32-битном соглашении о вызовах. ESI, EDI, EBX, EBP, ESP сохраняют вызовы, тогда как EAX, ECX и EDX не сохраняют вызовы. Регистры с сохранением вызовов соблюдаются библиотечной функцией C, и их значения сохраняются через вызовы функций библиотеки C.
Джефф Дантеманн в своей книге на ассемблере имеет пример кода ассемблера для печати аргументов командной строки. Код использует esi и edi для хранения счетчиков, поскольку они не будут изменены функцией printf библиотеки C. Для других регистров, таких как eax, ecx, edx, нет гарантии, что они не будут использоваться функциями библиотеки C.
https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025
См. Раздел 12.8 «Как C видит аргументы командной строки».
Обратите внимание, что 64-битные соглашения о вызовах отличаются от 32-битных соглашений о вызовах, и я не уверен, сохраняются ли эти регистры с сохранением вызовов или нет.
источник