![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как осуществить сдвиг с переносом для 64 битного значения? [D7, WinXP]
Still Swamp © (2006-09-17 19:21:00)Как осуществить сдвиг с переносом для 64 битного значения?
Still Swamp (2006-09-17 23:00:00) [21]хм... может я сильно туплю, но еще раз. shl сдвигает без переноса сдвигаемых бит. я проверил этот факт.
begin...end (2006-09-17 22:49:00) [22]> Still Swamp (17.09.06 22:13) [2]
Вот код на языке Delphi, аналогичный ассемблерному коду из [1]:
var
I: Int64;
begin
I := $123456789ABCDEF;
I := I shl 10;
ShowMessageFmt('%x', [I]) <-- '8D159E26AF37BC00'
end.
Получается тот же самый результат, т.е. перенос сдвигаемых битов из младшего двойного слова переменной I в её старшее двойное слово происходит корректно, и delphi-оператор shl нормально работает с Int64-переменными.
Still Swamp (2006-09-17 22:13:00) [23]С асмомо ответ исчерпывающий. А по поводу дельфи... есть там shl и shr. Но это сдвиг без переноса.
begin...end (2006-09-17 20:25:00) [24]Не совсем понял, о каком переносе идёт речь. Если имеется в виду обычный линейный сдвиг 64-битного значения, размещённого в двух 32-разрядных регистрах, можно использовать команды сдвига двойной точности (SHLD, SHRD) -- они сдвигают операнд в нужном направлении, заполняя освободившиеся биты битами второго операнда.
Для примера можно рассмотреть, например, линейный сдвиг влево числа $123456789ABCDEF на 10 разрядов:
00000001001000110100010101100111 10001001101010111100110111101111 <-- исходное число (01234567 89ABCDEF)
10001101000101011001111000100110 10101111001101111011110000000000 <-- результат (8D159E26 AF37BC00)
(регистры разделены пробелами). Очевидно, что для выполнения такого сдвига нужно сдвинуть содержимое старшего регистра на 10, заполняя его освобождающиеся младшие биты старшими битами младшего регистра (именно это и сделает команда SHLD), а содержимое младшего регистра просто сдвинуть на 10 разрядов влево, используя обычную SHL (старшие 10 битов регистра теперь можно спокойно потерять). Т.е. код будет такой:
MOV EAX, $01234567 // старшая часть
MOV ECX, $89ABCDEF // младщая часть
SHLD EAX, ECX, 10 // линейный сдвиг двойной точности
SHL ECX, 10 // обычный линейный сдвиг
Это если решать задачу в рамках ассемблерных вставок. А если речь об обычном дельфишном коде, то, само собой, нужно использовать Int64 (сдвиг для которого реализован, кстати, по описанному принципу) и не мучаться.