Машинная инструкция MOVSB станет вашим другом в копировании областей памяти. Он копирует один байт из памяти, адресованной RSI, в память, адресуемую RDI, а затем изменяет оба регистра на следующий элемент (байт).
SECTION .data
Memory DB '0123456789'
Src1st EQU Memory+0
SrcLast EQU Memory+4
Dest1st EQU Memory+3
DestLast EQU Memory+7
SECTION .text
LEA RSI,[Src1st]
LEA RDI,[Dest1st]
CLD
Мы можем визуализировать структуру памяти перед MOVSB таким образом
RSI RDI
| |
0 1 2 3 4 5 6 7 8 9
_________ Src
_________ Dest
После MOVSB
RSI RDI
| |
0 1 2 0 4 5 6 7 8 9
С префиксом инструкции REP повторяется RCX раз. После
MOV RCX,DestLast-Dest1st+1
REP MOVSB
RSI RDI
| |
0 1 2 0 1 2 0 1 8 9
Это не работает, как ожидалось, когда области Sr c и Dest перекрываются - вместо 0120123489 у нас есть 0120120189 . Когда поле назначения находится выше источника (RDI> RSI), мы должны скопировать назад (установить флаг направления) и начать с регистров, указывающих на конец полей.
LEA RSI,[SrcLast]
LEA RDI,[DestLast]
MOV RCX,DestLast-Dest1st+1
RSI RDI
| |
0 1 2 3 4 5 6 7 8 9
После
STD
REP MOVSB
RSI RDI
| |
0 1 2 0 1 2 3 4 8 9
Исходное поле копируется дословно в место назначения без временного массива, не тратя впустую память и часы. После обратного копирования флаг направления должен быть сброшен в состояние по умолчанию, что ожидается интерфейсом большинства операционных систем и библиотечных функций.