Во-первых, нет ЭЦП, только DS. Даже в 32-битном режиме регистры сегментов остаются 16 битами.
Во-вторых, если вы не работаете с древней системой, такой как расширитель DOS, или чем-то действительно необычным (сильно отличающимся от типичной настольной / серверной ОС, такой как Windows, Linux, OS / X, BSD и т. Д.), Вам не следует Не изменяйте регистры сегмента в любом случае. В большинстве современных систем используется «плоская» модель памяти, где ОС устанавливает все 1 регистры сегмента с основанием 0 и пределом верхней части памяти, поэтому у вас никогда не будет причин изменять какие-либо из них вообще.
К сожалению, хотя легко сказать, что ваш код неверен, немного сложнее сказать, что будет правильно - вы недостаточно сказали о том, что вы хотите сделать. Прямо сейчас, похоже, что вы копируете из буфера, но каждый раз в цикле вы перезаписываете значение, которое вы записали в последней итерации, так что вы можете просто скопировать последнее слово и все готово. Чтобы выполнить цикл через буфер, чтобы добиться многого, вам нужно скопировать его в буфер назначения того же (или большего) размера:
mov ecx, howmany
mov esi, offset FLAT:source
mov edi, offset FLAT:dest
rep movsd
Как уже отмечали другие, операндом для инструкции цикла является метка, а не регистр. Кажется, что они не указали на то, что с современными процессорами (чем-то более новым, чем оригинальный Pentium) вы обычно хотите вообще избегать использования инструкции LOOP. Однако, ради аргумента, цикл для перемещения, как указано выше, будет выглядеть так:
mov ecx, howmany
mov esi, offset FLAT:source
mov edi, offset FLAT:dest
move_loop:
lodsd
stosd
loop move_loop
Для современного процессора обычно лучше использовать больше, но более простых инструкций.
; same setup as above
move_loop:
mov eax, [esi]
mov [edi], eax
inc esi
inc edi
dec ecx
jnz move_loop
Другая сторона в том, что в этом случае это вряд ли имеет значение - если все это не помещается в кэш, перемещение блока, подобное этому, почти всегда будет ограничено пропускной способностью памяти - перемещения не получаются намного быстрее, но чтобы получить последнее улучшение, вы хотите использовать инструкции / регистры SSE.
Редактировать: Последняя деталь. VC ++ (помимо прочего) не позволит вам определить метку внутри блока _asm, поэтому, если вам нужна метка, вы делаете что-то вроде:
_asm {
mov ecx, howmany
mov esi, offset FLAT:source
mov edi, offset FLAT:dest
}
move_loop:
_asm {
lodsd
stosd
loop move_loop
}
1 Ну, не все - FS и, возможно, GS не будут такими, но CS, DS, ES и SS будут. В любом случае, вы не хотите менять ни одну из них (на самом деле, попытка сделать это обычно приводит к закрытию вашей программы).