Переписываю из буфера 1 в буфер 2... Пишу стандартно: mov ecx,length_to_copy mov edi,Buff2 mov esi,Buff1 rep movsb length_to_copy определяется динамически. Как правило, это килобайты. Есть мнение, что переписывая кусками побольше (MOVSD), будем быстрее. В А&О ничего не нашел... И что вообще предпочтительнее: movs m32,m32 или movsd?
Есть мнение, что переписывая кусками побольше (MOVSD), будем быстрее. ну а как же иначе. То цикл из n проходов, а то n/4. Конечно быстрей.
C movsd быстрее будет Code (Text): mov esi,offset Buff1 mov edi,offset Buff2 mov ecx,length_to_copy shr ecx,2 rep movsd mov ecx,length_to_copy and ecx,3 rep movsb Без movsd ещё быстрее будет Code (Text): mov esi,offset Buff1 mov edi,offset Buff2 mov ecx,length_to_copy cmp ecx,4 jl b_c sub ecx,4 @@: mov eax,[esi+ecx] mov [edi+ecx],eax sub ecx,4 js @F mov eax,[esi+ecx] mov [edi+ecx],eax sub ecx,4 jns @B @@: add ecx,4 b_c: jz _end @@: mov al,[esi+ecx-1] mov [edi+ecx-1],al dec ecx jnz @B _end:
LEDVINA > "В А&О ничего не нашел..." Видать плохо искал... Посмотри Копирование памяти, хотя там оптимизация под большие блоки. Но rep movsd для "килобайтных" блоков это наверное лучший вариант (имхо)
Когда нужна не скорость, а маленький размер кода: push length_to_copy push B1 push B2 call RtlMoveMemory Это короче, чем циклы копирования
Что интересно, в MSDN RtlMoveMemory документирована только для DDK. kernel32.dll экспортирует эту ф-цию (на самом деле форвардит в ntdll.dll), но в хидерах эта ф-ция определена так: Code (Text): #define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length)) Да оно и понятно - размер далеко не маленький, rep movsb будет на 4 байта меньше.
Ну всё-таки RtlMoveMemory (CopyMemory) это функция, без которой тяжело в языках, не имеющих возможности вставок ассемблерного кода. Для этих случаев это единственный приемлимый вариант. Тут уже не до размеров кода
Как интересно.. В WIN32 Programmer's Reference от Борланды светятся FillMemory, MoveMemory, ZeroMemory (как See also в CopyMemory) и никаких ртл-ов..
Борланд гонит Имхо, это всего лишь алиасы, например из басика : CopyMemory Lib "kernel32" Alias "RtlMoveMemory". Можно обозвать как угодно: ДвиньМоюМеморюОтсюдаТуда Lib "kernel32" Alias "RtlMoveMemory" и вызывать: Call ДвиньМоюМеморюОтсюдаТуда(Туда, Отсюда, Столько). И будет работать. Если посмотреть экспорт кернелл через Depends, то обнаруживается, что никаких там FillMemory, MoveMemory, ZeroMemory, CopyMemory нет. Есть RtlFillMemory, RtlMoveMemory, RtlZeroMemory. P.S. Сами они в кернелл не сидят, а импортируются кернелом из ntdll. Т.е. entry point обозначена как ntdll.RtlFillMemory, ntdll.RtlMoveMemory, ntdll.RtlZeroMemory
Да, есть только RTL. В хидерах вижуала они переопределяются на copymem, memset... или что-то в этом роде чтоб оптимизировать код по размеру и скорости. Не забывайте что само имя функции ("RtlCopyMemory" или как там её?) в IAT тоже место занимает. Зато эти ртл-функции тщательно проверяют валидность параметров, поэтому они "безопаснее" чем rep movsd.
Quantum Зато эти ртл-функции тщательно проверяют валидность параметров, поэтому они "безопаснее" чем rep movsd. В wxpsp2 ни ntdll.RtlMoveMemory, ни ntdll.RtlFillMemory, ни ntdll.RtlZeroMemory не проверяют валидность параметров. Единственное преимущество первой из них перед rep movsd, то, что она определяет и корректно справляется с возможным пересечением областей источника и приемника.
"Документированной функции" MoveMemory не существует вообще. Определена она в заголовках так: Code (Text): #define MoveMemory(pbDst,pbSrc,cb) memmove((pbDst),(pbSrc),(cb)) #define MoveMemory RtlMoveMemory CopyMemory - это совершенно другая вещь: