Перемещение одного и того же байта на каждый адрес между двумя разными адресами? - PullRequest
0 голосов
/ 01 ноября 2018

Можно ли вообще быстро переместить один и тот же байт в группу адресов

pseudocode...
mov ax, 10
mov [memAddrStart to MemAddrEnd], ax

Это поместит AX в каждый адрес, чтобы я мог ссылаться на любой адрес в последовательности и всегда получать 10.

Возможно ли это, и если нет, как я могу обойти это?

1 Ответ

0 голосов
/ 02 ноября 2018

Да, есть инструкция, специально разработанная для этого.

Это все же нужно немного настроить.

cld                                     //CLear the Direction flag (optional, see below)
mov al,10                               //we are moving bytes
mov edi,MemAddrStart                    //Destination = start
mov ecx,(MemAddrEnd - MemAddrStart)+ 1  //Count = (end-start)+1
rep stosb                               //(REP)repeat (STOS)storing (B)bytes until done

См .: Документация STOSB .

Указатель направления
Флаг direction определяет, будет ли rep stosx двигаться вперед или назад. Вы должны всегда оставлять его движущимся вперед, потому что это направление по умолчанию.
Если вы установите его в обратном направлении, используя std, затем убедитесь, что вы вернули его в нормальное состояние, используя cld впоследствии. В противном случае могут произойти плохие вещи, потому что многие компиляторы и операционные системы предполагают, что флаг направления всегда ясен.

'[...] если нет, как мне это сделать?'
Конечно, вы можете запрограммировать это, используя простой цикл:

mov al,10                               //we are moving bytes
mov edi,MemAddrStart                    //destination = start
mov ecx,(MemAddrEnd - MemAddrStart)+ 1  //length = (end-start)+1
Loop:
dec ecx                                 //This is
mov [edi+ecx],al                        //what `rep stosb` 
jnz Loop                                //does

Обратите внимание, что для эффективности и простоты мой цикл начинается в конце и возвращается обратно. stos (с очищенным флагом направления) начинается с начала. В противном случае они работают одинаково.
Поскольку я уменьшаю ecx, я могу использовать неявный тест для нуля (jnz), и мне не нужно добавлять другой тест или другой регистр, чтобы проверить, закончил ли я.

Замечания по коду вашего образца

mov ax, 10
mov [memAddrStart to MemAddrEnd], ax

Этот код перемещает слово (16 бит). Это записывает байты

Address        HEX   DEC
MemAddrStart:   0A    10
MemAddrStart+1: 00    00

Память, а не то, что вы хотите, если вы делаете в цикле следующее:

dec ecx 
mov [edi+ecx],ax           
jnz Loop          

Вы напишите следующее:

Address        HEX   DEC
MemAddrStart:   0A    10
MemAddrStart+1: 0A    10
....
MemAddrEnd      0A    10
MemAddrEnd+1    00    00  <<-- Oops, you're writing past the buffer.

Это известно как переполнение буфера , что является ошибкой, которая может вызвать всевозможные неприятные проблемы.

Если вы хотите сохранить слова, вам придется изменить свой код для этого (mov ecx,(end-start+1)/2 rep stosw).

...