OberonCore https://forum.oberoncore.ru/ |
|
Работа с байтами https://forum.oberoncore.ru/viewtopic.php?f=2&t=267 |
Страница 1 из 2 |
Автор: | Иван Горячев [ Суббота, 08 Июль, 2006 06:11 ] |
Заголовок сообщения: | Работа с байтами |
Господа, помогите убогому! Требуется разбить целое на байты а потом его обратно склеить. Как разбить, понятно: Код: 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; не работает, ибо тип BYTE знаковый, и плюсы местами честно превращаются в минусы BEGIN RETURN b0 + b1 * 100H + b2 * 10000H + b3 * 1000000H END COMPOSE; ![]() И попутный вопрос: кто-нибудь в компиляторе копался на предмет встроенных процедур? В смысле за процедурами BITS, ORD etc стоит реальный код, или они только для соблюдения строгости? |
Автор: | Сергей Губанов [ Суббота, 08 Июль, 2006 16:48 ] |
Заголовок сообщения: | Re: Работа с байтами |
Модуль 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 ] |
Заголовок сообщения: | |
Можно и так. Код: 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 ] |
Заголовок сообщения: | |
Нет, так нельзя. Сложение целых использовать для побитных операций нельзя, т.к. целые знаковые - на старшем байте все равно сложение превратится в вычитание. Можно так: Код: 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 ] |
Заголовок сообщения: | |
Согласен. Код: 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 ] |
Заголовок сообщения: | |
Очевидно, можно и так: Код: 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; этот вариант точно от машинного представления не зависит, хотя уродец тот ещё. |
Автор: | Trurl [ Понедельник, 10 Июль, 2006 10:44 ] |
Заголовок сообщения: | |
А мне все же больше нравиться Код: 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 ] |
Заголовок сообщения: | |
На самом деле я применил страшное слово "[code]". Зато хоть с ассемблером познакомился ![]() |
Автор: | Trurl [ Понедельник, 10 Июль, 2006 10:55 ] |
Заголовок сообщения: | |
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 ] |
Заголовок сообщения: | |
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; ![]() ![]() ![]() Говорят, что все имплементаторы всяких сетевых протоколов на этом обязательно всегда накалываются. Вот и я тоже накололся по первому разу. |
Автор: | Сергей Оборотов [ Понедельник, 10 Июль, 2006 17:20 ] |
Заголовок сообщения: | |
Вариант 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 ] |
Заголовок сообщения: | |
Trurl писал(а): Кажется, так нельзя. Ведь ORD(BITS(b0)) = b0 и приходим к тому, с чего начинали.
Можно. BITS(b0) преобразует байт в SET побитово, знак не учитывается. При обратном преобразовании получаем INTEGER, у которого младший байт = b0 |
Автор: | Trurl [ Вторник, 11 Июль, 2006 08:03 ] |
Заголовок сообщения: | |
Ivor писал(а): BITS(b0) преобразует байт в SET побитово, знак не учитывается. При обратном преобразовании получаем INTEGER, у которого младший байт = b0
BITS преобразует INTEGER в SET. А перед этим надо байт привести к целому. |
Автор: | Иван Горячев [ Вторник, 11 Июль, 2006 09:02 ] |
Заголовок сообщения: | |
Да, действительно ![]() В этом случае нужно делать так: Код: PROCEDURE [ code ] CARD* (x : BYTE) : INTEGER;
Это законченная процедура, превращающая байт в целое без учёта знака - хотя по незнанию можно долго искать, где у неё тело ![]() |
Автор: | Иван Горячев [ Вторник, 11 Июль, 2006 09:10 ] |
Заголовок сообщения: | |
А зачем так много? Код: 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 *) |
Автор: | Trurl [ Вторник, 11 Июль, 2006 09:51 ] |
Заголовок сообщения: | |
Ivor писал(а): Код: PROCEDURE [ code ] CARD* (x : BYTE) : INTEGER; Это законченная процедура, превращающая байт в целое без учёта знака - хотя по незнанию можно долго искать, где у неё тело ![]() Все же тело лучше добавить (MOVZXB EAX,AL). Иначе можно долго разбираться с мусором в старших битах. |
Автор: | Сергей Оборотов [ Среда, 12 Июль, 2006 13:47 ] |
Заголовок сообщения: | |
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 ] |
Заголовок сообщения: | |
GUEST писал(а): P.S. Мы верим в мужество отчаянных парней?
Просто надоели бесконечные SYSTEM.VAL, да и я не уверен, что все эти преобразования не добавляют дополнительного кода. А вообще - почему бы и нет? Хотя лучше сделали бы именно встроенный ассемблер. Процедуры в кодах это уж слишком круто. |
Автор: | Сергей Оборотов [ Четверг, 13 Июль, 2006 12:10 ] |
Заголовок сообщения: | |
Цитата: я не уверен, что все эти преобразования не добавляют дополнительного кода. А вообще - почему бы и нет?
Просто иногда дополнительный код ох как необходим. Нашли его? Или не искали? |
Автор: | Иван Горячев [ Пятница, 14 Июль, 2006 01:09 ] |
Заголовок сообщения: | |
Не искал. Свою задачу я решил, а на отстранённые исследования времени жалко. |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |