![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Помогитес двоичным числом разобраться
Kolan © (2004-12-11 16:14:00)Здравствуйте,
Задеча:
Есть 28 разрядное двоичное число. Это число задает 4 байта. Прервый 00llllll второй llllllll третий 00hhhhhh четвертый hhhhhhhh. Как из этого числа эти байты вычеслить. Формула?
Если не понятно то например(два байта):
Hbits := Value div 4;
if Hbits < 1 then
Hbits := 1;
Lbits := Value - Hbits * 4;
Value это десятичное число. В итоге имею 2 байта.
begin...end (2004-12-16 19:46:00) [1]> [24] Kolan © (16.12.04 03:10)
> Наоборот мне из компьютера на контроллер слать надо.
Ну так бы сразу и сказали... В таком случае [19] даже и пробовать не нужно - не поможет, т.к. значения нескольких битов просто потеряются.
Сейчас попытаюсь сформулировать задание так, как я его понял, и описать решение.
Имеется число (пусть это будет Cardinal). В памяти эта переменная занимает 4 байта, однако число умещается в младших 28 битах. Оставшиеся 4 старших бита всегда равны 0. Требуется представить это число в таком виде:
xxbbbbbb bbbbbbbb xxaaaaaa aaaaaaaa,
где все символы aи b- это и есть те 28 битов, которые были "задействованы" для представления исходного числа.
Т.е., если считать биты, начиная с нуля (справа), то 13-й бит этого преобразованного числа - это 13-й бит исходного, а вот 16-му биту нового числа соответствует 14-й бит старого.
Значения 14, 15, 30 и 31-го битов преобразованного числа игнорируются (обозначены как x).
Тогда последовательность преобразований может быть такой:
I - исходное число:
xxxxbbbbbbbbbbbbbbaaaaaaaaaaaaaa.
1. В исходном числе обнуляем младшие 14 битов, применяя and $FFFFC000, в результате получаем:
xxxxbbbbbbbbbbbbbb00000000000000.
2. Сдвигаем полученное число влево на 2 разряда ( shl 2), получаем:
xxbbbbbbbbbbbbbb0000000000000000<- назовём это J.
3. В исходном числе I обнуляем старшие 18 битов, применяя and $3FFF, в результате получаем:
000000000000000000aaaaaaaaaaaaaa<- назовём это K.
4. Объединяем J и K (операция or), получается:
xxbbbbbbbbbbbbbb 00aaaaaaaaaaaaaa.
Это-то нам и нужно, выделенные 2 нолика находятся в 14-м и 15-м битах, которые игнорируются. Биты исходного числа расположены до и после этих ноликов.
Теперь всё это объединим:
Y := ((X and $FFFFC000) shl 2) or (X and $3FFF).
(Скобки здесь нужны не все, они оставлены для наглядности.)
Это решение полностью аналогично решению [25] Sha © (16.12.04 09:52)(FromIntel), только там число вначале сдвигается на 2 разряда влево, а потом обнуляются младшие 16 битов (результат будет такой же, как и после пунктов 1 и 2). Я просто попробовал пояснить.
DesWind (2004-12-16 11:16:00) [2]
function Intel_WORD_To_MC_DWORD(Intel_WORD: cardinal): cardinal;
var
MCValue : array[0..1] of word;
IntValue: cardinal absolute MCValue;
begin
IntValue:=Intel_WORD;
MCValue[1]:=MCValue[1] shl 2;
MCValue[1]:=MCValue[1] or ((MCValue[0] and $C000) shr 14)
Result:=IntValue;
end;
Ega23 (2004-12-16 10:30:00) [3]
function TTIFF.Swap32(Value: Integer): Integer;
var
b1, b2, b3, b4 : Integer;
begin
b1 := Value and 255;
b2 := (Value shr 8) and 255;
b3 := (Value shr 16) and 255;
b4 := (Value shr 24) and 255;
b1 := b1 shl 24;
b2 := b2 shl 16;
b3 := b3 shl 8;
Result := b1 or b2 or b3 or b4;
end;
Sha (2004-12-16 10:09:00) [4]Sha © (16.12.04 09:52) [25]
Не учел, что внутри слов байты тоже переставлены.
Тогда так
var x, y: cardinal;
ToIntel
у:=(x shr 8) and $00FF00FF or (x shl 8) and $FF00FF00;
y:=(y shr 2) and $0FFFC000 or y and $3FFF;
FromIntel
x:=(y shr 8) and $00FF00FF or (y shl 8) and $FF00FF00;
x:=(x shl 2) and $3FFF0000 or x and $3FFF;
Ega23 (2004-12-16 10:01:00) [5]shl, shr ?
Sha (2004-12-16 09:52:00) [6]ToIntel
y:=(x shr 2) and $0FFFC000 or x and $3FFF
FromIntelx:=(y shl 2) and $3FFF0000 or y and $3FFF
Kolan (2004-12-16 03:10:00) [7]
> begin...end © (15.12.04 18:53) [19]
Вот подробности.
Есть прибор там макросхема. Пользователь задает частоту. Потом по данной мне ф-ле я ее привожу к другому числу. Далее посылаю устройству.А мокросхема, Забыл у точнить, завтра точно сформулирую, в устройстве хочет чтоб я ей передал именно 28 разрадов вот так и не как иначе.
xxbbbbbb bbbbbbbb xxbbbbbb bbbbbbbb
> DesWind © (15.12.04 21:01) [22]
>
> Насколько я понял надо преобразовать двойное слово какого-то
> микроконтроллера в слово для Intel;
Наоборот мне из компьютера на контроллер слать надо. Мой алгоритм
> Kolan © (13.12.04 12:06) [12]
хорошо работает (Только чуть я шас поправил где надо 255 на 256 итд.
>begin...end © (15.12.04 18:53) [19]
Попробую
Благодарю за ответы. :)
DesWind (2004-12-15 21:11:00) [8]Прошу прощения. Так будет лучше:
function MC_DWORD_To_Intel_WORD(MC_DWORD: cardinal): cardinal;
Если двойное слово микроконтроллера со знаком, то его старший бит надо перенести в старший бит интеловского слова;
DesWind (2004-12-15 21:01:00) [9]
Насколько я понял надо преобразовать двойное слово какого-то микроконтроллера в слово для Intel;
function MC_DWORD_To_Intel_WORD(MC_DWORD: integer): integer;
var
MCValue : array[0..1] of word;
IntValue: cardinal absolute MCValue;
begin
MCValue:=MC_DWORD;
MCValue[0]:=MCValue shl 2;
Result:=(IntValue shr 2)and $0HHHHHHH
end;
Это в том случае если MC_DWORD представлено ввиде xxbbbbbb bbbbbbbb xxbbbbbb bbbbbbbb
DesWind (2004-12-15 21:00:00) [10]
Насколько я понял надо преобразовать двойное слово какого-то микроконтроллера в слово для Intel;
function MC_DWORD_To_Intel_WORD(MC_DWORD: integer): integer;
var
MCValue : array[0..1] of word;
IntValue: cardinal absolute MCValue;
begin
MCValue:=MC_DWORD;
MCValue[0]:=MCValue shl 2;
Result:=(IntValue shr 2)and $0HHHHHHH
end;
Это в том случае если MC_DWORD представлено ввиде xxbbbbbb bbbbbbbb xxbbbbbb bbbbbbbb
uny (2004-12-15 19:58:00) [11]я будто что то упустил - в чём проблема?
begin...end (2004-12-15 18:53:00) [12]> [17] Kolan © (14.12.04 21:51)
> Это не галимотья а прикол микросхемы. Я точно не разбирался,
> но число там 28 разрядное и
> записывается так
> xxbbbbbb bbbbbbbb xxbbbbbb bbbbbbbb где xx не используются,
> а b это "0" или "1"
Ну а в программе-то Вашей это число в каком формате представлено?
Два старших бита из второго и третьего байтов не используются, что ли (т.е. на них можно не обращать внимание)?
Если так, то думаю, что можно всё же воспользоваться и предложенным мной способом, только немного модифицировать значения первого и третьего элементов массива, а именно применить к ним " and 00111111", т.е. and $3F. Тогда эти 2 старших бита просто обнулятся.
В общем, хотелось бы побольше подробностей.
Digitman (2004-12-15 08:11:00) [13]т.е., как я понял, тебе просто нужно некое заданное тобой 28-разр. число представить в указанном формате ?
Kolan (2004-12-14 21:51:00) [14]
> Digitman © (14.12.04 16:20) [16]
Благодарю мой алгоритм работает.
Это не галимотья а прикол микросхемы. Я точно не разбирался, но число там 28 разрядное и
записывается так
xxbbbbbb bbbbbbbb xxbbbbbb bbbbbbbb где xx не используются, а b это "0" или "1"
Поэтому верно.
0 0 63 255 + 0 0 0 1 будет не 0 0 64 0 , а 0 1 0 0
Пользователь моей программы видит только десятичное число. А я его сам преобразую.
Еще раз благодарю за помощь.
Интересно бы как нибкдь поизяшнее такой алгоритм сделать.
Digitman (2004-12-14 16:20:00) [15]
> Поэтому
> 0 0 63 255 + 0 0 0 1 будет не 0 0 64 0 , а 0 1 0 0
галиматья какая-то ...
если диапазон представления числа в дв.виде ограничен 28-ю разрядами , то
0 0 63 255 + 0 0 0 1 будет именно 0 0 64 0 , а не 0 1 0 0
Kolan (2004-12-14 16:05:00) [16]
> begin...end © (13.12.04 13:04) [13]
Хороший способ, но ты забыл что число то 28 разрядное. Поэтому
0 0 63 255 + 0 0 0 1 будет не 0 0 64 0 , а 0 1 0 0
Kolan (2004-12-13 13:21:00) [17]
> begin...end © (13.12.04 13:04) [13]
Благодарю за ответ.
> что массив из четырёх байт (Parts) располагается в памяти
> по тому же адресу
В жизни бы не догадался.
:)
begin...end (2004-12-13 13:04:00) [18]> [12] Kolan © (13.12.04 12:06)
> Не очень понял. Как сделать.
Идея решения в [6] состоит в том, что массив из четырёх байт (Parts) располагается в памяти по тому же адресу, что и четырёхбайтная переменная Value. Такое размещение достигается применением директивы absolute. Т.е. первый байт переменной Value "совмещён" с первым байтом массива Parts. А поскольку это array of Byte, т.е. каждый элемент массива занимает 1 байт, то, обратившись к первому элементу массива, мы получаем первый байт переменной Value. Другими словами, одну и ту же область памяти можно рассматривать и как место размещения числа Value, и как массив из четырёх байт Parts.
Присвоив переменной Value какое-либо значение, мы размещаем это значение в четырёх байтах памяти. А потом, обращаясь к первому, второму и т.д. элементам массива, получаем первый, второй и т.д. байты числа Value.
Если Вам эти байты нужны в виде отдельных переменных, пожалуйста - присвойте нужным переменным значения соответствующих элементов массива, и всё.
Например, есть у Вас число 4000000000 (в десятичной системе).
В двоичной оно запишется так: 11101110 01101011 00101000 00000000.
Таким образом, в первом байте (справа) находится число 0, во втором - 40, в третьем - 107, и в четвёртом - 238.
Теперь выполните такой код:
var
I: Byte;
Parts: array [0..3] of Byte;
Value: Cardinal absolute Parts;
begin
// Присваиваем значение переменной Value
Value := 4000000000;
// Работаем с каждым её байтом в отдельности как с элементом массива Parts
for I := Low(Parts) to High(Parts) do
ShowMessage(IntToStr(Parts[I]))
end
и сравните показанные числа с числами, приведёнными выше (0; 40; 107; 238).
Думаю, теперь понятно.
Kolan (2004-12-13 12:06:00) [19]
> Это как понять? В двоичной системе либо "0" либо "1".А то
> ШО?
h и l имеется в виду 0 или 1.
> uny © (11.12.04 17:22) [5]
> [4] наверно из 32 4 не используются:)))
Да не используются.
> > Kolan © (11.12.04 16:14)
>
> Что-то Вы молчите, так что буду разговаривать сам с собой.
Извените нет на работе "гонит" не мог ответить.
А я вот так извратился :)
procedure TKFreGrafCommands.EvalFourBytsFromValue(Value: LongInt);
var
HHiByte, LHiByte, HlowByte, LLowByte: Integer;
BothLowBytes, BothHiBytes: Integer;
begin
HHiByte := 0;
LHiByte := 0;
HlowByte:= 0;
LLowByte := 0;
BothLowBytes:= 0;
BothHiBytes:= 0;
if Value > 16383 then
begin
BothLowBytes := Value - 16384 * (Value div 16384);
BothHiBytes := Value div 16384;
end
else
begin
BothLowBytes := Value;
BothHiBytes := 0;
end;
if BothLowBytes > 255 then
begin
LLowByte := BothLowBytes - 256 * (BothLowBytes div 256);
HlowByte := BothLowBytes div 256;
end
else
begin
LLowByte := BothLowBytes;
HlowByte := 0;
end;
if BothHiBytes > 255 then
begin
LHiByte := BothHiBytes - 256 * (BothHiBytes div 256);
HHiByte := BothHiBytes div 256;
end
else
begin
LHiByte := BothHiBytes;
HHiByte := 0;
end;
end;
> var
> Parts: array [0..3] of Byte;
> Value: Cardinal absolute Parts;
>
> begin
> // Присваиваем значение переменной Value
> // Работаем с каждым её байтом в отдельности как с элементом
> массива Parts
> end.
Не очень понял. Как сделать.
cyborg (2004-12-12 12:43:00) [20]
> непонятно, зачем использовать для хранения значения 1 бита
> целых 4 байта.
Чтобы в 32 битный регистр значение помещалось, так, как процессоры 32 битные сейчас в основном. Что, зажал 3 байта? :)