Відповіді:
Є кілька операцій, які ви можете виконати лише з DI / SI (або їх розширеними аналогами, якщо ви не вивчили ASM в 1985 році). Серед них є
REP STOSB
REP MOVSB
REP SCASB
Які, відповідно, операції для повторного (= масового) зберігання, завантаження та сканування. Що ви робите, ви налаштовуєте SI та / або DI так, щоб вони вказували на один або обидва операнди, можливо, ставили підрахунок у CX, а потім дозволяли 'er rip. Це операції, які працюють над купою байтів одночасно, і вони начебто ставлять процесор автоматичним. Оскільки ви чітко не кодуєте петлі, вони роблять свою справу ефективніше (як правило), ніж цикл, кодований вручну.
На випадок, якщо вам цікаво: залежно від того, як ви налаштували операцію, повторне зберігання може бути чимось простим, як пробивання значення 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 не зберігаються. Записи збережених викликів дотримуються функції бібліотеки С, а їх значення зберігаються через виклики функції бібліотеки С.
Джефф Дантеманн у своїй книзі з мовою збірки має приклад коду складання для друку аргументів командного рядка. Код використовує esi та edi для зберігання лічильників, оскільки вони будуть незмінними функцією бібліотеки C printf. Для інших реєстрів, таких як eax, ecx, edx, немає гарантії, що вони не будуть використані функціями бібліотеки C.
https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025
Див. Розділ 12.8 Як C бачить аргументи командного рядка.
Зауважте, що 64-розрядні конвенції викликів відрізняються від 32-бітових конвенцій викликів, і я не впевнений, зберігаються вони чи ні.