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

Вниз

Циклический сдвиг вправо и влево   Найти похожие ветки 

 
DelphiDummy   (2002-10-31 22:31) [0]

Мастера! Подскажите, пожалуйста, есть ли в Delphi операция циклического сдвига вправо и влево? В Builder`е этим занимаются функции _lrotr и _lrotl. А есть ли что-либо подобное и в Delphi?

И еще: если такой функции все же нет, то не подскажет ли кто-нибудь, как с помощью стандартных функций Delphi написать функцию циклического сдвига?

Заранее всем ответившим большое спасибо!


 
Ученик ©   (2002-10-31 23:00) [1]

Поддерживается встроенный ассемблер
asm
...
end


 
Anatoly Podgoretsky ©   (2002-10-31 23:16) [2]

если без использования АСМ то иожно так (для 32 бит)
if N and 1 <> 0 then N shr 1 or $80000000 else N shr 1
if N and $80000000 <> 0 then N shl 1 or 1 else N shl 1


 
DelphiDummy   (2002-11-01 10:13) [3]

Дело в том, что я не знаю ассемблера вообще. То есть, приблизительно я представляю, как прикрутить ассемблерную вставку к своей программе, но то, что будет написано внутри asm ... end, я все равно объснить не смогу.

А насчет второго варианта я не совсем понял: во-первых, там где-нибудь должны стоять скобки или нет? Во-вторых, что это за цифра такая -- 80000000? Что она означает в данном случае?

Спасибо!


 
Alx2 ©   (2002-11-01 10:18) [4]

>DelphiDummy (01.11.02 10:13)
asm
ror (или rol) variable <то, в чем сдвигаем>, 3 // - то на что сдвигаем
end;


 
Ученик ©   (2002-11-01 10:20) [5]

{ Project JEDI Code Library (JCL) }
//------------------------------------------------------------------------------

type
TBitRange = Byte;

function LRot(const Value: Byte; const Count: TBitRange): Byte; assembler;
asm
MOV CL, Count
ROL AL, CL
end;

//------------------------------------------------------------------------------

function LRot(const Value: Word; const Count: TBitRange): Word; assembler;
asm
MOV CL, Count
ROL AX, CL
end;

//------------------------------------------------------------------------------

function LRot(const Value: Integer; const Count: TBitRange): Integer; assembler;
asm
MOV CL, Count
ROL EAX, CL
end;

//------------------------------------------------------------------------------

function RRot(const Value: Byte; const Count: TBitRange): Byte; assembler;
asm
MOV CL, Count
MOV AL, Value
ROR AL, CL
MOV Result, AL
end;

//------------------------------------------------------------------------------

function RRot(const Value: Word; const Count: TBitRange): Word; assembler;
asm
MOV CL, Count
MOV AX, Value
ROR AX, CL
MOV Result, AX
end;

//------------------------------------------------------------------------------

function RRot(const Value: Integer; const Count: TBitRange): Integer; assembler;
asm
MOV CL, Count
MOV EAX, Value
ROR EAX, CL
MOV Result, EAX
end;


 
Dr_Mike ©   (2002-11-01 10:28) [6]

А почему все функции завершаются именно так "MOV Result, AL(AX,EAX)" ???


 
han_malign ©   (2002-11-01 10:41) [7]

function _shl(Operand : word; Count: byte): WORD;
asm
push CX //возможно не нужно - непомню
mov CL,Count
shl AX,DX
pop CX //возможно не нужно - непомню
end;

для други типов
function _shl(Operand : Dword; Count: byte): DWORD;
asm
push CX //возможно не нужно - непомню
mov CL,Count
shl EAX,CL
pop CX //возможно не нужно - непомню
end;
function _shl(Operand : byte; Count: byte): byte;
asm
push CX //возможно не нужно - непомню
mov CL,Count
shl AL,CL
pop CX //возможно не нужно - непомню
end;

аналогично
RCx - циклический через флаг переноса
ROx - циклический через флаг переполнения
SAx - арифметический(не трогается знаковый бит)
SHx - сдвиг
SHxD- сдвигает превый операнд с присоединенным вторым
function _SHxD(Operand: int64;Count: byte):int64;
asm
push CX //возможно не нужно - непомню
mov CL,Count
SHxD EAX,EDX,CL
pop CX //возможно не нужно - непомню
end;

где x - L или R
короче
http://webster.cs.ucr.edu/Page_TechDocs/Doc386
или найди TechHelp(еще досовский справочник)

З.Ы. в Паскале целочисленные аргументы впихиваются в аккумуляторы (пару EAX:EDX)если помещаются, аналогично Result - тоже соответствует этой регистровой паре, поэтому приведенные примеры полностью функциональны.


 
Ученик ©   (2002-11-01 10:46) [8]

>Dr_Mike © (01.11.02 10:28)
Хороший вопрос, видимо, разные люди писали :-)


 
han_malign ©   (2002-11-01 10:48) [9]

Кстати MOV Result, AL(AX,EAX) совсем не нужен потому что фактичечески Result это тоже AL(AX,EAX,EAX:EDX)


 
han_malign ©   (2002-11-01 11:59) [10]

Извиняюсь int64 в функцию передается через стек поэтому
function _SHRD(const Value: int64; const Count: byte): int64; assembler;
asm
MOV CL,AL//Count
MOV EAX,DWORD PTR([Value])
MOV EDX,DWORD PTR([Value+4])
SHRD EAX,EDX,CL
SHR EDX,CL
end;
function _SHLD(const Value: int64; const Count: byte): int64; assembler;
asm
MOV CL,AL//Count
MOV EAX,DWORD PTR([Value])
MOV EDX,DWORD PTR([Value+4])
SHLD EDX,EAX,CL
SHL EAX,CL
end;


 
Dr_Mike ©   (2002-11-02 00:25) [11]

А точно через стек ???


 
apay ©   (2002-11-02 01:03) [12]

Я вообще не пойму, зачем нужны:
MOV Result, EAX
MOV EAX, <Param1>

при передаче пар-ров типа Byte, Word, Integer, Pointer ...
если не указано stdcall или что то подобное,
первый пар-р в EAX(AX или AL) , второй в EDX, третий в ECX, остальные ч/з стек.
Result берется из EAX (AX, AL), иногда EDX:EAX


 
Anatoly Podgoretsky ©   (2002-11-02 09:07) [13]

Dr_Mike © (01.11.02 10:28)
Хороший вопрос, ответ от незнания автором данной библиотеки Дельфи, к тому же непоследовательносять, в одних есть, а в других нет.

У него есть и вторая незначительная ошибка - ключевое слово Assembler лишнее. И так еще по мелочам.


 
DelphiDummy   (2002-11-02 11:10) [14]

В данный момент у меня в программе написано просто:

asm
ror Mask1, 4
end;

Это синтаксически правильно? Или все-таки нужно писать все, что мне указал здесь Ученик? И кстати, в том варианте, который написал Ученик, я так понял, есть ошибки? Не мог бы кто-нибудь точно сказать, что за ошибки?

Есть еще один вопрос глупый, но все-таки хотелось бы спросить: мне что, все сразу функции писать (из тех, которые здесь написал ученик) или просто нужно выбрать одну из них для своего типа переменных?

Спасибо!


 
DelphiDummy   (2002-11-02 11:29) [15]

Уважаемый han_malign! Я ничего не понял из того, что Вы написали. По ссылке, которую Вы мне дали, я не нашел ничего, кроме кучи html-файлов. Загрузил один из них и получил длинный список, в котором я ничего не понял. Вот одна из строчек в этом списке:

D0 /0 ROL r/m8,1 3/7 Rotate 8 bits r/m byte left once

Что такое D0? Что такое /0? Что такое r? Что такое m8?.. В общем, что такое это все?

А если я в программе написал просто rol Mask1, 4 или ror Mask1, 4 -- это разве не циклический сдвиг вправо и влево?


 
down   (2002-11-02 12:06) [16]

пиши просто X := Y shr {или shl} Z


 
DelphiDummy   (2002-11-02 12:09) [17]

Нда... Ну, спасибо, down, за бесполезный совет. Повторюсь: мне нужен не побитовый сдвиг, а именно циклический. Разница, надеюсь, понятна?


 
DelphiDummy   (2002-11-02 12:13) [18]

Кстати, господа! На все ваши варианты компилятор Delphi 5.5 ругается, что inline assembler error или что-то в этом роде. Короче говоря, ошибка внутреннего ассемблера. В help"е написано, что встроенный компилятор ассемблера увидел ошибку в ассемблерной вставке в моей программе. И ругань эта идет и на вариант от пользователя Ученик, и на вариант от пользователя han_malign.

Вопрос: неужели никто не может подсказать реально работающую функцию циклического сдвига? Чтобы было еще понятнее и дабы сократить размеры ответов, напишу, что есть переменная-маска Mask1 типа Integer, которую надо сместить вправо сначала на четыре бита, потом еще на четыре, а потом вернуть влево на 11 бит. Исходя из этого никто не может мне писать ассемблерную вставку в программу, реально позволяющую осуществить то, что я написал?

Спасибо!


 
down   (2002-11-02 12:23) [19]

а, извини, невимательно прочитал
может быть, это поможет (из idglobal.pas, не знаю, есть ли в D5)function ROL(val: LongWord; shift: Byte): LongWord; assembler;
asm
mov eax, val;
mov cl, shift;
rol eax, cl;
end;

function ROR(val: LongWord; shift: Byte): LongWord; assembler;
asm
mov eax, val;
mov cl, shift;
ror eax, cl;
end;


 
Anatoly Podgoretsky ©   (2002-11-02 12:57) [20]

down (02.11.02 12:23)
Это пишется так:


function ROL(val: LongWord; shift: Byte): LongWord;
asm
mov cl, dl;
rol eax, cl;
end;

function ROR(val: LongWord; shift: Byte): LongWord;
asm
mov cl, dl;
ror eax, cl;
end;


Для Д3 LongWord заменяется на Longint


 
down   (2002-11-02 13:05) [21]

Anatoly Podgoretsky © (02.11.02 12:57)
ok, передам разработчикам Indy


 
Anatoly Podgoretsky ©   (2002-11-02 13:10) [22]

Не надо, это их право так писать, сделай им снисхождение, не все же грамотные, тем более что страшного ничего нет, рабочий код в обоих случаях


 
DelphiDummy   (2002-11-02 13:11) [23]

Anatoly Podgoretsky (02.11.02 12:57)

А для типа Integer пишется так же, как и для LongWord? Сейчас попробую вставить указанное Вами в мою программу. О результатах сообщу дополнительно.


 
Anatoly Podgoretsky ©   (2002-11-02 13:15) [24]

Не надо сообщать, это работает много лет, начиная с Д2, для Д1 немного по другому
С интегер сложнее, размер у него задается компилятором и неоднократно менялся, да и смысла делать циклический сдвиг для знаковых как то непонятен


 
DelphiDummy   (2002-11-02 13:25) [25]

Anatoly Podgoretsky (02.11.02 13:15)

OK! Рассказываю все с самого начала. Есть задача: реализовать алгоритм блочного шифрования ГОСТ-28147-89 в Delphi. Кто знаком с этим алгоритмом, тот знает, что там используется функция циклического сдвига.

Более того, у меня уже есть абсолютно точно работающая программа, написанная на Builder`е. Задача облегчается: теперь надо просто переписать эту программу на Delphi. Я переписал, запустил -- не работает. Все проверки всех полей работают, но как только нажимаешь на кнопку шифрования, выдается ошибка Access violation at address 0044AF17 in module "lab2.exe". Read of address 005EC2F8. Так как я понятия не имею, что точно не работает, то подумал, что дело в функции циклического сдвига.

Я вставил код, представленный Вами, Анатолий, все опять же запускается, но ошибка не исчезает. В связи с этим вопрос: не могли бы Вы мне помочь разобраться с этим делом? Я мог бы прислать по почте уже работающую программу на Builder`е и прислать свой вариант на Delphi. Быть может, для мастера не составит труда найти ошибку. Может быть, я вообще не там ищу, и ошибка-то вот она, но я ее не вижу. Если можно так сделать, напишите, пожалуйста, здесь об этом. Заранее спасибо!

to All: Народ! Кто-нибудь еще может мне помочь с переписыванием программы на Builder`е под Delphi? Кто знаком с алгоритмами шифрования и, в частности, с алгоритмом ГОСТ-28147-89?


 
down   (2002-11-02 13:27) [26]

Дебуггер не помогает?


 
DelphiDummy   (2002-11-02 13:34) [27]

down (02.11.02 13:27)

> Дебуггер не помогает?

Нет, не помогает. Может быть, ты можешь помочь? Если есть время, конечно...


 
Anatoly Podgoretsky ©   (2002-11-02 13:38) [28]

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


 
DelphiDummy   (2002-11-02 13:43) [29]

Anatoly Podgoretsky (02.11.02 13:38)

Ну, так Вы мне не поможете найти эту ошибку? Программа на Delphi не очень большая... Просто я уже запарился ее искать. Не знаю, где там и что у меня не инициализировано, потому что я переписывал программу в точности с работающей программы, написанной на Builder`е. Почему на Builder`е она работает, а на Delphi нет, я не знаю.


 
DelphiDummy   (2002-11-02 13:45) [30]

Кстати, на сайте готовых решений, ссылка на который есть на этом сайте, я нашел такую функцию в одной из программ:

function ROTATE_LEFT(x, n: UINT4): UINT4;
begin
Result := (((x) shl (n)) or ((x) shr (32-(n))));
end;


Разве это не решение? Это ли не функция циклического сдвига? Или эта функция и те, которые были здесь приведены на asm -- это две разные вещи?


 
down   (2002-11-02 13:48) [31]

Range checking включено?


 
DelphiDummy   (2002-11-02 13:56) [32]

down (02.11.02 13:48)

> Range checking включено?

Извините, конечно, но что такое range checking?


 
down   (2002-11-02 14:03) [33]

Range checking - проверка на выход за границы массива. Выход за границы массива иногда (в лучшем случае) вызывает AV => может помочь


 
DelphiDummy   (2002-11-02 14:15) [34]

down (02.11.02 14:03)

> Range checking - проверка на выход за границы массива. Выход за
> границы массива иногда (в лучшем случае) вызывает AV => может
> помочь

Честно говоря, я вообще не понимаю, о чем Вы говорите. К моему большому сожалению, я не умею пользоваться debugger`ом. :(

Как же мне все-таки понять, что за ошибка у меня в программе? :(


 
down   (2002-11-02 14:29) [35]


> Честно говоря, я вообще не понимаю, о чем Вы говорите. К
> моему большому сожалению, я не умею пользоваться debugger`ом.
> :(

Тааак... с этого и надо было начинать. Действительно, как дебуггер может помочь, если пользоваться им не не умеешь.
Самое время научиться.
1.Поставь точку останова в начале процедуры, вызываемой при нажатии кнопки "зашифровать" (правая кнопка манипулятора, add breakpoint)
2.Запускаем программу, давим "зашифровать", нажимаем F7, пока не появится ошибка.
3.Смотрим, что ее вызвало, исправляем.
А вообще, см. книжку "Delphi for dummies" :)


 
DelphiDummy   (2002-11-02 14:48) [36]

Спасибо, конечно, но Вы уверены, что последовательность действий именно такая?

1. BreakPoint я поставил. Но! Процедура, Encrypt_ButtonClick у меня состоит всего из трех строчек: задаются два параметра, потом управление передается другой процедуре. А именно:

procedure TMain_Form.encrypt_buttonClick (Sender: TObject);

begin
param1 := 3;
param2 := 1;
Code (True)
end;


2. Запускаю программу клавишей F9, надимаю на кнопку `Зашифровать`, программа вываливается длинным сообщением и окошком с кнопкой OK. Нажимаю на кнопку OK, нажимаю F7, выделяется строка с вышеприведенной функцией, и все! И что мне это дало?

3. Я, конечно, был бы рад посмотреть, что вызвало ошибку, но только как это реально сделать-то?

P.S. И насчет книжки... а где ее взять-то? :)


 
down   (2002-11-02 15:02) [37]

Что за сообщение-то? И у меня написано - нажимать Ф7, пока не появится ошибка, а ты один раз нажал.
Про книжку я пошутил, не знаю, есть ли такая, просто есть такая серия - "Word for dummies", "Excel for dummies" (на русский переводятся как "... для идиотов"), и псевдоним у тебя подходящий.


 
DelphiDummy   (2002-11-02 15:28) [38]

За идиота спасибо, конечно. :( Dummy -- это вообще-то не идиот, а чайник. Но это я так, на всякий случай. Сообщение у меня следующее (дословно):

Project lab2.exe raised exception class EAccessViolation with message "Access violation at address 0044AF27 in module "lab2.exe". Read of address 003EFFFC". Process stopped. Use Step or Run to continue.

Это написано в окошке с кнопкой OK. Нажимаю OK. Нажимаю F7, курсор перемещается к началу процедуры, где я ставил BreakPoint, и все. При повторном нажатии F7 ничего не происходит.

И что дальше?


 
DelphiDummy   (2002-11-02 15:34) [39]

А может, я вообще breakpoint неправильно ставлю? Я делаю это так: захожу в меню Run, выбираю там строчку Add Breakpoint, и в ней выбираю Source Breakpoint. Так или нет? Потому что при нажатии правой кнопки мышки у меня никакой add breakpoint нет. :(

P.S. Я скоро с ума сойду с этой программой. И самое обидное, что вот она, лежит рядом на Builder`е, прекрасно работает, а вот на Delphi не работает, хотя написана точь-в-точь так же. :( Эх...


 
down   (2002-11-02 16:00) [40]


> За идиота спасибо, конечно. :(

Это книжки у нас такие продаются, я тебя идиотом не считаю, ok?
Кстати, может быть, не "... для идиотов", а "... для чайников"... Но "... для идиотов" тоже что-то вроде было...

Про то, как установить точку останова, я сказал не совсем правильно, извини. Нужно нажать правой кнопкой на требуемой строчке, потом в меню выбрать Debug -> Toggle breakpoint (или F5).

Точку останова нужно поставить в строке, выполняемой до того, как проявляется ошибка. Если у тебя ошибка проявляется при нажатии кнопки шифрования, то поставь ее на месте (*), там должна появиться красная точка.

begin
(*) param1 := 3;
param2 := 1;
Code (True)
end

Если при нажатии на кнопку выполняется эта процедура, то программа остановится на строчке (*), никаких окошек до этого показываться не должно. Далее нажимаешь Ф7, пока не дойдешь до ошибки.


 
DelphiDummy   (2002-11-02 17:06) [41]

Кажется я понял, в чем дело. Но, может быть, это мне только кажется. У меня есть в программе такая строчка:

for j := 1 to param1 do for i := 0 to 8 do Block[i] := Fun (Block, i);

По идее, это неправильно, ведь так? Получается, что при выполнении цикла для j во второй раз массив Block начнет заполняться заново, а в этом нет никакого смысла.

В связи с этим еще один вопрос (надеюсь, его решение поможет мне наконец-то отладить программу). В аналогичной программе на Builder`е эта строка выглядит так:

for (j = 1; j < param1; j++)
for (i = 0; i < 8; i++) Block := Fun (Block, i);


Здесь Fun -- это отдельная функция, объявленная следующим образом:

unsigned __int32* __fastcall TForm1::Fun(unsigned __int32 Block[], int ii)

Как видно, у нее есть параметр типа Cardinal -- это динамический массив Block. А сама функция тоже типа Cardinal. Почему-то Builder прекрасно принимает строчку Block := Fun (Block, i), а Delphi пишет, что нельзя типу array присвоить значение Cardinal.

Вопрос: как с этим бороться? Почему в Builder`е проходит Block := Fun (Block, i), а в Delphi не проходит?

Спасибо!


 
Anatoly Podgoretsky ©   (2002-11-02 17:20) [42]

Все зависит от того, что такое Block, Fun и что делается внутри Fun может и не совсем бессмысленно.


 
down   (2002-11-02 17:33) [43]

В Делфи массивы объявляются по-другому, нужно писать
type
CardinalArr = array of Cardinal;
function Fun(Block: CardinalArr; I: Integer): CardinalArr;



 
DelphiDummy   (2002-11-02 19:07) [44]

А есть большая разница, если я написал проще в Delphi?

procedure Fun (Block: Array of Cardinal; I: Integer): Cardinal;

Хотя в этом случае тип функции Fun получается Cardinal, и когда я пишу потом Block := Fun (Block, i), копилятор пишет, что нельзя array присвоить Cardinal.

КСТАТИ! Забыл сказать: в программе на Builder`е в конце функции Fun написано return Block. То есть, в конце возвращается не значение Fun, а значение Block. Может это на что-то влияет?

Anatoly Podgoretsky (02.11.02 17:20)

> Все зависит от того, что такое Block, Fun и что делается
> внутри Fun может и не совсем бессмысленно.

Block -- это динамический массив типа Cardinal, Fun -- это цикловая функция, объявленная как Fun (Block: Array of Cardinal; I: Integer): Cardinal; То, что делается внутри Fun, приведу ниже:

function TMain_Form.Fun (Block: array of Cardinal; ii: Integer): Cardinal;

var
S: Cardinal; // число S
Mask1, Mask2: Cardinal; // маски для получения необходимых бит числа S
Si: Cardinal; // биты числа S
n: Integer;

begin
Mask1 := 15;
Mask2 := (num - 1);
Mask2 := Mask2 shr 4;
S := (Block[0] + key[ii]) div num; // получаем число S
for n := 0 to 8 do
begin
Mask1 := ror (Mask1, 4); // циклический сдвиг вправо маски
Si := (S and Mask1); // получаем необходимые биты числа S
Si := (Si shr 4 * (7 - n)); // преобразуем в 4х битное число
S := (S and Mask2); // обнуляем использованные биты S
Si := MatrixV[ii, Si]; // получаем новые биты
Si := (Si shl 4 * (7 - n)); // смещаем их в необходимую позицию
S := (S or Si); // получаем новое значение S
Mask2 := ror (Mask2, 4)
end;
S := rol (S, 11); // осуществляем циклический сдвиг влево
S := (S xor Block[1]); // получаем новое значение S
Block[1] := Block[0]; // правый блок получает значение левого
Block[0] := S // левый блок получает значение S
end;


Вот. Это что-нибудь решает?


 
down   (2002-11-02 19:59) [45]

А что твоя функция должна возвращать, массив или одно значение? Если одно, то как ты массиву присваиваешь ее результат? Если же она возвращает массив, то так и надо писать.
Включи range checking (Project -> Options -> Compiler -> Runtime errors), явно с массивами не то творишь.


 
Anatoly Podgoretsky ©   (2002-11-02 20:03) [46]

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

Значит твоя задача состоит в том, что бы разобраться как работает программа на Билдере и написать ПРАВИЛЬНУЮ реализацию на Дельфи.

Вообще то для начала надо садиться за учебники по Паскалю и по тому языку который используется в Билдере, без этого толку не будет.

Другое решение заказать разработку у профессионального Дельфи программиста.


 
TTCustomDelphiMaster ©   (2002-11-02 20:09) [47]

type
CardinalArr = array of Cardinal;

procedure Fun(var Block: CardinalArr; I: Integer);
begin
end;


 
DelphiDummy   (2002-11-02 20:12) [48]

Да, Анатолий, Вы правы! Я с Вами согласен, что нужно садиться за учебники. Только проблема в том, что нет времени за них садиться. Не знаю, учились ли Вы в университете, и, если учились, то в каком городе это было, но в нашем университете вот есть такие преподаватели, которые дают лабораторную работу, а как ее сделать -- не объясняют, причем совсем, и даже не помогают, когда их попросишь. Все сам! А как я могу сам, если нам Delphi преподавали без году неделя?

Как работает программа на Builder`е,я вроде разобрался. Я же говорю, переписал на Delphi в точности, учтя то, что в Delphi нет некоторых функций, которые есть в Delphi. И программа запускается. Просто ошибки после запуска отловить труднее, чем ошибки компилятора.

А Вы, Анатолий, вместо того, чтобы давать такие советы, до которых я и сам могу додуматься, лучше бы взяли и посмотрели на обе моих программы. Я же предложил прислать эти программы. Если Вы так хорошо разбираетесь в Delphi, я думаю, для Вас не составит труда найти мою ошибку. Правильно? Ну, так что, присылать?


 
DelphiDummy   (2002-11-02 20:16) [49]

Короче! Во избежание дальнейшего размусоливания той темы, которую я затронул, привожу примеры этой функции на Builder`е (работающая) и на Delphi (с глюком).

На Builder`е:

//работа цикловой функции
unsigned __int32* __fastcall TForm1::Fun(unsigned __int32 Block[], int ii)
{
unsigned __int32 S;//число S
unsigned __int32 Mask1=15,Mask2=(num-1);//маски для получения
//необходимых бит числа S
unsigned __int32 Si;//биты числа S
unsigned int n;
Mask2=Mask2>>4;
S=(Block[0]+key[ii])%num;//получаем число S
for (n=0;n<8;n++)
{
Mask1=_lrotr(Mask1,4);//циклический сдвиг вправо маски
Si=(S&Mask1);//получаем необходимые биты числа S
Si=(Si>>4*(7-n));//преобразуем в 4х битное число
S=(S&Mask2);//обнуляем использованные биты S
Si=MatrixV[ii][Si];//получаем новые биты
Si=(Si<<4*(7-n));//смещаем их в необходимую позицию
S=(S|Si);//получаем новое значение S
Mask2=_lrotr(Mask2,4);
}
S=_lrotl(S,11);//осуществляем циклический сдвиг влево
S^=Block[1];//получаем новое значение S
Block[1]=Block[0];//правый блок получает значение левого
Block[0]=S;//левый блок получает значение S
return Block;
}


На Delphi:

function TMain_Form.Fun (Block: CardinalArr; ii: Integer): CardinalArr;

var
S: Cardinal; // число S
Mask1, Mask2: Cardinal; // маски для получения необходимых бит числа S
Si: Cardinal; // биты числа S
n: Integer;

begin
Mask1 := 15;
Mask2 := (num - 1);
Mask2 := Mask2 shr 4;
S := (Block[0] + key[ii]) div num; // получаем число S
for n := 0 to 8 do
begin
Mask1 := ror (Mask1, 4); // циклический сдвиг вправо маски
Si := (S and Mask1); // получаем необходимые биты числа S
Si := (Si shr 4 * (7 - n)); // преобразуем в 4х битное число
S := (S and Mask2); // обнуляем использованные биты S
Si := MatrixV[ii, Si]; // получаем новые биты
Si := (Si shl 4 * (7 - n)); // смещаем их в необходимую позицию
S := (S or Si); // получаем новое значение S
Mask2 := ror (Mask2, 4)
end;
S := rol (S, 11); // осуществляем циклический сдвиг влево
S := (S xor Block[1]); // получаем новое значение S
Block[1] := Block[0]; // правый блок получает значение левого
Block[0] := S // левый блок получает значение S
end;


Вот! Что именно здесь неправильно?


 
down   (2002-11-02 20:37) [50]

Так AV где выдается, в какой строчке? Range checking включил?


 
DelphiDummy   (2002-11-03 00:44) [51]

Range Checking я включил, то есть, галочку где надо поставил. А что такое AV? Если Вы имеете в виду Access violation, то эта ошибка у меня выдается после нескольких выполнений функции Fun. Курсор становится на слове begin в функции Fun.

Чтобы было понятнее, я ниже приведу всю цепочку, по которой передается управление.

{------------------------------------------------------------------------------}

(* Работа цикловой функции. *)

function TMain_Form.Fun (Block: CardinalArr; ii: Integer): CardinalArr;

var
S: Cardinal; // число S
Mask1, Mask2: Cardinal; // маски для получения необходимых бит числа S
Si: Cardinal; // биты числа S
n: Integer;

begin
Mask1 := 15;
Mask2 := (num - 1);
Mask2 := Mask2 shr 4;
S := (Block[0] + key[ii]) div num; // получаем число S
for n := 0 to 8 do
begin
Mask1 := ror (Mask1, 4); // циклический сдвиг вправо маски
Si := (S and Mask1); // получаем необходимые биты числа S
Si := (Si shr 4 * (7 - n)); // преобразуем в 4х битное число
S := (S and Mask2); // обнуляем использованные биты S
Si := MatrixV[ii, Si]; // получаем новые биты
Si := (Si shl 4 * (7 - n)); // смещаем их в необходимую позицию
S := (S or Si); // получаем новое значение S
Mask2 := ror (Mask2, 4)
end;
S := rol (S, 11); // осуществляем циклический сдвиг влево
S := (S xor Block[1]); // получаем новое значение S
Block[1] := Block[0]; // правый блок получает значение левого
Block[0] := S // левый блок получает значение S
end;

{------------------------------------------------------------------------------}

(* Шифрование и дешифрование в режиме простой замены. *)

function TMain_Form.ECBCode (Block: CardinalArr): Cardinal;

var
RL: Cardinal;
i, j: Integer;

begin
//применяем цикловую функцию
for j := 1 to param1 do for i := 0 to 8 do Block := Fun (Block, i);
for j := 1 to param2 do for i := 7 downto 0 do Block := Fun (Block, i);
//обмениваем зашифрованные блоки
RL := Block[0];
Block[0] := Block[1];
Block[1] := RL
end;

{------------------------------------------------------------------------------}

(* Шифрование и дешифрование в режиме гаммирования. *)

procedure TMain_Form.GammaCode;

begin
Gamma[0] := (Gamma[0] + const1) div num; // получаем новый правый блок гаммы
Gamma[1] := (Gamma[1] + const2) div (num - 1); // получаем новый левый блок гаммы
GammaEncoded[0] := Gamma[0];
GammaEncoded[1] := Gamma[1];
ECBCode (Gamma); // шифруем гамму в режиме ЕСВ
IOBlock[0] := (IOBlock[0] xor GammaEncoded[0]); // накладываем гамму на левый блок вх. текста
IOBlock[1] := (IOBlock[1] xor GammaEncoded[1]) // накладываем гамму на правый блок вх. текста
end;


Вот! Если что непонятно здесь, спрашивайте.

P.S. Знать бы хоть, есть ли хоть какая-нибудь надежда отладить эту программу так, чтобы она правильно работала?.. Эх...


 
down   (2002-11-03 10:39) [52]

Ладно, высылай свою программу на assorm@mail.ru, как отошлешь, напиши сюда.


 
DelphiDummy   (2002-11-03 12:48) [53]

Я отослал обе программы: и ту, которая на Builder`е -- это исходная программа, и ту, которая моя на Delphi -- это та, которую написал я сам, стараясь, чтобы она в точности повторяла билдеровскую.

Спасибо, что согласился помочь.


 
Yegor Derevenets   (2002-11-03 15:20) [54]

Скорее всего, я сегодня тормоз...
В паскале родном это shl, shr...

P.S. ActiveTCL рулит!!!



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

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

Наверх




Память: 0.64 MB
Время: 0.025 c
3-45674
Shil
2002-10-23 22:17
2002.11.14
Подскажите какой тип данных выбрать


1-45845
Guest2
2002-11-05 12:56
2002.11.14
Как автоматически проматывать ScroolBar?


3-45695
DDS
2002-10-28 10:37
2002.11.14
Как програмно установить BDE


1-45904
RDA
2002-11-05 18:48
2002.11.14
Internet Explorer


3-45699
oldimax
2002-10-24 18:38
2002.11.14
Paradox 3.5 & Delphi