Ответы:
Есть несколько операций, которые вы можете выполнять только с DI / SI (или их расширенными аналогами, если вы не изучали ASM в 1985 году). Среди них
REP STOSB
REP MOVSB
REP SCASB
Это, соответственно, операции для повторного (= массового) сохранения, загрузки и сканирования. Что вы делаете, так это настраиваете SI и / или DI так, чтобы они указывали на один или оба операнда, возможно, помещаете счет в CX, а затем позволяете разорвать. Это операции, которые работают с кучей байтов за раз, и они как бы переводят процессор в автоматический режим. Поскольку вы явно не кодируете циклы, они выполняют свою задачу более эффективно (обычно), чем цикл, кодируемый вручную.
На всякий случай вам интересно: в зависимости от того, как вы настроили операцию, повторное сохранение может быть чем-то простым, например, вставкой значения 0 в большой непрерывный блок памяти; Я думаю, что MOVSB используется для копирования данных из одного буфера (ну, любой связки байтов) в другой; а SCASB используется для поиска байта, который соответствует некоторому критерию поиска (я не уверен, ищет ли он только равенство или что-то еще - вы можете найти его :))
Это большая часть того, для чего нужны эти регистры.
SI
= Исходный индекс
DI
= Целевой индекс
Как указывали другие, они имеют особое применение со строковыми инструкциями. Для реального программирования режима, то ES
регистр сегмента должен быть использован с , DI
и DS
с , SI
как и в
movsb es:di, ds:si
SI и DI также могут использоваться в качестве индексных регистров общего назначения. Например, C
исходный код
srcp [srcidx++] = argv [j];
компилируется в
8B550C mov edx,[ebp+0C]
8B0C9A mov ecx,[edx+4*ebx]
894CBDAC mov [ebp+4*edi-54],ecx
47 inc edi
где ebp+12
содержит argv
, ebx
есть j
и edi
имеет srcidx
. Обратите внимание, что в третьей инструкции используется edi
умножение на 4 и добавление ebp
смещения на 0x54 (расположение srcp
); скобки вокруг адреса указывают на косвенное обращение.
AX
= аккумулятор
DX
= двойное слово аккумулятор
CX
= счетчик
BX
= базовый регистр
Они выглядят как регистры общего назначения, но есть ряд инструкций, которые (неожиданно?) Используют один из них - но какая? - неявно.
Коды операций, такие как MOVSB и MOVSW, которые эффективно копируют данные из памяти, на которую указывает ESI, в память, на которую указывает EDI. Таким образом,
mov esi, source_address
mov edi, destination_address
mov ecx, byte_count
cld
rep movsb ; fast!
В дополнение к строковым операциям (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.
https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025
См. Раздел 12.8 «Как C видит аргументы командной строки».
Обратите внимание, что 64-битные соглашения о вызовах отличаются от 32-битных соглашений о вызовах, и я не уверен, сохраняются ли эти регистры с сохранением вызовов или нет.