Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.10.29;
Скачать: CL | DM;

Вниз

Как осуществить сдвиг с переносом для 64 битного значения?   Найти похожие ветки 

 
Still Swamp   (2006-09-17 19:21) [0]

Как осуществить сдвиг с переносом для 64 битного значения?


 
begin...end ©   (2006-09-17 20:25) [1]

Не совсем понял, о каком переносе идёт речь. Если имеется в виду обычный линейный сдвиг 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 (сдвиг для которого реализован, кстати, по описанному принципу) и не мучаться.


 
Still Swamp   (2006-09-17 22:13) [2]

С асмомо ответ исчерпывающий. А по поводу дельфи... есть там shl и shr. Но это сдвиг без переноса.


 
begin...end ©   (2006-09-17 22:49) [3]

> 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 23:00) [4]

хм... может я сильно туплю, но еще раз. shl сдвигает без переноса сдвигаемых бит. я проверил этот факт.


 
oxffff ©   (2006-09-17 23:06) [5]

Что ты имеешь ввиду под переносом.

Сдвиг через флаг переноса CF


 
oxffff ©   (2006-09-17 23:08) [6]

Если использовать SHLD, SHRD , то в CF последний бит, участвовавший в сдвиге.


 
Still Swamp   (2006-09-17 23:08) [7]

Действие CF на оператор SHL в Delphi распространяется?


 
oxffff ©   (2006-09-17 23:13) [8]

Ты хочешь чтобы из CF на освободившееся место ?


 
oxffff ©   (2006-09-17 23:25) [9]

Тебе тогда надо использовать инструкции RCL или RCR


 
Pavia ©   (2006-09-18 00:05) [10]

Взять 128 битное число сделать сдвиг SHL потом сделать OR от нижней и верхней части.


 
Anatoly Podgoretsky ©   (2006-09-18 00:25) [11]

Что касается переноса придется делать на ассемблере, Дельфи не оперирует разрядом переноса.


 
Германн ©   (2006-09-18 00:39) [12]


> Anatoly Podgoretsky ©   (18.09.06 00:25) [11]
>
> Что касается переноса придется делать на ассемблере, Дельфи
> не оперирует разрядом переноса.

Формально да. Но ассемблер не обязателен.


 
Anatoly Podgoretsky ©   (2006-09-18 00:53) [13]

Ну конечно трюками можно это обойти.


 
Джо ©   (2006-09-18 01:43) [14]

С терминологией тут нелады, ИМХО. Тут циклический сдвиг обсуждается или иное?


 
Германн ©   (2006-09-18 01:49) [15]


> Anatoly Podgoretsky ©   (18.09.06 00:53) [13]
>
> Ну конечно трюками можно это обойти.
>

Почему трюками? Неужели использование множеств и директивы absolute есть большие трюки чем ASM-вставки в код паскалевской программы?


 
Германн ©   (2006-09-18 01:53) [16]


> Джо ©   (18.09.06 01:43) [14]
>
> С терминологией тут нелады, ИМХО. Тут циклический сдвиг
> обсуждается или иное?
>


Имхо, да. Если учесть

Still Swamp   (17.09.06 23:00) [4]

хм... может я сильно туплю, но еще раз. shl сдвигает без переноса сдвигаемых бит. я проверил этот факт.


 
Германн ©   (2006-09-18 01:56) [17]


> Германн ©   (18.09.06 01:53) [16]

P.S.
Имхо, да - относилось к
> Тут циклический сдвиг
> > обсуждается


 
begin...end ©   (2006-09-18 07:51) [18]

> Still Swamp   (17.09.06 23:00) [4]

Возможно, я тоже туплю. Чтобы никто из нас не тупил, давайте разбираться:

1. О каком переносе идёт речь? Что и куда должно быть перенесено?
2. Какой сдвиг нужен -- линейный (как в [1]) или циклический? Внимательно посмотрите на исходное и полученное значения в [1] -- Вам нужно это, или что-то другое?

Только без туманностей, плз. Чётко и конкретно.


 
Still Swamp   (2006-09-18 13:29) [19]

Я уже в общем выкрутился, но надо было вот такое при сдвиге влево, причем желательно без ухода в асм:
10001 -> 00011

Что касается терминалогии, то я почему то всегда был уверен, что эта операция называется сдвиг с переносом. Те сдвигаем допустим байт и все биты на вуходе переносятся в противоположную часть.


 
Германн ©   (2006-09-18 14:36) [20]


> но надо было вот такое при сдвиге влево, причем желательно
> без ухода в асм:
> 10001 -> 00011

Так это же сдвиг вправо?


 
Anatoly Podgoretsky ©   (2006-09-18 15:23) [21]

Still Swamp   (18.09.06 13:29) [19]
А это уже циклический сдвиг, а не через перенос.
Через перенос будет 1.0010 + CF


 
palva ©   (2006-09-18 15:25) [22]

Так это же сдвиг вправо?
Если сдвиг циклический, то пойдешь налево, придешь направо.


 
begin...end ©   (2006-09-18 15:48) [23]

> Still Swamp   (18.09.06 13:29) [19]

Это циклический сдвиг (в приведённом примере -- циклический сдвиг 5-разрядного значения влево на 1 разряд).

В Delphi готовых средств для циклического сдвига Int64 я не встречал (хотя для 32-разрядных значений они есть), но можно сделать их самому из команд линейного сдвига. Вот пример (ROL для Int64 на 20 разрядов):

00000001001000110100010101100111  10001001101010111100110111101111  <-- исходное число (01234567 89ABCDEF)
01010110011110001001101010111100  11011110111100000001001000110100  <-- результат      (56789ABC DEF01234)


var
 I: Int64;
begin
 I := $0123456789ABCDEF;
 I := (I shr (64 - 20)) or (I shl 20);
 ShowMessageFmt("%x", [I])  <-- "56789ABCDEF01234"
end


Как видите, решение получилось в одну строчку. И без асма.


 
Still Swamp   (2006-09-18 19:17) [24]

Спасибо за науку.



Страницы: 1 вся ветка

Текущий архив: 2006.10.29;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.055 c
6-1149591835
Comrade
2006-06-06 15:03
2006.10.29
Количество траффика из Инета


3-1157479783
DBE
2006-09-05 22:09
2006.10.29
paradox на другом компе


1-1158529404
Dublicator
2006-09-18 01:43
2006.10.29
Balloon Tips


2-1160679520
dreamse
2006-10-12 22:58
2006.10.29
Проблема при перезагрузке


11-1132569120
Reset
2005-11-21 13:32
2006.10.29
Подсказка-"шарик" у иконки трея