OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Пятница, 19 Апрель, 2024 14:53

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 23 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Работа с байтами
СообщениеДобавлено: Суббота, 08 Июль, 2006 06:11 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
Господа, помогите убогому! Требуется разбить целое на байты а потом его обратно склеить. Как разбить, понятно:
Код:
PROCEDURE SPLIT (x : INTEGER; VAR b0, b1, b2, b3 : BYTE);
BEGIN
   b0 := SHORT(SHORT(x MOD 100H));
   b1 := SHORT(SHORT(x DIV 100H));
   b2 := SHORT(SHORT(x DIV 10000H));
   b3 := SHORT(SHORT(x DIV 1000000H));
END SPLIT;

А вот со склейкой так просто не получается. Вариант:
Код:
PROCEDURE COMPOSE (b0, b1, b2, b3 : BYTE) : INTEGER;
BEGIN
   RETURN b0 + b1 * 100H + b2 * 10000H + b3 * 1000000H
END COMPOSE;
не работает, ибо тип BYTE знаковый, и плюсы местами честно превращаются в минусы :( Кроме модуля SYSTEM или страшного тега [ code ] ничего в голову не приходит, но может есть ещё варианты?

И попутный вопрос: кто-нибудь в компиляторе копался на предмет встроенных процедур? В смысле за процедурами BITS, ORD etc стоит реальный код, или они только для соблюдения строгости?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Работа с байтами
СообщениеДобавлено: Суббота, 08 Июль, 2006 16:48 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Модуль Stores:
Код:
  PROCEDURE (VAR rd: Reader) ReadInt* (OUT x: INTEGER), NEW;
    VAR le, be: ARRAY 4 OF BYTE;  (* little endian, big endian *)
  BEGIN
    rd.rider.ReadBytes(le, 0, 4);
    IF Kernel.littleEndian THEN
      x := SYSTEM.VAL(INTEGER, le)
    ELSE
      be[0] := le[3]; be[1] := le[2]; be[2] := le[1]; be[3] := le[0];
      x := SYSTEM.VAL(INTEGER, be)
    END
  END ReadInt;


Код:
  PROCEDURE (VAR wr: Writer) WriteInt* (x: INTEGER), NEW;
    TYPE a = ARRAY 4 OF BYTE;
    VAR le, be: a;  (* little endian, big endian *)
  BEGIN
    IF Kernel.littleEndian THEN
      le := SYSTEM.VAL(a, x)
    ELSE
      be := SYSTEM.VAL(a, x);
      le[0] := be[3]; le[1] := be[2]; le[2] := be[1]; le[3] := be[0]
    END;
    wr.rider.WriteBytes(le, 0, 4)
  END WriteInt;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Воскресенье, 09 Июль, 2006 00:36 

Зарегистрирован: Вторник, 29 Ноябрь, 2005 21:41
Сообщения: 1030
Можно и так.
Код:
PROCEDURE COMPOSE (b0, b1, b2, b3 : BYTE) : INTEGER;
VAR i:INTEGER;
BEGIN
   i := b3 MOD 100H;
   i := ASH(i,8)+b2 MOD 100H;
   i := ASH(i,8)+b1 MOD 100H;
   i := ASH(i,8)+b0 MOD 100H;
   RETURN i
END COMPOSE;

Процедуры ORD и BITS влияют на обработку выражений в компиляторе.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Воскресенье, 09 Июль, 2006 15:12 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Нет, так нельзя. Сложение целых использовать для побитных операций нельзя, т.к. целые знаковые - на старшем байте все равно сложение превратится в вычитание.

Можно так:
Код:
   i := BITS(b3)*{0..7} + BITS(ASH(b2, 8))*{8..15} +
         BITS(ASH(b1, 16))*{16..23} + BITS(ASH(b0, 24))*{24..31}


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 10 Июль, 2006 07:14 

Зарегистрирован: Вторник, 29 Ноябрь, 2005 21:41
Сообщения: 1030
Согласен.
Код:
PROCEDURE COMPOSE (b0, b1, b2, b3 : BYTE) : INTEGER;
VAR i:INTEGER;
BEGIN
   i := ORD(BITS(b3)*{0..7});
   i := ORD(BITS(ASH(i,8))+BITS(b2)*{0..7});
   i := ORD(BITS(ASH(i,8))+BITS(b1)*{0..7});
   i := ORD(BITS(ASH(i,8))+BITS(b0)*{0..7});
   RETURN i
END COMPOSE;
Хотя первые три присваивания можно было и не менять.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 10 Июль, 2006 07:46 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
Очевидно, можно и так:
Код:
PROCEDURE COMPOSE (b0, b1, b2, b3 : BYTE) : INTEGER;
BEGIN
   RETURN SHORT(ORD(BITS(b0)) + ORD(BITS(b1)) * 100L + ORD(BITS(b2)) * 10000L + ORD(BITS(b3)) * 1000000L)
END COMPOSE;

этот вариант точно от машинного представления не зависит, хотя уродец тот ещё.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 10 Июль, 2006 10:44 

Зарегистрирован: Понедельник, 28 Ноябрь, 2005 10:28
Сообщения: 1428
А мне все же больше нравиться
Код:
PROCEDURE COMPOSE (b0, b1, b2, b3 : BYTE) : INTEGER;
BEGIN
   RETURN b0 MOD 100H + b1 MOD 100H * 100H + b2 MOD 100H * 10000H + b3 MOD 100H * 1000000H
END COMPOSE;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 10 Июль, 2006 10:48 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
На самом деле я применил страшное слово "[code]". Зато хоть с ассемблером познакомился :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 10 Июль, 2006 10:55 

Зарегистрирован: Понедельник, 28 Ноябрь, 2005 10:28
Сообщения: 1428
Ivor писал(а):
Очевидно, можно и так:
Код:
PROCEDURE COMPOSE (b0, b1, b2, b3 : BYTE) : INTEGER;
BEGIN
   RETURN SHORT(ORD(BITS(b0)) + ORD(BITS(b1)) * 100L + ORD(BITS(b2)) * 10000L + ORD(BITS(b3)) * 1000000L)
END COMPOSE;

этот вариант точно от машинного представления не зависит, хотя уродец тот ещё.


Кажется, так нельзя. Ведь ORD(BITS(b0)) = b0 и приходим к тому, с чего начинали.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 10 Июль, 2006 12:15 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Trurl писал(а):
PROCEDURE COMPOSE (b0, b1, b2, b3 : BYTE) : INTEGER;
Кажется, так нельзя. Ведь ORD(BITS(b0)) = b0 и приходим к тому, с чего начинали.

Объявите так: PROCEDURE COMPOSE (b0, b1, b2, b3 : INTEGER) : INTEGER;

-----

На самом деле байты внутри int - это ерунда.

Вот биты внутри байта - это гораздо круче! На счёт битов в байте есть страшная тайна. Оказывается они (в x86) идут наоборот! То есть если передавать биты по сети, то сначала надо отправить вовсе не 0-вой бит, а 7-мой, потом 6-той и т.д.

Вот, например, стандарт передачи битов по сети в заголовке RTP-пакета: http://rfc.net/rfc1889.html#s5.1 Там написано, что в 0 и 1 битах заголовка передается версия. По наивности (раз она в 0 и 1 битах) можно было бы попытаться узнать версию так:
this.version = (this.datagram[0] & 3);
и это, оказывается, не правильно; а правильно так:
this.version = (this.datagram[0] >> 6) & 3;
:evil: :evil: :evil:
Говорят, что все имплементаторы всяких сетевых протоколов на этом обязательно всегда накалываются. Вот и я тоже накололся по первому разу.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 10 Июль, 2006 17:20 

Зарегистрирован: Вторник, 29 Ноябрь, 2005 21:41
Сообщения: 1030
Вариант A:
Код:
   movsx   eax, [ebp+arg_C]
   and   eax, 0FFh
   mov   [ebp+var_4], eax
   shl   eax, 8
   movsx   edx, [ebp+arg_8]
   and   edx, 0FFh
   add   eax, edx
   mov   [ebp+var_4], eax
   shl   eax, 8
   movsx   edx, [ebp+arg_4]
   and   edx, 0FFh
   add   eax, edx
   mov   [ebp+var_4], eax
   shl   eax, 8
   movsx   edx, [ebp+arg_0]
   and   edx, 0FFh
   add   eax, edx

Вариант B:
Код:
   movsx   eax, [ebp+arg_C]
   and   eax, 0FFh
   mov   [ebp+var_4], eax
   shl   eax, 8
   movsx   edx, [ebp+arg_8]
   and   edx, 0FFh
   or   eax, edx
   mov   [ebp+var_4], eax
   shl   eax, 8
   movsx   edx, [ebp+arg_4]
   and   edx, 0FFh
   or   eax, edx
   mov   [ebp+var_4], eax
   shl   eax, 8
   movsx   edx, [ebp+arg_0]
   and   edx, 0FFh
   or   eax, edx
.
Кто скажет что это не одно и тоже?
P.S. Тест на конформизм не прохожу, однако.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вторник, 11 Июль, 2006 07:16 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
Trurl писал(а):
Кажется, так нельзя. Ведь ORD(BITS(b0)) = b0 и приходим к тому, с чего начинали.

Можно. BITS(b0) преобразует байт в SET побитово, знак не учитывается. При обратном преобразовании получаем INTEGER, у которого младший байт = b0


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вторник, 11 Июль, 2006 08:03 

Зарегистрирован: Понедельник, 28 Ноябрь, 2005 10:28
Сообщения: 1428
Ivor писал(а):
BITS(b0) преобразует байт в SET побитово, знак не учитывается. При обратном преобразовании получаем INTEGER, у которого младший байт = b0

BITS преобразует INTEGER в SET. А перед этим надо байт привести к целому.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вторник, 11 Июль, 2006 09:02 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
Да, действительно :?
В этом случае нужно делать так:
Код:
PROCEDURE [ code ] CARD* (x : BYTE) : INTEGER;

Это законченная процедура, превращающая байт в целое без учёта знака - хотя по незнанию можно долго искать, где у неё тело :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вторник, 11 Июль, 2006 09:10 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
А зачем так много?
Код:
PROCEDURE [ code ] COMPOSE (b0, b1, b2, b3 : BYTE) : INTEGER
59H,             (* POP cx      *)
88H, 0CDH,       (* MOV ch, cl  *)
88H, 0C1H,       (* MOV cl, al  *)
5AH,             (* POP dx      *)
88H, 0D0H,       (* MOV al, dl  *)
5AH,             (* POP dx      *)
88H, 0D4H,       (* MOV ah, dl  *)
0C1H, 0E0H, 10H, (* SHL eax, 16 *)
09H, 0C8H;       (* OR eax, ecx *)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вторник, 11 Июль, 2006 09:51 

Зарегистрирован: Понедельник, 28 Ноябрь, 2005 10:28
Сообщения: 1428
Ivor писал(а):
Код:
PROCEDURE [ code ] CARD* (x : BYTE) : INTEGER;

Это законченная процедура, превращающая байт в целое без учёта знака - хотя по незнанию можно долго искать, где у неё тело :)

Все же тело лучше добавить (MOVZXB EAX,AL). Иначе можно долго разбираться с мусором в старших битах.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Среда, 12 Июль, 2006 13:47 

Зарегистрирован: Вторник, 29 Ноябрь, 2005 21:41
Сообщения: 1030
Ivor писал(а):
А зачем так много?
Код:
PROCEDURE [ code ] COMPOSE (b0, b1, b2, b3 : BYTE) : INTEGER
59H,             (* POP cx      *)
88H, 0CDH,       (* MOV ch, cl  *)
88H, 0C1H,       (* MOV cl, al  *)
5AH,             (* POP dx      *)
88H, 0D0H,       (* MOV al, dl  *)
5AH,             (* POP dx      *)
88H, 0D4H,       (* MOV ah, dl  *)
0C1H, 0E0H, 10H, (* SHL eax, 16 *)
09H, 0C8H;       (* OR eax, ecx *)
Не хотелось связываться со встроенным ассемблером, поскольку его отладка затруднительна. Над указанной процедурой ещё немного поработать необходимо.
P.S. Мы верим в мужество отчаянных парней?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 13 Июль, 2006 02:17 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
GUEST писал(а):
P.S. Мы верим в мужество отчаянных парней?


Просто надоели бесконечные SYSTEM.VAL, да и я не уверен, что все эти преобразования не добавляют дополнительного кода. А вообще - почему бы и нет?
Хотя лучше сделали бы именно встроенный ассемблер. Процедуры в кодах это уж слишком круто.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 13 Июль, 2006 12:10 

Зарегистрирован: Вторник, 29 Ноябрь, 2005 21:41
Сообщения: 1030
Цитата:
я не уверен, что все эти преобразования не добавляют дополнительного кода. А вообще - почему бы и нет?

Просто иногда дополнительный код ох как необходим. Нашли его? Или не искали?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 14 Июль, 2006 01:09 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
Не искал. Свою задачу я решил, а на отстранённые исследования времени жалко.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 23 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB