PC-01 Lviv http://pc01.lviv.ua/forum/ |
|
Учимся писать на Обероне http://pc01.lviv.ua/forum/viewtopic.php?f=20&t=396 |
Page 3 of 4 |
Author: | als [ 02 May 2021, 01:00 ] |
Post subject: | Re: Учимся писать на Обероне |
Зорко, что такое "LOOP" как его применять ? и как на Обероне будет "не_равно" ? т.е (><) (<>) такое не работает |
Author: | Zorko [ 02 May 2021, 02:06 ] |
Post subject: | Re: Учимся писать на Обероне |
Quote: Зорко, что такое "LOOP" как его применять ? Вечный цикл с выходом по EXIT. Может быть вложенным.[/quote]Quote: и как на Обероне будет "не_равно" ? #т.е (><) (<>) такое не работает Quote: Т.е. если я туда добавлю, то оно подхватит при компиляции тот файлик ? ну он не для просмотра только, он участвует ? Подхватит если открыть Lib/Mod/*.Def и пересобрать библиотечный модуль по F12.Quote: какого черта за каждым (А+В) или (А=В) выполнять какие-то процедуры проверок типа или его границ ?! - НУ ЭТО Ж КР580 все таки... А с чего ты взял что там какие-то процедуры проверок за каждым (А+В) или (А=В) ?Quote: а в обероне есть такое как директивы ? типа в дельфи {$I-} {$I+} Директив в описании Оберона как таковых нет, но в некоторых реализациях есть. Ты про (*$MAIN*) спрашивал, так вот это и есть директива. Но это крайняя мера и моя отсебятина, это направление мы развивать не будем.может это отлючить можна те дописки пройедур на проверки типа, пределов его ? Но ты сначала определись с претензией, чтобы говорить предметно. А то тебе кажется, что там какие-то проверки, а их на самом деле нет. Я понимаю, что ты заглядывал в код, но всё это произведение zcc. Я на это не влияю. Quote: в дельфи помоему всякое (редко пользовался) {$R-} -помому проверки границ масивов отключает и т.д. Для проверок границ есть опция трансляции -i (в Ofront+.par).Quote: что кроме Lvov.c куда-то еще надо вставлять типа в Lvov.h ? или тут такого нет ? Да, есть такая дурня. А в XDev и в .Def тоже. Оберон-уровень.
|
Author: | Zorko [ 02 May 2021, 02:19 ] |
Post subject: | Re: Учимся писать на Обероне |
Quote: да если бы ты сделал асм-вставки (кр580) в оберон то цены бы не было бы твоей диковинке! Давай помозгуем, разрешит ли это zcc.В SDCC это удалось сделать при помощи конструкции __asm__(команда). В zcc такого нет, но есть #asm #endasm. Наверно не получится. zcc не даст передать произвольную команду строчным литералом. Если вдруг получится, я отпишусь. Но надежды мало. Это нештатная сишная фича, есть мало где. В любом случае, смотри как выглядит это с SDCC: Code: MODULE AsmTest; IMPORT Asm; PROCEDURE Border (color: INT8); BEGIN Asm.Code("POP BC "); Asm.Code("POP DE "); Asm.Code("POP HL "); Asm.Code("PUSH HL "); Asm.Code("PUSH DE "); Asm.Code("PUSH BC "); Asm.Code("LD A,L "); Asm.Code("CALL 0x229B"); END Border; BEGIN (*$MAIN*) Border(2); END AsmTest.Ты первый пойдёшь плеваться на то, что каждую строку надо предварять Asm.Code. Но можно и по-другому. Вот так: Code: MODULE AsmTest; (*$MAIN*) IMPORT SYSTEM; PROCEDURE Border (color: SYSTEM.BYTE); BEGIN (*@ #asm POP HL EX (SP), HL LD A, L LD (0xBE38), A ; BORDER CALL 0xF836 ; CLS #endasm *) END Border; BEGIN Border(25); LOOP END END AsmTest. |
Author: | als [ 02 May 2021, 09:49 ] |
Post subject: | Re: Учимся писать на Обероне |
Quote:
Ты первый пойдёшь плеваться на то, что каждую строку надо предварять Asm.Code.
Зорко та ты о чём ?! Кто будет плевать на возможность асм-вставок, в любом виде?!вот смотри, и все что можна с этого реализуй в первую очередь! Точно будет плюс в карму! Еще больший плюс чем от моих "простыней" Вот если бы ты не поленился скачать посмотреть (ПРОСТО ПОСМОТРЕТЬ) как мой мадл устроен ты такое мне не говорил бы (пойдёшь плеваться)... ну та ладно... Итак, нужна процедура типа MEM(Addr:word,B:Byte); Которая будет добавлять байт в конкретный адрес памяти-Львова. Адрес ОБЯЗАТЕЛЬНО НУЖНО УКАЗЫВАТЬ, ну это ж пользователя проблемы если он не туда полезет (не в тот адрес). Твоя диковинка всегда ж с нуля компилит ?! Т.е мне достаточно знать что смело могу процедуру спрайта устанавливать подальше $8000 и код компилятора его долго еще "не заденет" если я начну новую программу. Далее я его переставлю подальше, скажем $B000 или еще куда, ну не такой я уж и дурной, что не пойму когда его код компилятора задел мой код! Тем более буду знать же это и соответственно учитывать такое! Далее, нужно так как и в мадле из документации к мадлу Quote: procedure SetAddrRAM(e:Cardinal);{CodeProc=1#}
Задается адрес куда будет компилироваться дальнейший поток кода. Если адрес более 49151, выдается соответствующая ошибка. Также выдается ошибка если в данный адрес уже было компилирование. Quote:
Если адрес более 49151, выдается соответствующая ошибка.
НУ ЭТО МОЖЕШЬ НЕ РЕАЛИЗОВЫВАТЬ! НАФИГ НАДО!
Также выдается ошибка если в данный адрес уже было компилирование. Code: Procedure ComA(COM:Cardinal);{CodeProc=9#} Procedure ComB(COM,Value:Cardinal);{CodeProc=10#} Procedure ComC(COM,Value:Cardinal);{CodeProc=11#} Процедурами ComA, ComB, ComC Обрабатываться процедуры-команды-КР580, соответственно однобайтовые, двухбайтовые и трехбайтовые. В принципе пользователь может ими пользоваться, вот только следует учесть тот факт, что в них нет проверки на ошибки и их нужно использовать только правильно, т.е. недопустимо "путанное" использование этих процедур. Процедура ComА исключительно для однобайтовых кодов команд-КР580 (COM). Процедура ComB исключительно для двубайтовых кодов команд-КР580 (COM), где Value должно быть в пределах 0..255. Процедура ComC исключительно для трехбайтовых кодов команд-КР580 (COM), где Value должно быть в пределах 0..65535. В случае неправильного использования процедур, результирующий код будет неправильным и при этом выдача ошибки не будет. Пример использования процедур некоторыми процедурами-командами-КР580. Однобайтовая: {40}Procedure MovBB;begin A($40);end; Двухбайтовая: {06}Procedure MviB(e:Cardinal);begin B($06,e);end; Трехбайтовая: {01}Procedure LxiBC(e:Cardinal);begin C($01,e);end; В файле uMD00u.pas, таких примеров много. :-)Понятное деле что в процедурах ComA, ComB, ComC идет автоматическая приплюсовка Addr:=Addr+1; Addr:=Addr+2;Addr:=Addr+3; Далее на этих командах базируються команды-в-виде-процедур вот так вот: Quote:
{1 и двух байтовые}
Все это есть в мадле в файле uMD00u.pas, как говориться бери та перепилюй, путём "заменить все" на соответствующие конструкции Си.{03}Procedure InxBC;Begin ComA($03);end; ............. {2E}Procedure MviL(e:Cardinal);Begin ComB($2E,e);end; ...... {трехбайтовые} {01}Procedure LxiBC(e:Cardinal);Overload;Begin ComC($01,e); end; ...... А если влом, то реализуй всего лишь три команды одно- двух- трех- байтовую для примера и кинь мне, остальное попробую сам! Если же команды будут соответвовать uMD00u.pas то доточить декомпилятор мадла на мне эти всякие "Asm.Code" раз плюнуть! Ты понимаешь, я ж могу писать мадлом с метками а не прямыми адресами нужные мне процедуры спрайтов или еще чего.. далее привязываю к адресу в памяти процедурой SetAddrRAM в мадле компилирую, далее декомпилирую что в командах будут не метки а четкие адреса! И далее копирую просто в процедуру оберона и вставляю! Это ж все разово на какую-то данную програму делается! В том смысле что раз МАДЛ использовать для нужных процедур и раз вставить в оберон имеено то что нужно на асме-кр580 для данной конкретной программы-писаной-на-обероне ! Декомпилятор "подточенный под оберон все сделает как надо только в процедуру вставить нужно будет! Вот подумаю хорошенько над этим всем! прокурти как это выглядеть будет! посмотри uMD00u.pas! Метки в трехбайтовых командах-асма-в-обероне не нужны! по четким числам(адресам) делай. далее я сам! главное SetAddrRAM и далее код и все будет впорядке! |
Author: | als [ 02 May 2021, 10:04 ] |
Post subject: | Re: Учимся писать на Обероне |
Доп. Да и еще - не забудь же возможность вызывать те подпрограммы с оберона Например, код то я вбил! А как вызывать его процедурой оберона, как писать то мне ту процедуру Procedure Sprite(X1.... Y1.... Adr1...); Begin CallLV($8000); - типа вот так CallLV потому что Call уже используется для добаления кода end; ну а параметры в процедуре или надо знать в какие регистры-кр580 они сразу попадают или тоже как-то надо типа рег HL=Adr1 рег A=X1 и т.д. |
Author: | als [ 02 May 2021, 10:19 ] |
Post subject: | Re: Учимся писать на Обероне |
ДОП. Ах да! "Забирать" то данные из асм-кр580 регистров или же какой-то ячейки памяти в оберон-данные то тоже нужно в случае Funciton ReadKey:Byte; (или ReadKey:Word;) Begin CallLV(...) В лучшем случае из регистров хотябы из А , HL ReadKey:=GetRgA; // забираем из регистра А ReadKey:=GetRgHL ну или в крайнем случае из памяти ReadKey:=memB[....] // B - байт забираю ReadKey:=memW[....] // W - ворд забираю end; Ну короче продумай. Я пока не буду ничего делать косаемое Lvov.c пока не дождусь ответа от тебя. А что касаемо Lvov.c то наверное если можна до сделаю новый LvovS.c например и делать там свое чтобы не путалось с твоим! Можна ж так будет ? и подключать процедуры через LvovS.MyProc ? |
Author: | als [ 02 May 2021, 11:20 ] |
Post subject: | Re: Учимся писать на Обероне |
Quote:
Но ты сначала определись с претензией, чтобы говорить предметно. А то тебе кажется, что там какие-то проверки, а их на самом деле нет. Я понимаю, что ты заглядывал в код, но всё это произведение zcc. Я на это не влияю.
Зорко, все говорит о том, что ты не писал динамических игрушек для КР580! ИМЕННО ДИНАМИЧЕСКИХ! А Я ПИСАЛ!Так вот игра "Лабиринт" поле 30х30 (могу уже и ошибаться в чем-то, может 31х31, забыл, не суть важно) нужно вывести конкретный спрайт 8х8 в конкретную область памяти $4000{смещение видеопамяти}+(X*8)+(Y*512) так вот: вот это умножение на 512 мне пришлось делать таблицей для Y=0..31, потому что каждый раз высчитывая (Y*512) , быстродействие падало ужас как! Не веришь ? - ПРОВЕРЬ! Таблицу умножения на 8, вроде не делал хотя не вспомню уже! Если бы те процедуры были просто как мусор какой-то, - я бы ничего не сказал! А так они задействованы в коде да еще и так часто, да еще и с такими как А=В или А+В. Если бы было хотя бы умножение, то можно бы было понять! Зорко, ну давай на этом не разводить полемики какой-то! Ну ты ж прекрасно знаешь и понимаешь что в данном, конкретном случае по кр580 ну я ж прав! Ну 2,5мГц КР580, это ж не 2,5гГц, что то всё незаметно будет, и даже не 250мГц кр580-й и даже не 25мГц Давай не будем! знаю что говорю! Это не обсырательство! Вот сделаешь как я просил у тебя будет "железный отмаз" - чё не нравиться как работает в конструкциях оберона, - набахкай в кодах! Какие проблемы то?!" да и если такое будет я и сам буду понимать что "обсирать" как ты выражается нечего! Quote:
А то тебе кажется, что там какие-то проверки, а их на самом деле нет.
Мне не важно что то такое и зачем, у меня глаз намыленый асмом-кр580 и я прекрасно понимаю как оно должно выглядеть! и если даже делать "погрешность" на то что то все таки компилятор, а не "ручная "лепка" командами кр-580", то по-моему слишком большая то "погрешность"! Сомневаюсь что в паскалях и дельфи такая погрешность компиляторов с "прямым" асмом! (в процентном соотношении я конечно имею виду к быстродействию к конкретной данной машины)!но давай не будем!.. Quote:
Я понимаю, что ты заглядывал в код, но всё это произведение zcc. Я на это не влияю.
А тут очень интересный момент. Ты меня, когда мы ссорились, упрекнул меня, что разработчики для меня старались 32битку выпустили, а я такая "свинья" лишь бы обгадить... ну дело не в том!тут возникает вопрос - ТАК ВЛИЯЕШЬ НА НИХ ИЛИ ЖЕ НЕ ВЛИЯЕШЬ ? Если же влияешь, то чего ты выгораживаешь ИХ передо МНОЮ ? Скажи им, про "народный гнев" пусть даже этот "народный" из одного человека, т.е меня состоит, - но этому есть место! Ведь они компилятор пишут для КР580 ?! Не для 32-64 биток же пишут с 3 гГц?! Мой "гнев" вполне обоснован! А ты себя "успокаиваешь" тем, что я просто злобный завистливый троль которому лишь бы кого обгадить, потому что оберон лучше его мадла! Вопрос к тебе - А ДЕЙСТВИТЕЛЬНО ЛИ У ТЕБЕ ВЫБРАНА ПРАВИЛЬНАЯ ТАКТИКА ПОВЕДЕНИЯ В ДАННОМ СЛУЧАЕ ?! Если же это неправильное применения конструкций или же BYTE надо, вместо INT8, то тут другое дело! Но это уже другая и тема.. закругляюсь а то опять скажешь "простыней" я понаписывал... да просто получается так почему-то! |
Author: | als [ 02 May 2021, 12:28 ] |
Post subject: | Re: Учимся писать на Обероне |
На будущее. Есть потребность вот таком Quote: Var ArrConstDATALEVELS:array[0..2000] of Byte=($00,$01 ... $39,$A5,$2F,$7B);
т.е. инициализированный масив констант и/или переменныхили как оно в обероне то делается если база уровней например... Quote: Зорко, что такое "LOOP" как его применять ?
Т.е. это приравнивается к m1:JMP m1 ? может быть в любом месте в таком виде и без параметров и солько хочеш раз ? (а то я подумал что это часть какой-то конструкции цикла где еще как-то Begin end должен "лепится" к ней. Ну типа Repeat until или что-то в этом роде.Вечный цикл с выходом по EXIT. Может быть вложенным. Что с типом String ? String[255] LongString ? или как в обероне делается то ? Максимальная длина LongString ? Такая как в дельфи, - 2 гига, да ? и есть ли процедуры обрабатывающие подобное S:=S+'sdfsdf' ? Length ? Copy ? Pos ? PChar не предлагать! Терпеть их не могу! Может потому что пользоваться не умею им! А вообще, просто скажи, есть ли PChar ? # - ага, понятно "не равно", спасибо! Не забывать бы! А то в Дельфи оно другое значение! =============== Если ты реализуешь, все что связано с асмеблером, который видимо не только в ПК-01 работать будет?! Думаю это и другие любители ретро-машин оценят! У меня будут грандиозные планы на твою диковинку... и далее я преставляю себе так. Пытаюсь писать код какой-то, выкладываю черновик, вопросы, ты расматриваешь черновик, может в примеры годится откоректированный, отпишеш мне о том как более коректно применять какие конструкции, ошибки применения типа BYTE INT8 ( ну это видимо в примерах будет).. если чего добавляешь в свой архив на https://github.com/Oleg-N-Cher/K580Dev/, кидай обязательно ссылку когда у тебя обновлено хоть что-то и т.д. Далее по ходу проб не мешало бы будет поделать примеры соответвенно названые, коротко и хорошо описанные! Например, ReadKey.mod - короткая программа по обработке, клавиш и вывод кода на екран! WriteSprite.mod, Delay.mod и т.д. Понимаешь, считаю что вот таким короткими файлами лучше всего находить что-то нужное в данный момент! Не я ж один пользуюсь FAR Manager(или чем-то подобным), - навёл на файл в ФМ, и по F3(F4) "бахнул" и все как на ладони! Класно если пример в екран ФМ вмещаться будет. - короткий и ясный! Да и поиск по файлу, по каталогу где эти файлы... А ты меня PDF-ками тролил... Но то ты уж сам! если так уж PDFки любишь ! та короче... сработаемся! Не ты, не я не идиоты и думаю это уже нам обоим понятно! -------- И самый главный момент. На улице весна-лето. Естественно я могу исчезнуть из интернета по разным причинам! И не появляться на форум днями, неделями, а может и месяцами! Но это не означает что я забросил это! Во всяком случае навсегда! Рано или поздно явлюсь и буду заниматься! "Диковинка" эта мне пришлась по душе! |
Author: | als [ 02 May 2021, 12:53 ] |
Post subject: | Re: Учимся писать на Обероне |
ну вот расматриваю... и думаю... Code: PROCEDURE Border (color: SYSTEM.BYTE); BEGIN @ #asm POP HL EX (SP), HL LD A, L LD (0xBE38), A ; BORDER CALL 0xF836 ; CLS #endasm END Border;Ну классный вариант! Да и первый пойдет! Смотри сам! Вот только в этом вариате, нюансы есть. мне ж надо понимать куда какие параметры передаются! color куда передается ? в HL? - ну это только догадки мои! А далее мнемоника мне не очень-то понятна что такое EX ? что такое LD ? ну тоже можна догадаться, но лучше чтобы все это хоть как-то мало-мальски документировано было! Самое то главное не забывай! Это "направить" компиляцию в нужное место (как правило $8000 -$BFFF)! Вот в чем весь сыр-бор! И не только код но и массив данных спрайтов! Поэтому может все таки мой нужно реализовывать! с SetAddrRAM ! А то глядиш, фигня получится, хоть и асм вставки есть! |
Author: | als [ 02 May 2021, 15:03 ] |
Post subject: | Re: Учимся писать на Обероне |
Слушай, ты C:\XDev\K580Dev\Mod\ сортировал бы как-то что ли... например C:\XDev\K580Dev\Mod\Lvov C:\XDev\K580Dev\Mod\RK86 а то они в перемешку не удобно как-то! или работать не будут в каталогах ? Кстати создавал каталог C:\XDevProg\ перенес мод - не работал! Хотя переменные среды прописаны вот это точно правильно написано ? Quote: Если вы планируете работать с проектами вне папки C:\XDev\ то также
или все таки C:\XDev\K580Dev\ нужно ?необходимо прописать в "Имя переменной:" - "XDev" (без кавычек) в "Значение переменной:" - "C:\XDev\" (без кавычек) И по поводу C:\XDev\K580Dev\Mod\Lvov C:\XDev\K580Dev\Mod\RK86 так а почему именно ТОЛЬКО Lvov и RK86 ? если бы всех компом можна бы было понять! или же только Львов - можна понять |
Author: | als [ 02 May 2021, 15:06 ] |
Post subject: | Re: Учимся писать на Обероне |
DemoLvov.Mod в C:\XDev\K580Dev\Mod\Lvov\ C:\XDevProg\ не работает! Ошибка та что и на срине! |
Author: | als [ 02 May 2021, 15:28 ] |
Post subject: | Re: Учимся писать на Обероне |
Перенес C:\XDev\K580Dev\ в "сторону, распаковал K580Dev-94fba1b268cf33172c1b75dee060795d75a1860b.zip ВСЕ ТОЖЕ САМОЕ! DemoLvov.Mod - работает! Empty.Mod, Hello.Mod - для РК86 - тоже работает! Lvov4.Mod, TestTimer.Mod - не работает! |
Author: | Zorko [ 03 May 2021, 02:08 ] |
Post subject: | Re: Учимся писать на Обероне |
Quote: Вот если бы ты не поленился скачать посмотреть (ПРОСТО ПОСМОТРЕТЬ) как мой мадл устроен Да я знаю что такое макроассемблер. Ну пусть с очень навороченными макросами. Так это ты ещё Форт не видел. В нём такие вещи, которые ты сделал в МАДЛе для задания спрайтов, можно добавлять на лету.Quote: нужна процедура типа MEM(Addr:word,B:Byte); Которая будет добавлять байт в конкретный адрес памяти-Львова. Адрес ОБЯЗАТЕЛЬНО НУЖНО УКАЗЫВАТЬ, ну это ж пользователя проблемы если он не туда полезет (не в тот адрес). SYSTEM.PUT(adr, num).Для байта: SYSTEM.PUT(adr, 0). Для слова: SYSTEM.PUT(adr, LONG(0)). Есть ещё SYSTEM.GET Ты вообще описание Оберона читал хотя бы бегло? Quote: Твоя диковинка всегда ж с нуля компилит ?! На самом деле не факт. Но это уровень zcc. Надо выяснить как задать адрес компиляции, скорее всего, его задать можно какой-то опцией командной строки.Quote: Т.е мне достаточно знать что смело могу процедуру спрайта устанавливать подальше $8000 и код компилятора его долго еще "не заденет" если я начну новую программу. Далее я его переставлю подальше, скажем $B000 или еще куда, ну не такой я уж и дурной, что не пойму когда его код компилятора задел мой код! Тем более буду знать же это и соответственно учитывать такое! Да. Эту проблему надо решить. Буду думать.Quote: procedure SetAddrRAM(e:Cardinal);{CodeProc=1#} См. выше. ORG даже в асм-вставке задать нельзя.Задается адрес куда будет компилироваться дальнейший поток кода. Quote: Procedure ComA(COM:Cardinal);{CodeProc=9#} Для SDCC я такое делал (см. модуль Asm). Но в SDCC есть __asm__, а в zcc его аналога нет. Вернее, я не уверен, что решётку (#) съест. Ну да это тонкости Си - диграфы, триграфы, решётка служебный символ, короче.Procedure ComB(COM,Value:Cardinal);{CodeProc=10#} Procedure ComC(COM,Value:Cardinal);{CodeProc=11#} А чем тебе встроенный асм не зашёл? Разве числами писать машкод лучше, чем прямо мнемониками? Quote: Пример использования процедур некоторыми процедурами-командами-КР580. Вот такое бы ты смог сделать с SDCC. Можно наверно запросить эту фичу у z88dk'шников, но я не уверен, что им это понравится.Однобайтовая: {40}Procedure MovBB;begin A($40);end; Двухбайтовая: {06}Procedure MviB(e:Cardinal);begin B($06,e);end; Трехбайтовая: {01}Procedure LxiBC(e:Cardinal);begin C($01,e);end; Смотри, с SDCC даже вот так можно: Code: MODULE TestCalc; IMPORT b := Basic, c := CalcZX; BEGIN (*$MAIN*) b.Init; c.PushWord(1000); (* 1000 *) c.PushByte(24); (* 24 *) c.Begin; c.add; (* + *) c.pi_div_2; (* PI/2 *) c.duplicate; (* DUP *) c.add; (* + *) c.add; (* + *) c.End; b.PRSTR("1000 + 24 + PI = "); c.Print_PopReal(); b.Quit END TestCalc.Всё это компилится в байтики, а не в вызовы, как и твой МАДЛ. Quote: Метки в трехбайтовых командах-асма-в-обероне не нужны! Да можешь метки юзать во встроенном асме спокойно, какие проблемы.Quote:
ДОП. Ах да! "Забирать" то данные из асм-кр580 регистров или же какой-то ячейки памяти в оберон-данные то тоже нужно в случае Всё уже продумано и сделано авторами zcc. Есть пара моделей передачи параметров - в регистре и в стеке со снятием внутри процедуры. Из вставки на асме мы не можем этого юзать. Надо писать в обёртке Си - так, как в Lib/C/*.cFunciton ReadKey:Byte; (или ReadKey:Word;) Begin CallLV(...) В лучшем случае из регистров хотябы из А , HL [...] Ну короче продумай. А из асм-вставки в Оберон-процедуре (без обёртки в Си) мы можем юзать только стандартную сишную модель передачи параметров (в стеке без снятия внутри процедуры). Результаты функций всегда передаются в L (байт) или HL (слово). Или DE:HL (двойное слово). |
Page 3 of 4 | All times are UTC+03:00 |
Powered by phpBB® Forum Software © phpBB Limited https://www.phpbb.com/ |