Оберон-клуб «ВЄДАsoft»

Твердыня модульных языков
Текущее время: 19 июн 2025, 23:41

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




Начать новую тему Ответить на тему  [ Сообщений: 22 ]  На страницу 1, 2, 3  След.
Автор Сообщение
СообщениеДобавлено: 05 июн 2014, 04:07 
Не в сети

Сообщения: 25
В этой теме будем обсуждать и развивать тонкие внутренние механизмы, которые помогут писателям библиотек.
Для тех, кто просто хочет писать свои библиотеки, или задаётся вопросом "Как добавить в свою программу код на ассемблере Z80 или на Си?", должно хватить темы: Как создать новую библиотеку для ZXDev

---------------

В Basic.h нашёл:

#define __hash__ #
#define __id__(x) x
#define __ld_a__(x) if(x==0) {__asm xor a,a __endasm;}else{__asm ld a,__id__(__hash__)x __endasm;}
#define __ld_c__(x) __asm ld c,__id__(__hash__)x __endasm

В чём нетавтология первых двух определений?
Оптимально ли сработает третье если х не константа?
(Не проверял, но кажется, что будет построена полная условная конструкция.)

Как называется применяемый диалект ассемблера z80 или где про него можно почитать?
За подсказки что такое # и $ спасибо, помогли. :)


Последний раз редактировалось Reobne 21 июн 2014, 12:47, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 06 июн 2014, 00:04 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Reobne писал(а):
В чём нетавтология первых двух определений?
Код: "C"
#define __hash__ #
#define __id__(x) x
— этот хитрый трюк нужен затем, что в ассемблере sdasz80 перед числовыми литералами и метками нужно обязательно ставить решёточку #. При задании макроса компилятор Си так просто не даёт это сделать. Так что __id__(__hash__) превращается после макропроцессора в #

Такой хитрый выход помог выработать Eltaron, за что ему огромное спасибо.

Reobne писал(а):
Оптимально ли сработает третье если х не константа?
Просто превратит одно в другое. Т.е. LD A,__id__(__hash__)1+2 в LD A,#1+2, а как это транслировать — будет решать sdasz80.

Reobne писал(а):
Как называется применяемый диалект ассемблера z80 или где про него можно почитать?
А вот тут: по ссылочке sourceforge.net/projects/sdcc/files/sdcc-doc/ есть доки, там в архиве раздел sdas посвящён исключительно ассемблеру.

Reobne писал(а):
За подсказки что такое # и $ спасибо, помогли. :)
Там ещё точка обозначает текущий адрес. Т.е.
Код: "ASM"
    DJNZ .    ; MET$: DJNZ MET$
И, в принципе, это почти всё, что следует знать об этом ассемблере. ;)


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 17 июн 2014, 03:42 
Не в сети

Сообщения: 25
Спасибо, читаю помаленьку. :)

Прочитал(sdccman.pdf 3.14.1.2), что в sdcc ассемблерные вставки можно делать так:
Код: "OBERON"
  1. __asm__ (; This is a comment\nlabel:\n\tnop”);


Тут "\n", это символ перевода строки; "\t" - табуляции.

И подумалось мне, что возможно, было-бы удобно писать ассемблерный текст прямо в обероновском исходнике.
Код: "OBERON"
  1. MODULE AsmTest;
  2. IMPORT Asm;
  3.  
  4. BEGIN (*$MAIN*)
  5. Asm.Code(' PUSH HL');
  6. Asm.Code(' LD HL,#0h4000');
  7. Asm.Code(' LD (HL),#1');
  8. Asm.Code(' INC H');
  9. Asm.Code(' LD (HL),#3');
  10. Asm.Code(' INC H');
  11. Asm.Code(' LD (HL),#7');
  12. Asm.Code(' INC H');
  13. Asm.Code(' LD (HL),#6');
  14. Asm.Code(' INC H');
  15. Asm.Code(' LD (HL),#255');
  16. Asm.Code(' INC H');
  17. Asm.Code(' LD (HL),#127');
  18. Asm.Code(' INC H');
  19. Asm.Code(' LD (HL),#127');
  20. Asm.Code(' INC H');
  21. Asm.Code(' LD (HL),#255');
  22. Asm.Code(' POP HL');
  23. END AsmTest.


Решил попробовать. Написал интерфейс библиотеки Asm
Код: "OBERON"
  1. MODULE Asm;
  2. (*PLATFORM Spectrum48;*)
  3.  
  4. PROCEDURE Code*(IN str: ARRAY OF CHAR); BEGIN END Code;
  5. END Asm.


Сохранил в "ZXDev\Lib\Mod"
Компильнул "F11"
Скопировал получившиеся Asm.c и Asm.h из "ZXDev\Lib\Obj" в "ZXDev\Lib"
Переправил хедер
Код: "OBERON"
  1. /* Ofront 1.2 -xtspkae */
  2.  
  3. #ifndef Asm__h
  4. #define Asm__h
  5.  
  6. #include "SYSTEM.h"
  7.  
  8.  
  9. #define Asm_Code(a,b) __asm__ ("; This is a comment\n\tnop")
  10.  
  11. import void *Asm__init(void);
  12.  
  13.  
  14. #endif
  15.  


Из Asm.c выкусил Asm_Code, (так как оно теперь в хедере, как предпроцессорный "макрос").
Собрал библиотеку.
Попробовал компилить тестовый пример - не получается :(
Потыкался, оказалось в батнике ZXDev\Bin\build.bat надо прописать "Asm.lib"

В таком виде всё компилится и собирается, но "; This is a comment\n\tnop" - это заглушка. Надо подставлять строку с кодом из аргумента.
И вот тут возник затык.
Тестовый пример даёт такой сишный код
Код: "OBERON"
  1. export main(int argc, char **argv)
  2. {
  3. __INIT(argc, argv);
  4. __IMPORT(Asm__init);
  5. __REGMAIN("AsmTest", 0);
  6. /* BEGIN */
  7. Asm_Code((void*)&" PUSH HL", (LONGINT)9);
  8. Asm_Code((void*)&" LD HL,#0h4000", (LONGINT)15);
  9. Asm_Code((void*)&" LD (HL),#1", (LONGINT)12);
  10. Asm_Code((void*)&" INC H", (LONGINT)7);
  11. Asm_Code((void*)&" LD (HL),#3", (LONGINT)12);
  12. Asm_Code((void*)&" INC H", (LONGINT)7);
  13. Asm_Code((void*)&" LD (HL),#7", (LONGINT)12);
  14. Asm_Code((void*)&" INC H", (LONGINT)7);
  15. Asm_Code((void*)&" LD (HL),#6", (LONGINT)12);
  16. Asm_Code((void*)&" INC H", (LONGINT)7);
  17. Asm_Code((void*)&" LD (HL),#255", (LONGINT)14);
  18. Asm_Code((void*)&" INC H", (LONGINT)7);
  19. Asm_Code((void*)&" LD (HL),#127", (LONGINT)14);
  20. Asm_Code((void*)&" INC H", (LONGINT)7);
  21. Asm_Code((void*)&" LD (HL),#127", (LONGINT)14);
  22. Asm_Code((void*)&" INC H", (LONGINT)7);
  23. Asm_Code((void*)&" LD (HL),#255", (LONGINT)14);
  24. Asm_Code((void*)&" POP HL", (LONGINT)8);
  25. __FINI;
  26. }
  27.  


Думаю, что из-за этого привидения типа "(void*)&", которое ОФронт понавставлял, и не работает.
Кажется, осталось немного и всё заработает. Либо обмануть ОФронт, чтобы не генерировал "(void*)&", либо как-то хитро сишным предпроцессором его откусить. Мне пока не удалось.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 17 июн 2014, 14:02 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
У меня тоже возникала эта проблема, и я не смог её решить. Ofront всегда приводит строку если не к "(void*)&" (в случае IN-параметра), то к "(CHAR*)". То есть требуется переделка Ofront'а. Пока не знаю как это лучше сделать. По поводу макропроцессора нужно консультироваться с продвинутыми сишниками. Но мне кажется, и здесь мало чего светит.

Предлагаю пока так:
Код: "OBERON"
  1. MODULE AsmTest;
  2. IMPORT _ := Asm;
  3.  
  4. BEGIN (*$MAIN*)
  5. _.Byte2( 3EH, 1); (* LD A, #1 *)
  6. _.Byte2(0D3H,0FEH); (* OUT (#0xFE), A *)
  7. END AsmTest.


Reobne писал(а):
Да, так можно.
Ещё можно каждой ассемблерной инструкции сделать обёртку и писать, например:
Код: "OBERON"
  1. Asm.LD_A_PEEK_HL;
  2. Asm.LD_A_CONST(12+3);
  3. Asm.LD_A_INT((I+5) MOD 16);
  4. Asm.LD_BYTEVAR_A(Char1);
  5. Asm.LD_WORDVAR_HL(X);



Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 19 июн 2014, 18:52 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Reobne писал(а):

Думаю, что из-за этого привидения типа "(void*)&", которое ОФронт понавставлял, и не работает.
Кажется, осталось немного и всё заработает. Либо обмануть ОФронт, чтобы не генерировал "(void*)&", либо как-то хитро сишным предпроцессором его откусить. Мне пока не удалось.
Возможно поможет средство Ofront PROCEDURE -
Цитата:
For procedures, Ofront allows a "-" sign after the keyword PROCEDURE in a procedure declaration to indicate that this procedure is an in-lined C code sequence.
The in-lined code is written in quotation marks after the procedure heading as in the following example:
Код: "OBERON"
  1. PROCEDURE -malloc(size: LONGINT): LONGINT
  2. "((LONGINT)malloc(size))";
Ofront translates such procedures into macro definitions which are subject to C preprocessing.
Код: "OBERON"
  1. #define Mymodule_malloc(size) ((LONGINT)malloc(size))
Obviously, this mechanism provides a way to interface Oberon with foreign languages such as C or assembly language, as explained in more detail in Section 4.2.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 20 июн 2014, 02:36 
Не в сети

Сообщения: 25
Saferoll писал(а):
Возможно поможет средство Ofront PROCEDURE -

Большое спасибо! Эта возможность ОFront-а удобна для написания библиотек. OFront сам генерирует #define. Править Си и Н файлы теперь можно меньше, или даже совсем не править! Одна проблема решена!!

Осталось, для "полного счастья" найти, как описать ему тип аргумента строку, чтобы она и оставалась строкой, без приведения типа.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 20 июн 2014, 12:13 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Saferoll писал(а):
Возможно поможет средство Ofront PROCEDURE -
Попробовал и так, не получается:
Код: "OBERON"
  1. PROCEDURE -Code* (cmd: ARRAY OF CHAR) "__asm__(cmd)";
  2. ...
  3. Asm.Code("ld a, #4");
  4. Asm.Code("out (#254),a");
  5.  
  6. (* всё равно превращается в: *)
  7.  
  8. Asm_Code((CHAR*)"ld a, #4", (LONGINT)9);
  9. Asm_Code((CHAR*)"out (#254),a", (LONGINT)13);
Проблему несомненно нужно как-то решать, а то вот даже Basic.DATA* удалось сделать для символов, байтов, слов и двойных слов, а со строками не получается. Раз подняли — будем решать. :)

Думаю попробовать модифицировать Ofront, чтобы помечать строковые параметры, которые не нужно приводить ни к какому типу, системным тегом [1], т.е. вот так:
Код: "OBERON"
  1. PROCEDURE -Code* (cmd: ARRAY[1] OF CHAR) "__asm__(cmd)";
Сейчас такие параметры приводятся к типу CHAR*, и раньше я активно использовал их чтобы избежать дублирования строк, но после добавления в Ofront IN-параметров использовать IN для этой цели даже ещё лучше, чем тег [1], потому что не нужен импорт SYSTEM. Так что вроде бы неплохое решение.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 20 июн 2014, 13:46 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Сделал. В процедуру OPV.ActualPar добавляем:
Код: "OBERON"
  1. IF ~(n^.typ^.comp IN {Array, DynArr}) THEN
  2. IF n^.typ^.sysflag # 0 THEN (* Ok *)
  3. ELSIF mode = VarPar THEN
После чего нужно пересобрать весь Ofront: Docu/Rebuild-Ofront.odc

Определение Code на Обероне:
Код: "OBERON"
  1. PROCEDURE -Code* (cmd: ARRAY[1] OF CHAR) "__asm__(cmd)";
Asm.Code("xor a") оттранслировалось в:
Код: "OBERON"
  1. ;AsmTest.c:21: Asm_Code("xor a", (LONGINT)6);
  2. xor a


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 20 июн 2014, 13:49 
Не в сети

Сообщения: 25
Кажется получилось! :)
Код: "OBERON"
  1. #define Asm___KILLER__(a)
  2. #define Asm_Code(str, str__len) __asm__(Asm___KILLER__ str)
  3.  


KILLER берёт как свой аргумент (CHAR*) и ликвидирует его.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 20 июн 2014, 16:43 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Браво, Reobne! Элегантно и оригинально! :) У вас определённо нестандартное мышление. Подпихнуть ненужное приведение типа как фиктивный параметр отдельного макроса — это надо додуматься. :)

На базе этого решения придумывается такая идея (думаю, легко будет реализовать):
Код: "OBERON"
  1. Asm.Code4(
  2. " LD A, #1 ",
  3. " OUT (#0xFE), A ",
  4. " LD B, #123 ",
  5. " METKA$: DJNZ METKA$ "
  6. );
Так ещё чище асм-код будет смотреться. А с учётом того, что сейчас Ofront умеет сам добавлять "линии разреза", — и смартлинковкой будет пользоваться проще. Правда, наверное ещё будут проблемы с переменными, будем дорабатывать по мере сил. :) Так что поздравляю, мы уже можем начинать разработку библиотек для Z80, не выходя напрямую на уровень Си.

Ну и откажемся от доработки тега [1], как я предлагал выше, — чтобы не разбивать совместимость. А то я уже засомневался и хотел делать для такого случая тег [2].


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

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


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

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


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

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
© VEDAsoft Oberon Club