Я довольно догматичен об объявлении каждой возможной переменной final
. Это включает параметры метода, локальные переменные, и редко, поля объекта значения. У меня есть три главных причины для объявления последних переменных везде:
Однако я действительно думаю, что заключительные классы и методы совсем не так же полезны как ссылки последней переменной. final
ключевое слово, когда используется с этими объявлениями просто предоставляют контрольно-пропускные пункты автоматизированному тестированию и использованию Вашего кода способами, которыми Вы никогда, возможно, не ожидали.
Есть несколько операций, которые вы только можете выполнять с DI / SI (или их расширенными аналогами, если вы не изучали ASM в 1985 году). Среди них
REP STOSB
REP MOVSB
REP SCASB
, которые представляют собой, соответственно, операции для повторного (= массового) сохранения, загрузки и сканирования. Что вы делаете, так это настраиваете SI и / или DI так, чтобы они указывали на один или оба операнда, возможно, помещаете счет в CX, а затем позволяете разорвать. Это операции, которые работают с кучей байтов за раз, и они как бы переводят процессор в автоматический режим. Поскольку вы явно не кодируете циклы, они выполняют свою задачу более эффективно (обычно), чем цикл, кодируемый вручную.
На всякий случай вам интересно: в зависимости от того, как вы настроили операцию, повторное сохранение может быть чем-то простой как вставка значения 0 в большой непрерывный блок памяти; МОВСБ используется, я думаю, копировать данные из одного буфера (ну любой связки байтов) в другой; а SCASB используется для поиска байта, который соответствует некоторому критерию поиска (я не уверен, что это только поиск равенства или чего-то еще - вы можете найти его :))
Это большая часть того, для чего эти регистры.
В дополнение к строковым операциям (MOVS / INS / STOS / CMPS / SCASB / W / D / Q и т. Д.), Упомянутым в других ответах, я хотел добавить, что есть и другие «современные» инструкции сборки x86, которые неявно используют как минимум EDI / RDI:
Инструкция SSE2 MASKMOVDQU
(и предстоящий AVX VMASKMOVDQU
) выборочно записывает байты из регистра XMM в память указано EDI / RDI.
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!