OberonCore
https://forum.oberoncore.ru/

Оберон-07: вопросы реализации
https://forum.oberoncore.ru/viewtopic.php?f=115&t=6352
Страница 3 из 5

Автор:  Илья Ермаков [ Воскресенье, 24 Февраль, 2019 21:49 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Ну такую штуку можно как-то ещё решить окружением.
Например, генерация модуля с такими данными из ресурсного файла.

Автор:  Oleg N. Cher [ Воскресенье, 24 Февраль, 2019 23:31 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Илья Ермаков писал(а):
Например, генерация модуля с такими данными из ресурсного файла.
И чего будут представлять собой эти данные в коде? Поэлементное присваивание? Тоже UUDecode("Data")? В таком решении сразу три вида потерь памяти: копия в коде, избыток за счёт символьного кодирования, копия в данных. А должна быть только копия в данных.

Кстати, я бы ещё поспорил за присутствие LOOP/EXIT и RETURN из середины процедур. Для мк это может быть ценно хотя бы из соображений производительности.

Господа, я загрустил, поняв, что решить RorLong средствами КП красиво не получится. И родил такое решение:

Код:
   PROCEDURE [code] rorlong (x: LONGINT; n: INTEGER): LONGINT
      059H,                         (* POP    ECX          *)
      083H, 0E1H, 03FH,             (* AND    ECX, 0x3F    *)
      089H, 0C6H,                   (* MOV    ESI, EAX     *)
      089H, 0D7H,                   (* MOV    EDI, EDX     *)
      00FH, 0ADH, 0D6H,             (* SHRD   ESI, EDX, CL *)
      0D3H, 0EFH,                   (* SHR    EDI, CL      *)
      053H,                         (* PUSH   EBX          *)
      031H, 0DBH,                   (* XOR    EBX, EBX     *)
      0F6H, 0C1H, 020H,             (* TEST   CL,  0x20    *)
      00FH, 045H, 0F7H,             (* CMOVNE ESI, EDI     *)
      00FH, 045H, 0FBH,             (* CMOVNE EDI, EBX     *)
      0BBH, 040H, 000H, 000H, 000H, (* MOV    EBX, 0x40    *)
      029H, 0CBH,                   (* SUB    EBX, ECX     *)
      088H, 0D9H,                   (* MOV    CL,  BL      *)
      00FH, 0A5H, 0C2H,             (* SHLD   EDX, EAX, CL *)
      0D3H, 0E0H,                   (* SHL    EAX, CL      *)
      031H, 0DBH,                   (* XOR    EBX, EBX     *)
      0F6H, 0C1H, 020H,             (* TEST   CL,  0x20    *)
      00FH, 045H, 0D0H,             (* CMOVNE EDX, EAX     *)
      00FH, 045H, 0C3H,             (* CMOVNE EAX, EBX     *)
      05BH,                         (* POP    EBX          *)
      00BH, 0C6H,                   (* OR     EAX, ESI     *)
      00BH, 0D7H;                   (* OR     EDX, EDI     *)

   PROCEDURE RorLong* (x: LONGINT; n: INTEGER): LONGINT;
   BEGIN
      ASSERT((0 <= n) & (n <= 63));
      RETURN rorlong(x, n)
   END RorLong;

На этом вопрос снят.

У меня ещё вопрос про реализацию PACK и UNPK. Описание крайне скупое в доках. Как они вообще могут выглядеть в виде алгоритма?

Автор:  albobin [ Понедельник, 25 Февраль, 2019 09:35 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Oleg N. Cher писал(а):
У меня ещё вопрос про реализацию PACK и UNPK. Описание крайне скупое в доках. Как они вообще могут выглядеть в виде алгоритма?

Не смотрели на IEEE 754, в частности на:
https://ru.wikipedia.org/wiki/%D0%A7%D0 ... 1%82%D0%B8
PS.
Сам-то я, давече, "слегка", на 1 бит, лажанулся про где лежит порядок числа.

Автор:  Oleg N. Cher [ Вторник, 26 Февраль, 2019 11:33 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Оптимизированный вариант RorLong:
Код:
   PROCEDURE [code] rorlong(x: LONGINT; n: INTEGER): LONGINT
      059H,             (*     POP   ECX          *)
      089H, 0C6H,       (*     MOV   ESI, EAX     *)
      089H, 0D7H,       (*     MOV   EDI, EDX     *)
      00FH, 0ADH, 0D6H, (*     SHRD  ESI, EDX, CL *)
      0D3H, 0EFH,       (*     SHR   EDI, CL      *)
      0F6H, 0C1H, 020H, (*     TEST  CL,  20H     *)
      074H, 002H,       (*     JZ    SHORT L1     *)
      087H, 0F7H,       (*     XCHG  ESI, EDI     *)
      0F6H, 0D9H,       (* L1: NEG   CL           *)
      00FH, 0A5H, 0C2H, (*     SHLD  EDX, EAX, CL *)
      0D3H, 0E0H,       (*     SHL   EAX, CL      *)
      0F6H, 0C1H, 020H, (*     TEST  CL,  20H     *)
      074H, 001H,       (*     JZ    SHORT L2     *)
      092H,             (*     XCHG  EAX, EDX     *)
      00BH, 0C6H,       (* L2: OR    EAX, ESI     *)
      00BH, 0D7H;       (*     OR    EDX, EDI     *)

Коллеги, что скажете насчёт важности контролировать переполнение при логических сдвигах влево? Переполнение в арифметических сдвигах ловить смысл есть. Ofront+ ловит его при константных аргументах, а BlackBox даже в рантайме. В циклических сдвигах переполнений быть не может.

Остаются логические сдвиги. Это не очень понятный момент, но в Обероне-07 такой сдвиг присутствует в языке, то есть, сначала Вирт утверждает, что целый тип — абстрактный, и прикладному программисту не обязательно знать как устроено хранение чисел. Но как только логический сдвиг добавлен в язык — программисту уже требуется знать, что бит знака хранится в старшем разряде, что отрицательные числа хранятся в дополнительном коде и т.д. Получается, выдвинули тезис "числа это не биты", потом радостно его сломали и начали битики двигать. А вот в КП эти сдвиги там, где им и положено быть — в SYSTEM.

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

Автор:  Trurl [ Вторник, 26 Февраль, 2019 11:43 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

А зачем делать сдвиги для LONGINT? Этого же нет в языке, да и смысла в них особо нет.

Автор:  Oleg N. Cher [ Вторник, 26 Февраль, 2019 11:45 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Мне даже в Обероне-07 нужна поддержка типа SYSTEM.ADRINT, а он может быть 64-битным.

Любой реализатор Оберона-07 сталкивается с тем, что ему предлагают накрепко привязать разрядность адресного типа к INTEGER. Я не считаю, что это такая уж хорошая идея. Поэтому INTEGER отдельно, SYSTEM.ADRINT отдельно.

Автор:  Comdiv [ Вторник, 26 Февраль, 2019 13:20 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Oleg N. Cher писал(а):
Мне даже в Обероне-07 нужна поддержка типа SYSTEM.ADRINT, а он может быть 64-битным.
И биты вращать адресу тоже нужно? Вы, ведь, знаете, что в общем случае адрес - это не обязательно индекс в массиве общей памяти?

Автор:  Trurl [ Вторник, 26 Февраль, 2019 14:15 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Если адрес 64-битный, то и процессор, скорее всего, тоже. Но тогда реализация сдвигов довольно проста.

Автор:  Oleg N. Cher [ Вторник, 26 Февраль, 2019 14:47 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Хорошо, я попробую иначе сформулировать. Мне нужна единая разрядность INTEGER на 32-х и 64-битных архитектурах, чтобы писать код без оглядки на разрядность системы. С той же целью нужна единостильная работа с адресами через тип SYSTEM.ADRINT. Посему да, поддержку сдвигов для 64-х бит нужно заложить, она тут сама просится. Также нужна возможность даже из Оберона-07 работать с системным типом SYSTEM.INT64.

Ещё я не исключаю возможность опционально задавать для Оберона-07 разрядность INTEGER.

А ещё я делаю реализацию Ofront+ для BlackBox, а он чисто 32-битный, как вы знаете. На самом Ofront+ с циклическими сдвигами проблем вообще нет — ROR сделан через SYSTEM.ROT.

Автор:  Kemet [ Среда, 27 Февраль, 2019 06:37 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

В А2 есть реализации, и в них есть ссылка на хороший папир
Код:
PROCEDURE RorH*(l: HUGEINT; r: LONGINT): HUGEINT;
CODE{SYSTEM.i386}
   PUSH   ECX
   ; taken from "Software Optimization Guide for AMD64 Processors"
   MOV ECX,[EBP+r+0]
   MOV EAX,[EBP+l+0]
   MOV EDX,[EBP+l+4]
   ; EBX (initially=EAX) -> EDX -> EAX
   ; Shift EDX:EAX right, shift count in ECX (count
   ; applied modulo 64).
   MOV EBX,EAX
   SHRD EAX,EDX,CL      ; First apply shift count.
   SHRD EDX,EBX,CL       ; mod 32 to EDX:EAX
   TEST ECX,32          ; Need to shift by another 32?
   JZ rshiftdone          ; No, done.
   MOV EBX,EAX
   SHRD EAX,EDX,CL
   SHRD EDX,EBX,CL
   rshiftdone:
   POP   ECX
END RorH;

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

Автор:  Oleg N. Cher [ Среда, 27 Февраль, 2019 12:30 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Переписал для BlackBox:
Код:
   PROCEDURE [code] rorlong(x: LONGINT; n: INTEGER): LONGINT
      (* taken from "Software Optimization Guide for AMD64 Processors"           *)
      (* ESI (initially=EAX) -> EDX -> EAX                                       *)
      (* Shift EDX:EAX right, shift count in ECX (count applied modulo 64).      *)
   059H,             (*      POP   ECX           *)
   08BH, 0F0H,       (*      MOV   ESI, EAX      *)
   00FH, 0ADH, 0D0H, (*      SHRD  EAX, EDX, CL  ; First apply shift count.     *)
   00FH, 0ADH, 0F2H, (*      SHRD  EDX, ESI, CL  ; mod 32 to EDX:EAX            *)
   0F6H, 0C1H, 020H, (*      TEST  CL,  32       ; Need to shift by another 32? *)
   074H, 008H,       (*      JZ    SHORT done    ; No, done.                    *)
   08BH, 0F0H,       (*      MOV   ESI, EAX      *)
   00FH, 0ADH, 0D0H, (*      SHRD  EAX, EDX, CL  *)
   00FH, 0ADH, 0F2H  (*      SHRD  EDX, ESI, CL  *)
   ;                 (* done:                    *)

Код точно рабочий? Я проверил. Он даёт для ROR(1, 1) результат F333333333333334, для ROR(1, 2) то же самое.

Kemet писал(а):
Контролировать переполнение смысла нет, так как такого контроля нет и в арифметических операциях
В Ofront'е+ при вычислении константных значений такой контроль есть. А в BlackBox он встречается и в рантайме (в ASH, в частности).

Автор:  Kemet [ Среда, 27 Февраль, 2019 14:15 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

А как в ББ параметры передаются?

Автор:  Kemet [ Среда, 27 Февраль, 2019 14:31 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Oleg N. Cher писал(а):
Код точно рабочий? Я проверил. Он даёт для ROR(1, 1) результат F333333333333334, для ROR(1, 2) то же самое.

Рабочий
Код:
PROCEDURE Do*;
VAR x: HUGEINT;
BEGIN
    x := 1;
    TRACE( SYSTEM.VAL( SET64, x  ));
    x := ROR( x, 1);
    TRACE( SYSTEM.VAL( SET64, x  ));
    x := ROR( x, 1);
    TRACE( SYSTEM.VAL( SET64, x  ));
    x := ROR( x, 1);
    TRACE( SYSTEM.VAL( SET64, x  ));

    x :=1;
    x := ROR( x, 3);
    TRACE( SYSTEM.VAL( SET64, x  ));
END Do;

Вывод
{P cpuid= 0, pid= 9360 Test.Do@84:SYSTEM.VAL(SET64, x)= {0}; }
{P cpuid= 0, pid= 9360 Test.Do@136:SYSTEM.VAL(SET64, x)= {63}; }
{P cpuid= 0, pid= 9360 Test.Do@188:SYSTEM.VAL(SET64, x)= {62}; }
{P cpuid= 0, pid= 9360 Test.Do@240:SYSTEM.VAL(SET64, x)= {61}; }
{P cpuid= 0, pid= 9360 Test.Do@302:SYSTEM.VAL(SET64, x)= {61}; }

Автор:  Oleg N. Cher [ Среда, 27 Февраль, 2019 15:48 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Kemet писал(а):
А как в ББ параметры передаются?
Цитата:
Процедуры в машинных кодах позволяют использовать специальные последова­тель­ности машинных команд, которые не генерируются компилятором. Для их объявления исполь­зуется следующий специальный синтаксис:

ProcDecl = PROCEDURE "[" SysFlag "]" IdentDef [FormalPars]
[ConstExpr {"," ConstExpr}] ";".

Список констант, объявленный с процедурой, интерпретируется как строка байт и встав­ляется непосредственно в код («in-line»), из которого вызвана процедура. Если присут­ствует список параметров, фактические параметры загружаются в стек справа налево. Однако первый параметр записывается в регистр. Если тип первого параметра REAL или SHORTREAL, то он записывается в верхний регистр для чисел с плавающей точкой. Иначе параметр (или в случае VAR/IN/OUT-параметра — его адрес) записывается в EAX. Для процедур-функций ожидается, что и результат сохраняется в верхнем регистре с плавающей точкой или в EAX, в зависимости от его типа. Будьте осторожны, когда используете регистры в кодовых процедурах. В общем, можно использовать регистры ECX, EDX, ESI и EDI. Параметры должны удаляться со стека процедурой.

Примеры

PROCEDURE [code] Sqrt (x: REAL): REAL (* Math.Sqrt *)
0D9H, 0FAH; (* FSQRT *)

PROCEDURE [code] Erase (adr, words: INTEGER) (* erase memory area *)
089H, 0C7H, (* MOV EDI, EAX *)
031H, 0C0H, (* XOR EAX, EAX *)
059H, (* POP ECX *)
0F2H, 0ABH; (* REP STOS *)

Для нашего случая

PROCEDURE {code} rorlong (x: LONGINT; n: INTEGER): LONGINT;

аргумент x передаётся в EDX:EAX, аргумент n мы снимаем со стека командой POP ECX, а результат ожидается в EDX:EAX.

Также в варианте для BlackBox я использовал регистр ESI вместо EBX, потому что EBX нужно было бы сохранять, а ESI не надо.

Автор:  Oleg N. Cher [ Среда, 27 Февраль, 2019 17:43 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Kemet, этот код точно нерабочий для n >= 32, можете подавать баг-репорт.

Смотрите. Если первый сдвиг производится на (n mod 32) битов, а там нужен был сдвиг на {0..63}, то второй сдвиг надо делать ровно на 32 бита, т.е. просто поменять регистры местами. А он опять делается на (n mod 32) битов.

Вот рабочий вариант:
Код:
   PROCEDURE [code] rorlong(x: LONGINT; n: INTEGER): LONGINT
      059H,             (*      POP   ECX           *)
      08BH, 0F0H,       (*      MOV   ESI, EAX      *)
      00FH, 0ADH, 0D0H, (*      SHRD  EAX, EDX, CL  *)
      00FH, 0ADH, 0F2H, (*      SHRD  EDX, ESI, CL  *)
      0F6H, 0C1H, 020H, (*      TEST  CL,  32       *)
      074H, 001H,       (*      JZ    SHORT done    *)
      092H              (*      XCHG  EAX, EDX      *)
   ;                    (* done:                    *)

Автор:  Kemet [ Четверг, 28 Февраль, 2019 06:15 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

XCHG там не подходит, потому что не устанавливает флаги, которые устанавливаются в 64-битном режиме.

Автор:  Oleg N. Cher [ Четверг, 28 Февраль, 2019 07:51 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Очень даже подходит. Зачем нужно устанавливать эти флаги? Кто-то после вызова процедуры будет полагаться на них? Может есть негласные правила, как их надо выставить правильно? Бред же.

Коллеги, кто может прояснить вопрос: зачем BlackBox требует сохранять регистр общего назначения EBX? Как именно он его использует? Я предполагаю, что в документации просто забыли упомянуть EBX как разрешённый для изменения регистр.

Oleg N. Cher писал(а):
Код точно рабочий? Я проверил. Он даёт для ROR(1, 1) результат F333333333333334
А вот это, оказывается, было вызвано багом в калькуляторе Windows 7. Попробуйте вставить число -9223372036854775808 и сконвертить в Hex 8 байт. Он выдаёт: F333333333333334. Если вбить в Hex вручную 8000000000000000 и сконвертить обратно в Dec, будет -9223372036854775808. Мда уж.

Автор:  SovietPony [ Пятница, 01 Март, 2019 07:06 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Oleg N. Cher писал(а):
Коллеги, кто может прояснить вопрос: зачем BlackBox требует сохранять регистр общего назначения EBX? Как именно он его использует? Я предполагаю, что в документации просто забыли упомянуть EBX как разрешённый для изменения регистр.

Он используется как статическая свзязь. Т.е. используются локальными процедурами.

Автор:  Kemet [ Суббота, 02 Март, 2019 17:44 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Oleg N. Cher писал(а):
Очень даже подходит.
Всё-же, я думаю, что после XCHG нужно поставить что-то типа
Код:
TEST EDX, 80000000H
JZ done
STC

Автор:  Oleg N. Cher [ Воскресенье, 03 Март, 2019 11:17 ]
Заголовок сообщения:  Re: Оберон-07: вопросы реализации

Зачем? Вам так спокойнее? :-)

Никогда не видел такой практики, чтобы ценилось непонятное значение флагов непонятно после какой операции. Которых там может быть тьма.

Kemet, но чисто для Вас я поменял местами XCHG и SHRD.
Код:
   PROCEDURE [code] rorlong (x: LONGINT; n: INTEGER): LONGINT
      059H,             (*     POP  ECX          *)
      0F6H, 0C1H, 020H, (*     TEST CL, 32       *)
      074H, 001H,       (*     JZ   SHORT L1     *)
      092H,             (*     XCHG EAX, EDX     *)
      08BH, 0F0H,       (* L1: MOV  ESI, EAX     *)
      00FH, 0ADH, 0D0H, (*     SHRD EAX, EDX, CL *)
      00FH, 0ADH, 0F2H; (*     SHRD EDX, ESI, CL *)

Страница 3 из 5 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/