PDA

Просмотр полной версии : Ищу Си для Z80



Страницы : 1 [2]

Smalovsky
12.09.2016, 23:10
Error404 писал:

Общепринятый.
z88dk может ещё конкуренцию составить. А так SDCC очень неплохой компилятор. Не я один считаю, что SDCC крут.
Alex Rider, я уже давно исправил функцию. А неправильный вариант можно считать демой. ))

Sergey
13.09.2016, 20:00
Что бы экран очищался правильно, нужно атрибуты устанавливать не только для основного экрана, но и для окна системных сообщений.

void setattr(char attrib){
__asm
ld hl, #2
add hl, sp
ld a, (hl)
ld (23693), a
ld (23624),a
__endasm;
}

один аргумент забирать можно ПРОЩЕ!


void setattr(char attrib) __z88dk_fastcall __naked {
__asm
ld a,l
ld (23693), a
ld (23624),a
ret
__endasm;
}

Если аргументов до 4-х слов, забирать со стека лучше через pop/push
Последний аргумент можно забрать в HL так: ex (sp),hl

Oleg N. Cher
14.09.2016, 04:23
Ух ты, а я и не знал о такой фишке. Значит, __z88dk_fastcall это однобайтовый аргумент в регистре L? Очень разумно. Вообще новые ключики SDCC __preserves_regs, __z88dk_callee и __z88dk_fastcall позволяют делать весьма интересные оптимизации, которые раньше были недоступны, в свете чего можно отрефакторить все библиотеки (ZXDev), оптимизировав различными способами получение параметров.

Например, вот эту процедуру можно оптимизнуть:


void Basic_AT_ROM_stdcall (unsigned char x, unsigned char y) __z88dk_callee __naked {
__asm
LD A,#22
RST 16
POP HL
POP BC
LD A,B
RST 16
LD A,C
RST 16
JP (HL)
__endasm;
} //Basic_AT_ROM_stdcall

- - - Добавлено - - -

В случае использования моделей вызова __z88dk_callee и __z88dk_fastcall есть проблемы с вызовом функций по указателю, на что указал Alcoholics Anonymous, но далеко не все функции нужно юзать таким способом, иногда в этом просто нет смысла.

- - - Добавлено - - -

Вот какая красота. Филипп обещал регистровые параметры и сделал. Пока что __z88dk_fastcall не тянет на идеал (можно только 1 параметр передавать), но, надо думать, идея получит развитие, я на это очень надеюсь.


4.3.3 Calling convention

By default, all parameters are passed on the stack, right-to-left. 8-bit return values are passed in 1, 16-bit values in hi, 32-bit values in dehl. Except for the GBZ80, where 8-bit values are passed in e, 16-bit values in de, 32-bit values in hide. Larger return values are passed in memory in a location specified by the caller through a hidden pointer argument.

There are three other calling conventions supported, which can be specified using the keywords __smallc, __z88dk_fastcall (not on GBZ80) and __z88dk_callee. They are primarily intended for compability with libraries written for other compilers. For __smallc, the parameters are passed on the stack, left-to-right, but variable arguments are currently not supported. For __z88dk_fastcall, there may be only one parameter of at most 32 bits, which is passed the same way as the return value. For __z88dk_callee, parameters are passed on the stack, but the stack is not adjusted for the parameters after the call (thus the callee has to do this instead). __z88dk_callee can be combined with __smallc.

Это, пожалуй, тот штрих, которого мне больше всего не хватало в Си для Z80 - именно регистровой передачи параметров. Ещё два момента, которые упорно обходят и не реализовывают - это:

помещение процедур и переменных в отдельные сегменты (аналог GCC'шных -ffunction-sections и -fdata-sections), что позволило бы не хранить функции в разных файлах, а если и хранить, то не резать код вручную на кусочки. Впрочем, для автоматизации этого процесса у нас есть моя утилита smartlib);
присвоение структур a = b;
SDCC глючен, и глупо было бы отрицать это. Но оптимизирующие компиляторы вообще сложны, и глюки фиксятся только благодаря стараниям команды и тех, кто их находит и не ленится репортить, т.е. нас с вами. SDCC (и бэк-энду для Z80) в этом смысле не хватает массового юзера. Но хорошая новость тут в том, что каждый глюк попадает в базу автоматических тестов, и потенциально мы имеем большую и всё увеличивающуюся базу различных тестов, которую даже наверное можно использовать для верификации других компиляторов языка Си.

Alcoholics Anonymous
15.09.2016, 00:36
z88dk может ещё конкуренцию составить. А так SDCC очень неплохой компилятор. Не я один считаю, что SDCC крут.


Это на самом деле не конкуренция - это больше похоже на сотрудничество. В "z88dk_callee" и "z88dk_fastcall" функциональных связей происходят из z88dk и "smallc" был добавлен легко взаимодействовать с библиотекой кода, написанного для sccz80, который выталкивает параметры функции в порядке слева направо (это наследуется от малых С и все компиляторы происходит от небольшой C разделяют эту idiosyncracy). Эти дополнения позволяют SDCC генерировать чистый и эффективный код при вызове в библиотеки языка сборки z88dk в. Они также служат очень хорошо для взаимодействия с пользователем сборки кода. Со стороны z88dk мы адаптировали в большую часть кода библиотеки в SDCC и создали модифицированную версию SDCC (zsdcc), что позволяет нашим ассемблер, z80asm, который будет использоваться в качестве заднего конца. Изменения включают имеющие SDCC правильно генерировать Экстерн списки и создание переводчика, чтобы перевести asz80 код на стандартный Zilog (The peepholer опирается на синтаксис asz80 так что вы не можете изменить SDCC генерировать стандартный код, то, что мы пытались в первую очередь). Тогда наша версия SDCC был изменен, чтобы сгенерировать лучший код: - это происходит от исправления ошибки в peepholer, чтобы он мог правильно определить, какие регистры считываются и записываются, в паре с добавлением тысячи новых правил глазок, чтобы исправить некоторые из сомнительного код SDCC производило. Также были добавлены некоторые правила, чтобы исправить некоторые ошибки генерации кода и больше возможностей для оптимизации размера кода при работе с длинных позиций, поплавки и longlongs. Я ожидаю, что эти улучшения или подобные ему будут появляться в SDCC в конце концов.


It is not really competition -- it's more like cooperation. The "z88dk_callee" and "z88dk_fastcall" function linkages come from z88dk and "smallc" was added to interface easily with library code written for sccz80 which pushes function parameters in left to right order (this is inherited from small C and all compilers derived from small C share this idiosyncracy). These additions allow sdcc to generate clean and efficient code when calling into z88dk's assembly language libraries. They also serve very well for interfacing with user assembly code. From z88dk's side we adapted most of the library code to sdcc and created a modified version of sdcc (zsdcc) that allows our assembler, z80asm, to be used as back end. The changes involve having sdcc properly generate extern lists and creating a translator to translate asz80 code to standard Zilog (the peepholer relies on asz80 syntax so you cannot change sdcc to generate standard code, something we tried at first). Then our version of sdcc was modified to generate some better code :- this comes from fixing a bug in the peepholer so that it can properly identify which registers are read and written, paired with adding a thousand new peephole rules to fix some of the questionable code sdcc was generating. Also added were some rules to fix some code generation errors and more opportunities for code size optimization when dealing with longs, floats and longlongs. I expect these improvements or similar ones will appear in sdcc eventually.




В случае использования моделей вызова __z88dk_callee и __z88dk_fastcall есть проблемы с вызовом функций по указателю, на что указал Alcoholics Anonymous, но далеко не все функции нужно юзать таким способом, иногда в этом просто нет смысла.


SDCC также способен компиляции z88dk __fastcall функции C ++, но он не может генерировать код для функций z88dk_callee абоненту.
Хорошо:



unsigned int abs(int a) __z88dk_fastcall
{
if (a < 0)
return -a;
return a;
}



Но есть проблемы с указателями на функции. SDCC не сможет генерировать указатель вызовы функций z88dk_fastcall или z88dk_callee функции, если это не разрешено использовать IY (так что вы не можете скомпилировать с "--reserve-регуляров-гу»). Существует также проблема, что расстраивает z88dk_fastcall и z88dk_callee являются частью типа функции. Это должно быть так, потому что компилятор должен знать, как вызвать функцию.


But there are problems with function pointers. sdcc will not be able to generate function pointer calls to z88dk_fastcall or z88dk_callee functions unless it is allowed to use IY (so you cannot compile with "--reserve-regs-iy"). There is also the frustrating problem that z88dk_fastcall and z88dk_callee are part of the type of the function. It has to be that way because the compiler has to know how to call the function.


So:



int func1(int a);
int func2(int a) __z88dk_fastcall;

int (*f)(int a);
int (*g)(int a) __z88dk_fastcall;

f = func1; // OK
f = func2; // error

g = func1; // error
g = func2; // ok

g = (int (*)(int a) __z88dk_fastcall)func1; // ok (I think) forced cast
g(-10); // does not work as call is via fastcall linkage without parameter on stack


Это означает, что вы должны иметь три ароматы указателей на функции, которые не могут быть взаимозаменяемыми.

Чтобы обойти эту проблему, в z88dk мы делаем все звонки через указатели на функции, используя стандартную связь и обеспечивают две точки входа для каждой функции: одну стандартную связь и одну азЬсаИ или вызываемого абонента. Если функция присваивается указатель на функцию, она всегда задается точка входа со стандартной связью. Во всех остальных случаях используется азЬсаИ или вызываемая связь.


This means you must have three flavours of function pointers that cannot be interchanged.

To get around this, in z88dk we do all calls through function pointers using standard linkage and provide two entry points for each function: one standard linkage and one fastcall or callee. If a function is assigned to a function pointer, it is always given the entry point with standard linkage. In all other cases, the fastcall or callee linkage is used.


In z88dk:


unsigned char *(*f)(unsigned int s);
unsigned char *a;

f = malloc; // standard linkage entry point
a = malloc(100); // fastcall linkage
a = f(100); // standard linkage



Существует только один вид указателя функции и выбор стандартной связи по сравнению с азЬсаИ или вызываемая является прозрачным. Это делается с помощью соответствующих макросов в файле заголовка. Вы можете увидеть, как в одном из заголовков:


There is only one kind of function pointer and the selection of standard linkage versus fastcall or callee is transparent. This is done with appropriate macros in the header file. You can see how in one of the headers:


http://z88dk.cvs.sourceforge.net/viewvc/z88dk/z88dk/include/_DEVELOPMENT/sdcc/string.h?revision=1.8&view=markup



Пока что __z88dk_fastcall не тянет на идеал (можно только 1 параметр передавать), но, надо думать, идея получит развитие, я на это очень надеюсь.


Это невозможно с генератором тока кода. Все z80 компиляторы были написаны начиная с идеей кадра стека, так что никто из них не сможет сделать это. Даже дискуссии я видел здесь о LLVM начинать с предположения кадра стека, так это опять-таки не было бы возможно с такой компилятор. (Существует еще один фронт компилятор конец вокруг под названием vbcc, который предназначен для пытается передать параметры через регистры, это было бы хорошим кандидатом для z80 компилятора, если у кого есть время, чтобы посмотреть на него).

Z88dk_fastcall и z88dk_callee связи то, что может быть сделано после того, как генератор кода уже написано. Вы можете попытаться придумать связи аналогично азЬсаИ, скажем, два параметра, но при добавлении параметров вы добавляете сложность кода, ведущих к вызову, потому что теперь компилятор должен жонглировать значения в правильные регистры и что не приходят бесплатно. Я смотрел на это некоторое время назад, и решил, что z88dk_callee был, вероятно, лучший компромисс, поскольку это позволяет ASM процедуры для сбора параметров в регистры через стек, используя минимальное число толчков и хлопков. АзЬсаИ связь по двум параметрам не всегда может привести к лучший код, чем 21-цикл PUSH / поп-пары при получении значения в двух регистрах. Возможно, в определенных обстоятельствах, как мимо двух символов это могло бы быть лучше, но я не думаю, что это стоит. Есть еще много других областей для улучшения, которые будут иметь большее влияние, я думаю.


This is not possible with the current code generator. All z80 compilers have been written beginning with the idea of the stack frame so none of them will be able to do this. Even discussions I have seen here about LLVM begin by assuming a stack frame so this again would not be possible with such a compiler. (There is another compiler front end around called vbcc that is designed for trying to pass parameters via registers; it would be a good candidate for z80 compiler if anyone has the time to look at it).

The z88dk_fastcall and z88dk_callee linkages are what can be done after a code generator is already written. You can try to come up with a linkage similar to fastcall for, say, two parameters but when you add parameters you add complexity to the code leading up to the call because now the compiler has to juggle values into the right registers and that does not come free. I looked at this some time ago and decided that z88dk_callee was probably the best compromise as it allows asm routines to gather parameters into registers via the stack using the minimum number of pushes and pops. A fastcall linkage for two parameters may not always produce better code than a 21-cycle push/pop pair when getting values into the two registers. Perhaps in specific circumstances like passing two chars it might be better but I don't think it's worth it. There are still a lot of other areas for improvement that would have more impact I think.

Oleg N. Cher
16.09.2016, 01:51
Alcoholics Anonymous, the model __z88dk_fastcall is the thing that I really needed and did not have earlier in SDCC compiler, and I am very happy now that there are models __z88dk_fastcall and __z88dk_callee. __preserves_regs is a very interesting feature too! And all they are really useful for practical coding, and not only for compatibility with libraries written for other compilers, as written in the manual. And for new libraries design with so effective passing parameters to functions, which is close to pure assembler. Great thing! And many thanks to all those who made it possible, firstly thanks z88dk team, of course!

I still haven't tried your peephole optimizer, but I'll exactly do it in the near future.

How do you look at the idea to extend the concept of the model __z88dk_fastcall ? Now it allows only one parameter of 8, 16 and 32 bits size. You can allow using more parameters, wherein the first byte of a first parameter to be placed in L, the second byte in H, after it, in E, D, C, B, A, IY.

That is, for example, three parameters of "void PutPixel (unsigned char x, unsigned char y, unsigned char color)" will be placed: x in L, y in H, color in E. The three parameters of "void PutPixel3D (int x, int y, int z)" will be placed: x in HL, y in DE, z in BC. Etc. Such model would be even more useful than current __z88dk_fastcall. What do you think?

Smalovsky
21.09.2016, 00:49
Использую SDCC. Перенёс функции в библиотеку - написал заголовочный файл и файл описаний. Подключил библиотеку через #include "...". Скомпилированая программа вылетает с сообщением о неправильном цвете чернил. Хотя если функции в одном файле с главной функцией программы - то всё работает.
Почему так происходит?

Oleg N. Cher
21.09.2016, 01:46
Недостаточно информации. Кажи код.

Smalovsky
21.09.2016, 11:57
Код тут не причём. Я в главной функции закомментировал вызовы функций. Результат - программа не работает. Если закомментировать include компилируется и запускается. Может дело в каких-нибудь ключах компилятора?

- - - Добавлено - - -

В моём проекте нет crt0.s, а адрес размещения кода задаётся --code-loc. Я подумал, надо добавить crt0.s.
Возьму пример отсюда http://www.speccy.pl/articles.php?article_id=22
На сайте есть примеры интересных решений из области MCU:
__sfr __at 0xfe border; // port for border colour setting
__sfr __banked __at 0x7ffe keyboard; // port for reading keyboard (space)
это объявление ячеек с фиксированными адресами как специализированных регистров.
Этот сайт нельзя показывать и BlastOFF'у и wbr'у, а то они быстро найдут дополнительную аудиторию для своей газеты.))

Oleg N. Cher
21.09.2016, 18:00
Я всегда удивлялся, зачем люди придумывают себе такие сложности. Хотя до простоты нужно идти часто ещё дальше. В данном случае люди спотыкаются об генерацию tap, конвертирование ihx в bin, вот этот самый crt0 - нужен или нет? Smalovsky, возьмите EmuZWin и пройдите программу по шагам, там это легко. Задайте в PC стартовый адрес своего машкода, откройте дебаггер и прошагайте по F7/F8 весь код, и ошибка непременно найдётся.

Alcoholics Anonymous
22.09.2016, 01:41
How do you look at the idea to extend the concept of the model __z88dk_fastcall ? Now it allows only one parameter of 8, 16 and 32 bits size. You can allow using more parameters, wherein the first byte of a first parameter to be placed in L, the second byte in H, after it, in E, D, C, B, A, IY.


That is, for example, three parameters of "void PutPixel (unsigned char x, unsigned char y, unsigned char color)" will be placed: x in L, y in H, color in E. The three parameters of "void PutPixel3D (int x, int y, int z)" will be placed: x in HL, y in DE, z in BC. Etc. Such model would be even more useful than current __z88dk_fastcall. What do you think?

The best way to see what the problems are is to try to write the code by hand that the compiler will have to write ahead of a function call. Use a real compiler-generated assembly listing and try to modify code leading into those calls to use fastcall linkage like this. The issue with forcing the compiler to place values into registers is that as registers are given their values, the compiler can no longer use those registers to gather more values. This leads to a lot of code ahead of the call.

So in "void PutPixel3D (int x, int y, int z)" after putting x into HL, the compiler can no longer use HL to put y into DE. After it puts y into DE the compiler cannot use HL or DE to put z into BC. The code will be poor unless x,y,z are static variables. This is what I meant by the callee linkage being quite a good compromise -- because it allows the parameters to be gathered without register restriction and it only costs 21 cycles / 2 bytes for the push before the function call and the pop inside the function. Better, the called function can pop the values into the registers it needs them in whereas using a fastcall linkage like this the called function will have to shuffle the registers into the correct destination registers.

You might be thinking that the parameter gathering into registers from local values is not a big deal since it can be done easily with (ix+d) offsets. But the compiler needs to stay away from ix as much as possible to get any sort of decent performance or decent code size. sdcc tries to keep things in registers, as it should, and only spills to (ix+d) or the stack when it has to. If it has to gather values into specific registers, I think you will see a lot more pushing/popping to save registers or even storing in temporaries created by the compiler and indexed by ix, which is what sdcc does when it has too many variables in its working set.

In specific circumstances like gathering two chars into HL, it's very a likely a win but I'm not too enthusiastic about other cases for the reasons mentioned above.


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

Таким образом, в "ничтожной PutPixel3D (INT х, у Int, Int г)" после того, как положить х в HL, компилятор больше не может использовать HL положить у в DE. После того, как он ставит у в DE компилятор не может использовать HL или DE, чтобы положить в г до н. Код будет плохим, если х, у, г не статические переменные. Это то, что я имел в виду вызываемым связи будучи довольно хороший компромисс - потому что это позволяет параметры должны быть собраны без ограничений регистра и стоит всего 21 циклов / 2 байта для толчка перед вызовом функции и поп-музыки внутри функции. Лучше, вызываемая функция может выскочить значения в регистры он нуждается в них в то время как с помощью азЬсаИ связи, как это вызываемая функция придется перетасовать регистры в соответствующие регистры назначения.

Вы можете подумать, что параметр сбора в регистры из локальных значений не имеет большого значения, так как это может быть сделано легко с (IX + D) смещений. Но компилятор должен держаться подальше от IX как можно больше, чтобы получить какой-либо достойной производительности или достойного размера кода. SDCC пытается держать вещи в регистрах, как и положено, и только разливает к (IX + D) или в стеке, когда он должен. Если он должен собрать значения в конкретные регистры, я думаю, вы увидите гораздо больше, толкания / выскакивают, чтобы сохранить регистры или даже хранить в современниками, созданных компилятором и проиндексированных IX, которая является то, что SDCC делает, когда он имеет слишком много переменных в его рабочий набор.

В конкретных обстоятельствах, как сбор двух символов в HL, это очень вероятный выигрыш, но я не слишком энтузиазма по поводу других случаев по причинам, указанным выше.

OrionExt
22.09.2016, 02:13
Учитесь у буржуя=) Мысли по делу излагать. Мини Хелп с разжёвыванием как оно работает.

Хотя он там об оптимизации кода говорит или ... Да и пусть. Любитель.

- - - Добавлено - - -

Вы еще Си не нашли, тогда вам к нам HI-TECH Z80 C Compiler. Занимает 30кБ +30кБ +30кБ. Адекватен. Понятен. Доступен всем!!!

- - - Добавлено - - -

HI-TECH Z80 C Compiler написан на Си HI-TECH Z80 C Compiler. ВО!!!. Академичные алгоритмы мало интересны для Z80 если они не могут переплюнуть разработку 83 года) Тем более не адекватностью генерируемого кода зашкаливает у новоделов.

Знаем, смотрели Си HI-TECH Z80 в IDA Pro с хитрыми макросами. Написан на СИ.

Oleg N. Cher
22.09.2016, 02:47
HI-TECH Z80 C Compiler запускается из-под CP/M. Во! ;-) И имеет глюки, которые уже никто не исправит. Тоже во! ;-) И нам без разницы на чём он написан, потому что исходников нет. И эмоциями тут делу не поможешь.

Smalovsky, насчёт вашего глюка. Я рискну предположить, что вы инклюдите не хидер *.h, а *.c-файл. Это плохо. Потому что инклюдить нужно только хидеры, как бы руки ни чесались. Так задумано.

Второе, это наверняка ваша main() расположена не первой, а программа стартует с самой первой функции. Из-за отсутствия правильного crt0, который переходит к стартовой точке - ф-ции main().

Всё это вкупе даёт такой глюк:


#include "mufuncs.c" // <--

void main(void) {
return;
}Программа будет стартовать с первой ф-ции из файла mufuncs.c - рискну предположить, что там ф-ция задания цвета, которая получает на вход случайный аргумент?

Рискну предложить такой crt0:


.module crt0
.globl _main
jp _mainЗаписываете его в файл crt0.s и ассемблируете:


sdasz80 -o ..\crt0.rel crt0.s

OrionExt
22.09.2016, 03:03
HI-TECH Z80 C Compiler запускается из-под CP/M. Во! ;-) И имеет глюки, которые уже никто не исправит. Тоже во! ;-) И нам без разницы на чём он написан, потому что исходников нет. И эмоциями тут делу не поможешь.

У меня нет эмоций. Все понятно, и еще раз понятно.
Мучайтесь дальше=)

Мазохисты форевер уже лет 20)

Oleg N. Cher
22.09.2016, 13:52
Мы наслаждаемся...

- - - Добавлено - - -

Как будто бы сношаться с эмулем CP/M это не мазохизм?

Я вот сделал ставку на SDCC в своё время, и ни капельки не жалею. Компилятор жив, открыт, мультиплатформенн, развивается, можно пообщаться с разработчиками. Пока я совершенствовал Ofront, команда SDCC развивала мой бэк-энд. А с учётом появления фич __preserves_regs, __z88dk_callee и __z88dk_fastcall мне вообще все другие компилеры не пригодятся. Кстати, HITECH C неоптимально использует стек при передаче однобайтовых параметров ф-циям. А в версии 7.50 есть глюки, на что указал мне приватно Alcoholics Anonymous. А юзать компилер с глюками и без надежды на их исправление - та ещё байда.

Так что "где-то когда-то видел в дизасме код, и я тащусь" слабо актуально. Это вы ещё не видели код после peephole оптимизатора z88dk-sdcc.

- - - Добавлено - - -

Да, кстати, а есть в HITECH C возможность не занимать рег. IY? В SDCC есть --reserve-regs-iy. И вообще, прислушиваться надо к мнению тех, кто кодил на нём, а не "где-то что-то" видел. ;)

Smalovsky
22.09.2016, 18:14
Немного разобрался. crt0.s нужен был. Взял с форума тэсэлыча.)) У денпопова в тетрисе такой же.
Проект компилируется, запускается подготовленный тап. Только компилятор глобальный массив инициализирует с ключевым словом const - иначе никак. Может, получше crt0.s найду потом - пока этого хватит.
Я тут написал inkey().

unsigned char inkey(){
__asm
ld a, (23560)
ld l, a
ld h, #0
ld a, #0
ld (23560), a
ret
__endasm;
}

Только функция чего-то символы псевдографики и udg ловит. Стартаповый файл, видимо, режим ввода меняет. Буду разбираться.

- - - Добавлено - - -

Ничего не понял... Кукую переменную надо поменять, что бы изменить режим ввода? Прочитал о MODE и FLAGS. Менял MODE - inkey() ловит коды в режиме G.
Может, лучше задействовать K_STATE( ячейка #5C04( 23556) )?

Oleg N. Cher
22.09.2016, 20:28
Если из массива производится только чтение, то const рекомендую и оставить. Иначе же данные массива сдублируются два раза - копия начального состояния массива всё равно будет храниться. Так что это примерно то же самое, что и завести два массива - константный и обычный, и копировать при старте из константного в обычный. Только делается в стартовой секции crt0 неявно. Мой вариант crt0 урезан и эту инициализацию не выполняет.

У меня INKEY устроен иначе:


unsigned char Basic_INKEY (void) {
__asm
LD A, (#0x5C07)
CP #0xFF
JR Z, INKEY_RET_0X$
CALL 0x28E
LD C, #0
JR NZ, INKEY_RET_0X$
CALL 0x31E
JR NC, INKEY_RET_0X$
DEC D
LD E, A
CALL 0x333
LD L, A
RET
INKEY_RET_0X$:
LD L, #0
__endasm;
} //Basic_INKEY

Sergey
28.09.2016, 07:16
Я тут написал inkey().
А теперь правильный инкей:


unsigned char inkey(void) __naked
{
__asm
ld a,(0x5c04) ; BASIC var
ld l,a

1$: ld a,(0x5c04)
inc a
ret z
jr 1$
__endasm;
}
В моём варианте 2048 клавиатура опрашивается так.
Можно укоротить на 1 байт и 1 такт:


ld hl,(0x5c04) ; BASIC var

- - - Добавлено - - -


Рискну предложить такой crt0:
Здравствуйте, - а как же будут переменные и массивы инициализироваться?!

Oleg N. Cher
28.09.2016, 15:27
Ну, до сих пор для ZXDev такого crt0 хватало (в Обероне нет проинициализированных переменных и массивов).

Smalovsky
28.09.2016, 16:04
Я тут, кое-что напрограммировал. Делаю головоломку. Оцените скорость генерации уровня и качество перемещения фишки. После изображения уровня нажмите любую клавишу для появления фишки. Пожалуйста, отпишитесь.
По компилятору возникло много вопросов. Например, глобальные переменные видны только main, и их придится передовать в качестве параметров другим функциям. Компилируется с ошибками, когда доступ к стуктуре происходит через указатель.
58360

s_kosorev
28.09.2016, 16:29
Например, глобальные переменные видны только main, и их придится передовать в качестве параметров другим функциям.
Почитай что нить по си хотя бы классику, Керниган и Ритчи

Alcoholics Anonymous
07.10.2016, 09:10
HI-TECH Z80 C Compiler написан на Си HI-TECH Z80 C Compiler. ВО!!!. Академичные алгоритмы мало интересны для Z80 если они не могут переплюнуть разработку 83 года) Тем более не адекватностью генерируемого кода зашкаливает у новоделов.

Знаем, смотрели Си HI-TECH Z80 в IDA Pro с хитрыми макросами. Написан на СИ.

Hitech C CPM уступает по справедливой отрывом z88dk / SDCC. Hitech C v7.50 для DOS ближе. Вы можете взглянуть на некоторые из сравнений, которые мы сделали 10 месяцев назад с использованием реальных программ и общих критериев:

http://www.z88dk.org/wiki/doku.php?id=temp:front#dhrystone_2.1

С тех пор я не стал бы ожидать больших изменений в скорости для z88dk / SDCC, но некоторые типы программ будет значительно меньше сих пор.

Где Hitech действительно выходит вперед в скорости в плавающей точкой, когда он работает. Но причина этого в том, что реализация флоат Hitech является 32-бит, тогда как z88dk является 48-битный.

Есть и другие факторы, помимо качества генерации кода, которые являются важными или более важными. Такие вещи, как соответствие стандартам качества, библиотек и гибкого набора инструментов. Я бы сказал Hitech был превзойден по всем этим пунктам. Так что нет, я не совсем согласен с вашей оценкой, что современные инструменты не лучше, чем в 1983 г. продукт :)

Существует текущее развитие при помощи LLVM с C фоновым, а затем передавая, что через компилятор Z80 C для генерации кода. LLVM выполняет больше оптимизацию, чем SDCC и, похоже, может быть, LLVM-> sdcc-> z80 может генерировать лучший код. Еще одна интересная возможность это открывает использует LLVM для компиляции других языков на C, которые затем могут быть скомпилированы для Z80. Это именно то, как работает Оберон Олега.

Зачем идти от LLVM-> C, а не LLVM-> z80? Причина заключается в задний конец инструмента LLVM являются не подходят для генерации кода для 8-битных целей. Много усилий придется вложить, чтобы сделать это. Маршрут LLVM-> C ярлык и выглядит, как это может быть нормально, даже для перевода C-> C. Но я думаю, что более интересный аспект будет на других языках, переведенных на C после оптимизации с помощью LLVM.


Hitech C CPM is outperformed by a fair margin by z88dk/sdcc. Hitech C v7.50 for DOS is closer. You can have a look at some of the comparisons we did 10 months ago using real programs and common benchmarks:

http://www.z88dk.org/wiki/doku.php?id=temp:front#dhrystone_2.1

Since then I would not expect much change in speed for z88dk/sdcc but some types of programs will be significantly smaller now.

Where Hitech does come out ahead in speed is in the floating point, when it works. But the reason for that is that Hitech's float implementation is 32-bit whereas z88dk's is 48-bit.

There are other factors besides quality of code generation that are important or more important. Things like standards compliance, quality of libraries and flexible toolchain. I would say Hitech has been surpassed on all these points. So no, I don't quite agree with your assessment that modern tools are no better than a 1983 product :)

There is current development in using LLVM with a C back-end and then passing that through a Z80 C compiler to generate code. LLVM performs more optimizations than sdcc and it looks like maybe LLVM->sdcc->z80 might generate better code. Another interesting possibility this opens up is using LLVM to compile other languages to C which could then be compiled to z80. This is exactly how Oleg's Oberon works.

Why go from LLVM->C rather than LLVM->z80? The reason is LLVM's back end tools are not suitable for generating code for 8-bit targets. A lot of effort would have to be invested to do that. The LLVM->C route is a shortcut and looks like it might be ok even for C->C translation. But I think the more interesting aspect would be other languages translated to C after optimization by LLVM.

Oleg N. Cher
18.12.2016, 21:28
Alcoholics Anonymous, let me request a feature :-)

Can you improve the functionality of the convention call __z88dk_fastcall to pass not only one argument, but two too? The register that be used for passing the second argument will be determined in advance.

To reduce the complexity, I suggest yet to allow the second argument only of size 1 (or 2) bytes, and use C (or BC) to pass it. For the first argument, let everything is as it is now: L, HL, HL : DE

Yeah, it looks like a half-measure, but can you have a better idea? Or, you never want to pass arguments in this manner?

P.S. I have functions like Plot(char x, char y), Draw(char x, char y), etc, and I want to pass the arguments using registers.

Alcoholics Anonymous
01.01.2017, 07:19
Can you improve the functionality of the convention call __z88dk_fastcall to pass not only one argument, but two too? The register that be used for passing the second argument will be determined in advance.


I can have a look at it but it may take a while to get to it.... the to-do list is long :)

Oleg N. Cher
01.01.2017, 14:39
Now for a function that uses two arguments, I use this way:


/*--------------------------------- Cut here ---------------------------------*/
unsigned char Basic_ATTR_callee (unsigned char y, unsigned char x) __z88dk_callee {
__asm
POP HL
POP BC
PUSH HL
CALL 0x2583
CALL 0x2DD5
LD L,A
__endasm;
} //Basic_ATTR_callee

/*--------------------------------- Cut here ---------------------------------*/
unsigned char Basic_ATTR_fastcall (unsigned int yx) __z88dk_fastcall {
__asm
LD C,L
LD B,H
CALL 0x2583
CALL 0x2DD5
LD L,A
__endasm;
} //Basic_ATTR_fastcall

//----------------------- ATTR (y, x: TextCoords): UBYTE -----------------------
extern unsigned char Basic_ATTR_callee (unsigned char y, unsigned char x) __z88dk_callee;
extern unsigned char Basic_ATTR_fastcall (unsigned int yx) __z88dk_fastcall;
#ifndef ATTR_fastcall
# define Basic_ATTR Basic_ATTR_callee
#else
# define Basic_ATTR(y,x) Basic_ATTR_fastcall(((x)<<8) + (y))
#endif
If the token ATTR_fastcall is defined, two unsigned char arguments x, y are packed to one unsigned int, and calls Basic_ATTR_fastcall. It's efficient for constant arguments, but may has some calculations in run-time for non-consts - the inevitable overhead of this method. So the solutions is rather indirect. And I thought, maybe it is possible to expand the scope of the __z88dk_callee to pass at least two 1-byte arguments in registers.

P.S. Excellent developers have the to-do list is long always ;-)

Smalovsky
03.01.2017, 17:12
А у меня вопрос - можно ли использовать не поддерживаемые компиляторы си - хайтеч и иар? Разрешено ли их использование в коммерческих целях без лицензии ?

s_kosorev
04.01.2017, 00:07
только в играх без магии

Oleg N. Cher
04.01.2017, 00:12
Когда-то переписывался с IAR на тему использования их компилятора для Z80, мне предложили его купить, выслали демо-версию со сроком работы 1 мес. Про хайтек не в курсе. Но скорее всего он так и помер коммерческим продуктом, никто его безплатным не делал.

Чем SDCC не устраивает? Вкуснейший компилятор, особенно в свете фич __z88dk_fastcall, __z88dk_callee, __preserves_regs. Или z88dk?

Sayman
04.01.2017, 07:45
Вкуснейший компилятор, особенно в свете фич __z88dk_fastcall, __z88dk_callee, __preserves_regs. Или z88dk?
что там вкусного? баги двухлетней давности не могут устранить, а новые только плодятся. проекты собираются по 10 - 15 минут на 4х головой машине. от версии к версии один и тот же исходник перестают собираться и его каждый раз нужно править.
что-то не очень вкусно, знаете ли.

Oleg N. Cher
04.01.2017, 12:37
Чтобы устраняли баги - надо их активно репортить. Да, некоторые зависают, бывает. Но это издержки разработки. В отличие от багов, которые уже никогда не исправят в хайтек и иар Си, это, знаете ли, очень приемлемо.

Вопросы раздельной компиляции мы уже обсудили. Руки отрывать за монолитный исходник. Более того, в SDCC можно воспользоваться старым аллокатором регистров (его оставили) --oldralloc, он шустрее. Такая длительная компиляция, как я понимаю, она из-за поиска оптимального размещения в регистрах, реализована, видимо, перебором.

"От версии к версии перестаёт собираться и надо править" - а что ж вы хотели, не всегда есть смысл тащить совместимость с отмершими вещами. Например, убрали обязательный фрейм PUSH IX : LD IX, 0 : ADD IX, SP для каждой функции, так что же, плакать из-за этого? Да я лучше порадуюсь и код перепишу, эффективнее будет.

Alcoholics Anonymous
04.01.2017, 22:42
Когда-то переписывался с IAR на тему использования их компилятора для Z80, мне предложили его купить, выслали демо-версию со сроком работы 1 мес. Про хайтек не в курсе. Но скорее всего он так и помер коммерческим продуктом, никто его безплатным не делал.


Обращались ли вы IAR в последнее время? Они не упоминают свои Z80 инструменты на их веб-страницы больше.

Hitech был куплен Microchip которого первым делом должен был убить всех компиляторов Hitech, не связанные с ПОС. До этого было сделано, Hitech дал разрешение на использование и распространение компилятор C, который работает на CP / M (не версия DOS, которая работает под управлением MS-DOS).


Did you contact IAR recently? They don't mention their z80 tools on their webpage anymore.

Hitech was bought by Microchip whose first order of business was to kill all Hitech compilers not related to the PIC. Before that was done, Hitech gave permission to use and distribute the C compiler that runs on CP/M (not the DOS version that runs under MSDOS).




что там вкусного? баги двухлетней давности не могут устранить, а новые только плодятся. проекты собираются по 10 - 15 минут на 4х головой машине. от версии к версии один и тот же исходник перестают собираться и его каждый раз нужно править.
что-то не очень вкусно, знаете ли.

Дайте z88dk попробовать. Мы ликвидировали множество ошибок в SDCC и получили доступ к библиотекам SDCC z88dk в, которые написаны в машинном коде и гораздо более полным. Она может быть нацелена спектра непосредственно без махинаций с КРТ и программ будет быстрее и меньше по сравнению с нативным SDCC. Вы можете собрать любое количество исходных файлов (ASM или С среди них) в одну линию прямо к водопроводной или двоичном.

Скорость компиляции является медленным, согласился, но вы можете уменьшить оптимизацию при разработке, чтобы ускорить или настроить Makefile только перекомпилировать файлы, которые изменились.

Я бы не использовать старую ralloc в SDCC - есть много ошибок в там.


Give z88dk a try. We've eliminated many of the bugs in sdcc and given sdcc access to z88dk's libraries, which are written in machine code and are much more complete. It can target the spectrum directly without fiddling with the crt and programs will be faster and smaller compared to native sdcc. You can compile any number of source files (asm or c among them) in one line straight to tap or binary.

The compilation speed is slow, agreed, but you can turn down the optimization while developing to speed things up or set up a makefile to only recompile files that have changed.

I wouldn't use the old ralloc in sdcc -- there are many bugs in there.

Oleg N. Cher
05.01.2017, 00:14
Alcoholics Anonymous, yes, indeed the IAR C compiler for Z80 target is no longer present in the list of their products. I contacted the company IAR and I have a letter from them dated at end of 2012 year.

- - - Добавлено - - -


Submitted Friday September 28, 2012 12:49 PM (Central European Time)
-----------------------------------------------------------------
Product: EWZ80
Name: Oleg N. Cher
Title: Developer
Email: <SKIPPED>
Phone: <SKIPPED>
Fax:
Company: VEDAsoft
Country: Ukraine
Countrycode: UA
Address:
Zip code:
City:
Web site:

Dear IAR Systems,

For some hobby retrogaming stuff I am interested in your old Workbench for Zilog Z80 CPU. But I could not find on your site, even a trial version to download and try.

If you are not interested in selling the version for Z80, can you consider to make available the downloadable trial version, or liberalize as free for non-commercial use? Thank you.

Oleg N. Cher,
VEDAsoft,
http://zx.oberon2.ru=>

Dear Oleg,
Thanks for your email!

I've now checked the issue and due to this is a product we do not longer support we can offer you an PC locked license of EWZ80 version 4.06 ( from the year 2001) without support.

For the amount of 1715 EUR
Payment: In advance

Please do check if this version would be ok and also if you would need any further information or would like to place an order.

Best regards,
Lise

Liselott Lundeborg Sales Manager Sweden - Key Account Manager Nordic
IAR Systems AB
Box 23051, Strandbodgatan 1
SE-750 23 Uppsala, SWEDEN
Mobile: +46 708 66 10 51 Phone: +46 18 16 78 36 Fax: +46 18 16 78 01
Website: www.iar.com
Twitter: www.twitter.com/iarsystems

aviator
05.01.2017, 11:13
Классный ценник. Да за такие деньги можно написать свой компилятор, "с шаблонами и сборщиком мусора". Мда...

Oleg N. Cher
05.01.2017, 16:31
Разработать эффективный оптимизирующий компилятор Си не так легко. Команда SDCC усиленно работает уже долгий срок, Филипп Краузе, разработчик бэк-энда для Z80, делает коммиты чуть ли не каждый день. Я слежу за этим проектом уже много лет, и конечно не буду позиционировать его как идеал, но, как разработчик, я с большой симпатией отношусь к открытости и безплатности компилятора SDCC. Также весьма хорош z88dk, его команда смогла сделать много чего, что не умеет SDCC. Тоже делается уже долго. И оба эти компилятора хорошо влияют на разработку друг друга.

Bedazzle
05.01.2017, 16:33
Классный ценник. Да за такие деньги можно написать свой компилятор, "с шаблонами и сборщиком мусора". Мда...

Что ж никто не пишет? :)
Просто посчитаем - возьмём с потолка стоимость одного дня работы в 30 евро => 57 дней, т.е. за три месяца неспешно можно сделать.
/голосом Станиславского/ ой, не верю!

Берём стоимость одного дня в 90 евро => 19, один рабочий месяц.
Это и дизайн системы, и код, и отладка багов.
Ой, не верю!

aviator
05.01.2017, 17:14
Берём стоимость одного дня в 90 евро => 19, один рабочий месяц.
Это и дизайн системы, и код, и отладка багов.
Ой, не верю!
На базе LLVM например. Почему бы и нет. Фронтенд - подмножество Си, модифицируем существующий. Бэкэнд - пишем. Зачем писать всю инфраструктуру с нуля?
А EWZ80 "отбился" по деньгам уже давно. Но всё равно цену будут задирать. Это есть "кровавый энтерпрайз"...

Sayman
05.01.2017, 18:43
Также весьма хорош z88dk
можно более подробно, что там хорошего? а то я беру один и тот же сорец и не вижу разницы в компиляции между тем, что компилит версия скачанная с сорсфоржа (за 15й год) и тем, что там в ночных сборках. в результате я получаю такой же мегамедленный и раздутый код. не понимаю, я что-то не так делаю?

Alcoholics Anonymous
05.01.2017, 20:54
На базе LLVM например. Почему бы и нет. Фронтенд - подмножество Си, модифицируем существующий. Бэкэнд - пишем. Зачем писать всю инфраструктуру с нуля?
А EWZ80 "отбился" по деньгам уже давно. Но всё равно цену будут задирать. Это есть "кровавый энтерпрайз"...

1700 евро не намного больше, чем за неделю до двух заработной платы недели для опытного программиста.

LLVM не очень хорошо подходит для генерации программ для 8-битных целей, как есть. Много работы было бы сделать, чтобы получить что-то хорошее из него. Вы можете взять его (и я надеюсь, что вы делаете!), Но есть причина, почему LLVM-z80 связанные проекты томился в течение многих лет.


1700 Euro is not much more than a week to two week's wages for an experienced programmer.

LLVM is not well suited to generating programs for 8-bit targets as-is. A lot of work would have to be done to get something good out of it. You are welcome to take it up (and I hope you do!) but there is a reason why LLVM-z80 related projects have languished for years.



можно более подробно, что там хорошего? а то я беру один и тот же сорец и не вижу разницы в компиляции между тем, что компилит версия скачанная с сорсфоржа (за 15й год) и тем, что там в ночных сборках. в результате я получаю такой же мегамедленный и раздутый код. не понимаю, я что-то не так делаю?

Инструменты и библиотеки гораздо более разнообразны и настраиваемый в z88dk - есть не только одна команда компиляции.

Всегда используйте ночную сборку (http://nightly.z88dk.org/). Проект очень активен, так что частые обновления. Установить инструкции здесь (https://www.z88dk.org/wiki/doku.php?id=temp:front#installation). При загрузке окна или OSX строит, они включают в себя zsdcc двоичные файлы; Для Linux вам придется скомпилировать zsdcc от источника, если вы хотите использовать SDCC.

Существует технический обзор того, как новая часть z88dk работает здесь (https://www.z88dk.org/wiki/doku.php?id=libnew:target_embedded). Это для встроенной цели, то есть общий Z80 машина, на которой построен целевой спектр. Хотя для компиляции спектра немного по-другому, понятия, обсуждаемые переносятся.

Библиотека и драйверы настраиваются на линии компиляции так, чтобы получить минимально возможное бинарное зависит от того, что вы пытаетесь собрать. Если у вас есть тестовая программа, которую вы хотите попробовать, может быть, поделитесь им здесь, так что я могу предложить и объяснить линию компилирования для него.

Эта линия компиляции:


The tools and libraries are much more varied and customizable in z88dk -- there is not just one compile command.

Always use the nightly build (http://nightly.z88dk.org/). The project is very active so there are frequent updates. Install instructions are here (https://www.z88dk.org/wiki/doku.php?id=temp:front#installation). If you download the windows or osx builds, they include zsdcc binaries; for linux you would have to compile zsdcc from source if you want to use sdcc.

There is a technical overview of how the new part of z88dk works here (https://www.z88dk.org/wiki/doku.php?id=libnew:target_embedded). This is for an embedded target, that is a generic z80 machine, on which the spectrum target is built. Although compiling for the spectrum is a little bit different, the concepts discussed carry over.

The library and drivers are customizable on the compile line so to get the smallest possible binary depends on what you are trying to compile. If you have a test program you want to try, maybe share it here so I can suggest and explain a compile line for it.

This compile line:


zcc +zx -vn -startup=31 -clib=sdcc_iy -SO3 --max-allocs-per-node200000 --opt-code-size test.c -o test -create-app --list


компилирует "test.c" в файл .TAP с использованием SDCC, как компилятор с оптимизацией оказалось высоким. "startup = 31" выбирает лучевую трубку без Printf / Scanf водителей, "SO3" включает агрессивные правила глазок "opt-code-size" позволяет правила сокращения размера кода, которые особенно эффективны для кода с использованием 32-битного INT / 64-бит INT / поплавки (также попробовать без него, особенно для маленьких программ), "create-app" просит z88dk сделать файл .TAP, "list" просит, чтобы показать с исходные файлы переведены на ассемблере (она будет создавать "test.c.lis"). Если вы делаете поплавки, добавьте "-lm". Изменить "-vn" на "-v", чтобы увидеть все шаги ZCC принимает для компиляции программы.

Если вы хотите, чтобы остановить при сборке перевода, добавить "-a":


will compile "test.c" to a .tap file using sdcc as compiler with optimization turned high. "startup=31" selects a crt without printf/scanf drivers, "SO3" turns on aggressive peephole rules, "opt-code-size" enables code size reduction rules which are particularly effective for code using 32-bit int/64-bit int/floats (also try without it especially for small programs), "create-app" asks z88dk to make a .tap file, "list" asks to show the c source files translated to asm (it will create "test.c.lis"). If you are doing floats, add "-lm". Change "-vn" to "-v" to see all the steps zcc is taking to compile the program.

If you want to stop at assembly translation, add "-a":


zcc +zx -vn -a -startup=31 -clib=sdcc_iy -SO3 --max-allocs-per-node200000 --opt-code-size test.c

Я нахожу полученный ASM файл "test.c.asm" более удобным для чтения. Это хорошее место, чтобы исследовать разрастание кода.

Выходной двоичный для приведенного выше составляет около 508 байт. То есть, потому что есть куча инициализации там, код вставляется для успешного возвращения в основной и так далее.

Если добавить следующие прагмами в верхней части файла test.c:


I find the resulting asm file "test.c.asm" more readable. This is a good place to investigate code bloat.

The output binary for the above is about 508 bytes. That is because there is a heap initialization in there, code is inserted for successful return to basic and so on.

If you add the following pragmas to the top of your test.c file:


#pragma output REGISTER_SP = -1 // do not change the value of SP at startup
#pragma output CRT_ON_EXIT = 0x10001 // on program exit, enter an infinite loop
#pragma output CLIB_MALLOC_HEAP_SIZE = 0 // do not create a heap for malloc
#pragma output CLIB_STDIO_HEAP_SIZE = 0 // do not create a heap for stdio FILE*
#pragma output CLIB_FOPEN_MAX = -1 // no FILEs can be created

не изменяет значение SP при запуске
при выходе из программы, войти в бесконечный цикл
не создают кучу для malloc
не создают кучу для STDIO FILE*
ни один файл не может быть создан

вы будете уменьшить размер кода дополнительно. (Смысл прагмах описан здесь (https://www.z88dk.org/wiki/doku.php?id=libnew:target_embedded#crt_configurati on) и здесь (https://www.z88dk.org/wiki/doku.php?id=libnew:target_embedded#printf_and_scan f_configuration)).

С этим добавил, выходной двоичный составляет около 66 байт.



you will shrink the size of the code further. (The meaning of the pragmas is described here (https://www.z88dk.org/wiki/doku.php?id=libnew:target_embedded#crt_configurati on) and here (https://www.z88dk.org/wiki/doku.php?id=libnew:target_embedded#printf_and_scan f_configuration)).

With these added, the output binary is about 66 bytes.

NEO SPECTRUMAN
05.01.2017, 22:39
1700 Euro is not much more than a week to two week's wages for an experienced programmer.
Не знаю как там у канадских программистов...
А вот простым смертным из Украины придется не есть не пить и не платить за свет, за газ на протяжении одного года, чтоб купить это...

aviator
05.01.2017, 23:08
1700 Euro is not much more than a week to two week's wages for an experienced programmer.
But not in the Russia... For example, I'm lead software developer and architecture developer (with more than 10 years experience in industry automation). My salary is about 800 in USD equivalent per month before taxes. And this is above average salary level for my city!

- - - Добавлено - - -

Ладно, завязываем с оффтопиком.
Если честно, я порывался что-то сделать с софт-ядром Z80 и кросс-компиляторами под него, но каждый раз меня неумолимо тянет в сторону ARM...
Навряд ли можно сделать хороший универсальный оптимизатор, в чём то он будет выигрывать, в чём-то проигрывать...

Oleg N. Cher
06.01.2017, 01:48
But not in the RussiaAnd not for Ukraine! Alcoholics Anonymous, d'ya understand? This price angers us, we feel black slaves!


можно более подробно, что там хорошего?Ну, нам Alcoholics Anonymous рассказывает чудеса про его более компактные, чем в SDCC, библиотеки и поддержку различных Z80-based архитектур из коробки. Я не пользовался, так что рассуждаю только на основе его слов. Также есть адаптированный (патченный) SDCC для вызова из z88dk, и даёт, по словам Alcoholics Anonymous, лучший код, чем генерит сам SDCC. Опять же, не проверял. Только видел результаты тестирования, они действительно впечатляют. Ссылка на сравнительные тесты разных компиляторов для Z80 (https://www.z88dk.org/wiki/doku.php?id=temp:front#sdcc3).


SDCC targets a variety of 8-bit mcus and comes with a subset of the C library that is expected by embedded systems. Its library is written in C which makes it portable across all its targets but that comes at the expense of code size and speed. It sticks to vanilla C and a generic target so there is no mechanism to build for specific z80 systems. Nevertheless the quality of code generated by the compiler is comparatively of high for the z80 (and probably others too). The main selling point of sdcc is quality code generation and modern standards compliance (most C89, much C99, some C11).

Z88DK is a development kit that specifically targets the z80. Ostensibly it provides the same sort of facilities. However it comes with a C library that tries to be complete and is written in assembly language. It's probably close to ten times larger than sdcc's and is a few times smaller and faster. Its C compiler (sccz80) is small-C derived although most of the restrictions of small-C have been eliminated (it supports floats, longs, ansi, etc and approaches C89 compliance with some notable omissions). sdcc's compiler generates faster code but until recently it has also been larger code. sccz80 has always been intended to generate small code with speed gains achieved through the hand-written library functions. z88dk has a mechanism to target specific z80-machines so that the same source code can be compiled for cp/m, zx spectrum or rc2014 with a change in compiler switch. The libraries do not confine themselves to the standard and there are many additions to do with sound, graphics, compression and so on whose availability depends on the target. The main selling point of z88dk is its comprehensive libraries and ease of use.

In the past year there has been cross-pollination between the two projects. Into sdcc went some of z88dk's calling conventions. Into z88dk went sdcc-z80 :)

So now z88dk can use either sdcc or sccz80 as c compiler. z88dk uses a patched version of sdcc-z80 that improves its generated code (5-40% size reduction depending on the source code -- a more likely number is 5-10% ; the 40% comes from frequent use of floats, longs and longlongs) and addresses some of sdcc's code generation bugs. sdcc is used to translate to asm only and then that output is plugged into z88dk's back end. This allows sdcc to use z88dk's more complete machine language C libraries and its crts so that it's simple matter to compile for eg, an rc2014, cp/m or a zx spectrum using the same source code by employing a different command line switch.

In short, the z88dk/sdcc combination puts together the best of both projects and is available through z88dk.

Ага, вот ещё нашёл:

http://zx-pk.ru/threads/24869-churrera-dvizhok-dlya-sozdaniya-igr.html?p=789011&viewfull=1#post789011


Все составляется C будь SDCC, sccz80 (составитель z88dk в), или любой другой известный компилятор z80 C генерирует код, который является по меньшей мере в три раза больше и в три раза медленнее, чем писаные ассемблере.

Точка z88dk является доступность существенной библиотеку ассемблерных подпрограмм, так что C используется в основном как клей ("бизнес-логики"). Большинство время выполнения затем провел в быстром ассемблере и размер программы значительно сокращается, поскольку большая часть его написана на ассемблере.

Это страница с использованием C код для встраивания в QSort и рисование линий, например, когда z88dk содержит QSort и рисования линий функции, написанные на ассемблере. Если те, которые используются z88dk версия в несколько раз быстрее и меньше, чем SDCC.Гм, выглядит как будто бы в SDCC нельзя использовать эту быструю процедуру, взятую из z88dk?


Но sccz80 не оптимизирующий компилятор, как SDCC так, что размер кода преимущество может произойти, только если программист осознает, что может привести к sccz80 получать большие код.

Мой вердикт: берём SDCC и побольше кода из библиотек z88dk. Осторожненько щупаем версию SDCC, адаптированную для вызова из z88dk. Ругаем политику компании IAR. =)

Sayman
06.01.2017, 05:36
Oleg N. Cher, мне во всём этом не понятно два момента:
1. почему нужно использовать 2 компилятора (и ловить в 2 раза больше косяков потом)
2. почему разрабы не объединят усилия для создания одного быстрого и оптимального компилятора, чтобы избавить пользователей от подобных костылей?
если либы у z88dk столь оптимизированные, ну тогда переносить их изначально надо под sdcc. сам по себе, как самостоятельный компилятор, z88dk весьма слабый. а использовать его чисто для вызова sdcc это тот ещё костыль, на мой взгляд. я ни когда не прибегал и не прибегну к такому мазохизму. да и сам sdcc тоже весьма не самый оптимальный вариант. посмотри на evo sdk. он базируется на sdcc версии 2.9.0. если в него засунуть последние билды и попробовать собрать хоть что-то из проектов, то ты словишь пачку варнингов и ошибок там, где их быть не может и не должно. и сами проекты собираться начинают по несколько минут. порт Digger`а у ВБИ собирается около 10 минут последним sdcc, жескачь какой то.
а вот хайтех. который ты так сильно недолюбливаешь, собирает весь этот код за 5 секунд)))

Oleg N. Cher
06.01.2017, 06:46
Oleg N. Cher, мне во всём этом не понятно два момента:
1. почему нужно использовать 2 компилятора (и ловить в 2 раза больше косяков потом)В принципе, незачем. Я использую только SDCC. Но смысл ещё в том, что почему-то дёргаемый из z88dk SDCC даёт лучший код, видимо, за счёт дополнительных условий для щелевого оптимизатора. Не интересно? Не юзай.


2. почему разрабы не объединят усилия для создания одного быстрого и оптимального компилятора, чтобы избавить пользователей от подобных костылей?У них могут быть различные цели и взгляды на разработку. А может быть и личные амбиции. Sayman, есть транслятор Ofront - Оберон-2 в Си, кроме оригинального, авторского, имеется мой Ofront+. Пришлось начать свою ветку, сначала для того, чтобы иметь возможность использовать Ofront с SDCC, потом убедился, что Йозеф Темпл не приемлет предлагаемых мною фич просто потому, что он не любит дополнять проекты ненужными ему лично фичами. Например, его версия пасторальна и всё ещё не работает под 64 битами. Ну вот он такой чел, не любит париться понапрасну и усложнять себе жизнь. Второй клон Ofront'а - voc - разрабатывает команда, которая не только не желает поддержки моих фич, т.к. очень консервативна, и не желает изменять и дополнять входной язык, даже на уровне системных возможностей (которые стандарт не ограничивает). Но она смотрит в сторону диалекта Оберон-07, который настолько минимален, что даже многие оберонщики на него морщатся.

Подобные же взгляды могут быть и в команде SDCC.

А ты сам почему не хочешь присоединиться к проекту SDCC, раз все должны объединиться на благо создания нового компилера? Дай угадаю. Ты им не пользуешься, тебя задолбали баги и тебе вообще всё это нафиг сплющилось. Ну бывает. Но тогда нефиг предлагать всем компилерописателям "сплотиться", потому что тебе пришла такая светлая мысль. Захочут - сплотятся. ;-)


если либы у z88dk столь оптимизированные, ну тогда переносить их изначально надо под sdcc.Переноси, если тебе нужно. Филиппу Краузе, например, вообще начхать на поддержку конкретных Z80-based компьютеров, не говоря уже о Спектруме. Он вообще фанат Coleco Vision.


сам по себе, как самостоятельный компилятор, z88dk весьма слабый. а использовать его чисто для вызова sdcc это тот ещё костыль, на мой взгляд.Ну, это придумал не я. Это решение команды z88dk, с помощью которого они получили ту оптимизацию, которую, возможно, никогда не реализуют сами. У каждой команды разработчиков свои возможности, не все обладают ярко выраженными талантами для написания оптимизирующих компиляторов, а я снимаю шляпу хотя бы за то, что их проект на плаву. Если помнишь, компилятор Паскаля от Андрея Шарина тоже обещал быть оптимизирующим, но что-то давно не было обновлений, а код, им продуцируемый, мягко говоря, оставляет желать много лучшего.


я ни когда не прибегал и не прибегну к такому мазохизму. да и сам sdcc тоже весьма не самый оптимальный вариант. посмотри на evo sdk. он базируется на sdcc версии 2.9.0. если в него засунуть последние билды и попробовать собрать хоть что-то из проектов, то ты словишь пачку варнингов и ошибок там, где их быть не может и не должно.Давай конкретнее. Что именно перестало поддерживаться? Ты хочешь сказать, что злобные разрабы меняют стандарт языка Си по ходу дела? И вообще. Любой проект можно поддерживать для свежего компилятора, а можно остановиться на старом, это вопрос взглядов на разработку, бывают консервативные. Но это не аргумент. Компилятор не развивается? Плохо. Развивается? Опять плохо, потому что не остаётся неизменным. Ты определись, что для тебя лучше. И пользуй старую версию, либо же нет.


и сами проекты собираться начинают по несколько минут. порт Digger`а у ВБИ собирается около 10 минут последним sdcc, жескачь какой то.Млин, уже в третий раз говорю: пихать всю игру в одну простыню это отстой. Там идёт долгая кодогенерация из-за поиска оптимального размещения данных в регистрах. Не доходит до тебя это? Есть опция, снижающая эффективность этого показателя и повышающая скорость компиляции. Есть старый регистровый аллокатор. Всё это прекрасно годится для отладочных и промежуточных сборок.


а вот хайтех. который ты так сильно недолюбливаешь, собирает весь этот код за 5 секунд)))А под хайтех, который я так сильно недолюбливаю, переделать код ещё сложнее, чем со старой версии SDCC на новую. Там много чего вообще иначе, и передача параметров, и многое другое. Он не умеет генерить код, который не трогает регистр IY. Он неэкономно передаёт параметры (даже однобайтовые - всегда в двух байтах). Там нету поддержки различных моделей вызова. И т.д. и т.п.

Sayman
06.01.2017, 07:52
А под хайтех, который я так сильно недолюбливаю, переделать код ещё сложнее, чем со старой версии SDCC на новую.
ну ОК, давай про версии компиляторов. у меня есть тут парочка проектов под фряху, писал когда то давно, под гцц конечно, пара консольных утилит для себя делал. почему то от версии к версии самого гцц мне исходник править не требуется. он что в 6.2 собирается, что в девятке - одинакого.
под VS2005 тоже было парочка проектов небольших (ещё по теме профика и там с sdl мелочь была). почему то оно собирается одинаково легко и без правок на 2005 и на 2013й VS.
ЧЯДНТ? почему мои исходники при переходе на новые версии компиляторов не требуют исправлений? почему мои исходники на си писанные под z80 при сборке на sdcc каждый раз нужно тратить время и искать причину ошибок и править исходник? и это без различных асмовых вставок, чистый си исходник. почему я беру тот же не работающий кусок кода и он собирается на старом хайтехе, который вообще под цпм был писан?

Там много чего вообще иначе, и передача параметров
каких параметров? аргументов в функции? передача аналогична любому компилятору для z80 - через стек.

н не умеет генерить код, который не трогает регистр IY.
серьёзно? странно, у меня только ix гоняет в хвост и гриву. iy начинает гонять только когда объявляю register на какую то переменную и то не всегда. регистр А для 8бит. hl для 16 бит, но может и iy использовать. зависимости тут я не выловил. но в целом, если не гонять register, то iy простаивает.

Он неэкономно передаёт параметры (даже однобайтовые - всегда в двух байтах).
а вот это уже вопрос вкуса - кому то это не экономно, а кому то лишние inc sp не экономно (а именно так sdcc и передаёт 8ми битные аргументы стэком, может посчитаем, как оно более оптимально по тактам передавать, просто на стек кинув значение или кинуть да ещё и стэком отдельно крутить?) мне 1 байт не впадлу со стэка отдать, у меня памяти не 48кб, не жалко.

Там нету поддержки различных моделей вызова.
это типа которые __чего-то-там_fast_callee__? вот от сюда, в том числе, баги и ошибки при компиляции так же плодятся. от версии к версии условия передачи аргументов меняются, сиди потом сам разыскивай причины ошибок.

вообще начхать на поддержку конкретных Z80-based компьютеров
вот с этого и надо было начинать. а теперь вспомни свои высказывания на тему, что хайтех давно никем не поддерживается. вот и автору sdcc тоже наплевать на эту поддержку по теме z80. об чём тогда разговор. не понятно?
sdcc конечно может выдать вменяемый код, местами, временами. но сопутствующие затраты в итоге всё портят.
для затравки - ядро uzix для Ориона собирается примерно 3 секунды. тот же самый код на sdcc ты никогда не собирёшь! а после правок оно будет собираться минут 5. если, как ты советуешь, убрать все оптимизации дабы ускорить сборку, то в результате получается настолько медленный и раздутый код, что с ним по тормозности может сравниться только древний компилятор Aztec 1.05 (1.06).

aviator
06.01.2017, 09:28
Вот поэтому и надо отталкиваться от стандарта ANSI C90 или более привычного C99 (О C1X не говорю, так как там в основном плюшки для современных архитектур). А все нестандартные расширения - в топку.

Alcoholics Anonymous
06.01.2017, 10:28
And not for Ukraine! Alcoholics Anonymous, d'ya understand? This price angers us, we feel black slaves!


I more meant that the price is not so outrageous considering IAR's development is done in the west where the costs are higher. But yes I understand what you are saying. 1700 euros is way more than what I would pay for a z80 compiler too :)


Oleg N. Cher, мне во всём этом не понятно два момента:
1. почему нужно использовать 2 компилятора (и ловить в 2 раза больше косяков потом)
2. почему разрабы не объединят усилия для создания одного быстрого и оптимального компилятора, чтобы избавить пользователей от подобных костылей?
если либы у z88dk столь оптимизированные, ну тогда переносить их изначально надо под sdcc. сам по себе, как самостоятельный компилятор, z88dk весьма слабый. а использовать его чисто для вызова sdcc это тот ещё костыль, на мой взгляд. я ни когда не прибегал и не прибегну к такому мазохизму. да и сам sdcc тоже весьма не самый оптимальный вариант.

Существует больше компилятора, чем просто компилятор. Существует передний конец, который делает использование компилятора легко, сам компилятор, библиотеки, ассемблер / линкер / библиотекарь и выходная мощность генератора. Все эти вещи являются независимыми. С точки зрения размера кода и производительности, это не компилятор, который имеет наибольшее влияние - это библиотеки. Все программы подчиняются 20-80 правило, которое означает, что 20% кода выполняет 80% времени. Если вы можете сделать что 20% кода очень эффективно, ваша программа будет хорошо работать. Вот почему мы пишем библиотеки в машинном коде, а не С. Вот почему вы пишете спрайт двигатель в играх в машинном коде, а не С.

В сравнении между SDCC и z88dk, z88dk имеет гораздо более передний конец, его библиотеки гораздо лучше, ассемблер / линкер / библиотекарь сравнима (я предпочитаю стандартные Z80 опкоды в z80asm, но это на самом деле не материал), то выходная мощность генератора делает не существует в SDCC (выход генератора принимает выходные двоичные файлы и обрабатывает их в форме, требуемой цели, например, делая .TAP для спектра, .sms для мастер-системы Сега, .ihx для встраиваемых систем и т.д.). Это C компилятор SDCC, что интересно.

Эти части являются независимыми. Это означает, что мы можем заменить одну библиотеку с другим (и мы, есть два C библиотеки в z88dk), один компилятор с другой (мы делаем, есть два компилятора C). В настоящее время мы экспериментируем с лязгом / LLVM в качестве третьего компилятора C (мы можем компилировать .TAP с лязгом сейчас, но некоторые ручное вмешательство необходимо и качество кода не так хорошо, как SDCC или sccz80) и если кто-то приходит с компилятор мы бы с удовольствием подключи, что один в тоже. Более интересным для нас, чем лязг / LLVM для компиляции C использует LLVM для компиляции других языков, как Fortran и Pascal. Тогда мы получим те использовать код библиотеки C и дополнить, что с дополнительными функциями, необходимыми этими языками. z88dk представляет собой комплект разработки для Z80 компьютеров не только компилятор Си.

Что касается SDCC, его библиотека C является минимальным и написан на С, что делает его медленным и большой. Есть много вещей, отсутствует из библиотеки SDCC. Например нет понятия FILE и вся зсапЕ сторона STDIO отсутствует. Для z80, библиотека имеет реализации машинного кода 16 и 8 бит математике, а также около 4-5 важных функций из string.h (тетсру, зЬгсру, ..). Мне очень нравится тот факт, Филипп повернулся тетсру и несколько других в встроенные модули (код будет встраиваемыми, а не призван к подпрограмме). Эти вещи будут выполнять хорошо и очень важны в программах на языке Си в целом. После того, как вы выходите из этого, вы увидите проблемы с производительностью. 32-битная математика примерно в 1,7 раза медленнее, чем z88dk. 64-битная математика движется к 3x медленнее, чем z88dk. Поплавки 3x медленнее, чем z88dk и в результате на 40% больше кода. Такого рода сравнение будет пронизывать через всю библиотеку. Не является недостатком компилятора - это недостаток библиотеки, которая не зависит от компилятора.

Существует причина, почему библиотека SDCC написана на C. SDCC цели 7 или 8 различных микропроцессоров. Библиотека написана на C означает, что он является портативным для всех 8 из этих процессоров. Потому что есть только одно тело кода реализации библиотеки, есть только одно тело кода для поддержания. SDCC никогда не будет принимать процессор конкретной библиотеки в SDCC как библиотеку z80 z88dk в. Они потребуются специалисты в каждом процессоре, чтобы поддерживать каждую отдельную библиотеку. Библиотеки больше не будут одинаковыми для каждого процессора - некоторые процессоры будут лучше поддерживается, чем другие, и людей, использующих SDCC бы труднее использовать для различных целевых процессоров, поскольку они должны будут изучать различные библиотеки. Причуды каждого из них, уровень поддержки для каждого из них.

SDCC также никогда не ориентированы на конкретные архитектуры. Он никогда не будет поддерживать отдельную базу кода для десятков Z80 машин в существовании.

z88dk о делает все вещи, SDCC не хочет делать. Решение не ставить z88dk в SDCC, это поставить SDCC в z88dk.


There is more to a compiler than just the compiler. There is the front end that makes the use of the compiler easy, the compiler itself, the libraries, the assembler/linker/librarian and the output generator. All of these things are independent. In terms of code size and performance, it is not the compiler that has most impact -- it is the libraries. All programs obey the 20-80 rule which means 20% of the code is executing 80% of the time. If you can make that 20% of the code very efficient, your program will perform well. That's why we write the libraries in machine code and not C. That's why you write the sprite engine in your games in machine code and not C.

In comparison between sdcc and z88dk, z88dk has a much better front end, its libraries are much better, the assembler/linker/librarian is comparable (I prefer the standard z80 opcodes in z80asm but that is not really material), the output generator does not exist in sdcc (the output generator takes the output binaries and processes them into a form required by the target, for example making .tap for spectrum, .sms for sega master system, .ihx for embedded systems, etc). It is sdcc's C compiler that is interesting.

These pieces are independent. This means we can replace one library with another (and we do, there are two C libraries in z88dk), one compiler with another (we do, there are two C compilers). We are currently experimenting with clang/llvm as a third C compiler (we can compile to .tap with clang now but some manual intervention is necessary and the code quality is not as good as sdcc or sccz80) and if anyone else comes up with a compiler we'd gladly plug that one in too. More interesting to us than clang/llvm for C compilation is using llvm to compile other languages like Fortran and Pascal. Then we'll get those to use the C library code and augment that with additional functions required by those languages. z88dk is a development kit for z80 computers not just a C compiler.

As for sdcc, its C library is very minimal and is written in C which makes it slow and big. There are many things missing from the sdcc library. For example there is no concept of FILE and the entire scanf side of stdio is missing. For the z80, the library has machine code implementations of 16 and 8 bit math as well as about 4-5 important functions from string.h (memcpy, strcpy,..). I really like the fact Philip turned memcpy and a few others into built-ins (the code will be inlined rather than called to a subroutine). These things will perform ok and are really important in C programs in general. Once you step out of this, you will see performance issues. The 32-bit math is about 1.7 times slower than z88dk. The 64-bit math is heading toward 3x slower than z88dk. Floats are 3x slower than z88dk and result in 40% larger code. This kind of comparison will pervade through the whole library. The is not a shortcoming of the compiler -- this is a shortcoming of the library which is independent of the compiler.

There is a reason why sdcc's library is written in C. sdcc targets 7 or 8 different microprocessors. A library written in C means it is portable to all 8 of those processors. Because there is only one body of code implementing the library, there is only one body of code to maintain. sdcc will never accept a processor-specific library into sdcc like z88dk's z80 library. They would require experts in each processor to maintain each separate library. The libraries would no longer be the same for each processor -- some processors would be better supported than others and people using sdcc would find it harder to use to target different processors because they would have to learn different libraries. The quirks of each, the level of support for each.

sdcc will also never target specific architectures. It will never support a separate code base for the dozens of z80 machines in existence.

z88dk is about doing all the things sdcc does not want to do. The solution is not to put z88dk into sdcc, it's to put sdcc into z88dk.

Oleg N. Cher
06.01.2017, 14:54
Sayman, да... тормоза, ошибки, всё плохо, хайтек рулит немерено... А зачем uzix на Орионе?

Sayman
06.01.2017, 16:13
Oleg N. Cher, а зачем мы вообще под 8 бит что-то делаем?

Oleg N. Cher
08.01.2017, 04:26
Да кто зачем. Думаю, мы получаем радость от этого. Но я, например, не понимаю зачем на 8-битном компе ОС, которая жрёт почти всю память. Разве что посмотреть один раз. Просто это вне области моих интересов.


а вот это уже вопрос вкуса - кому то это не экономно, а кому то лишние inc sp не экономно (а именно так sdcc и передаёт 8ми битные аргументы стэком, может посчитаем, как оно более оптимально по тактам передавать, просто на стек кинув значение или кинуть да ещё и стэком отдельно крутить?)А давай посчитаем. Я просто уверен, что Филипп тщательно продумал варианты, и раз сделал именно так, значит это имеет свои плюсы.

Ты тут ругал лишний INC SP при передаче аргумента, но он экономит байт на стеке. А ты в курсе, что SDCC для передачи двух однобайтных аргументов делает один PUSH, а внутри ф-ции один POP? Твой хвалёный хайтек в этом случае сделает два PUSH и два POP. Это неэффективно. Если будем считать, учти этот случай тоже.

У любого узкоспециализированного решения есть недостатки. Я uzix для Ориона не компилирую. Дурак (65 кб исходника монолитом) для прогоночной сборки собирается SDCC за 15 сек на моём стареньком одноядерном ноуте. Использует несколько модулей, которые не занимают время основной сборки (пересобираются только при их изменении). Плюс две библиотеки - Basic и Laser2, то же самое. Терпимо, сам виноват, надо было не монолитом делать. Да, отладочная сборка даёт 25 кб кода, релизная (с более высокой оптимальностью использования регистров) - 20 кб. Если я вдруг замечтаю заточить собирать всё это хайтеком или иар, понадобится чёртова уйма рутинной работы.

- - - Добавлено - - -


iy начинает гонять только когда объявляю register на какую то переменную и то не всегда.Ты понимаешь разницу между "использует не всегда" и "гарантированно не использует вообще", как SDCC с опцией --reserve-regs-iy? А то можно таких проблем отгребсти, отлавливая непонятное поведение кода, что глюки SDCC покажутся сладким сном. ;-)

Sayman
08.01.2017, 09:57
Oleg N. Cher, этот спор ни к чему не приведёт. каждый сам для себя решает. нужна ему ос на 8ми битной машине или нет. отрицать тот факт. что на многих машинах есть какие-то оси, не имеет смысла. на Орионе уже есть целая шайка разных цпм подобных досов, есть порт юзикса, на мсх есть юзикс, есть мсх дос1 и мсх дос2, есть симбос. на спринтере есть своя дос эстекс. у профи тоже целая свора цпм подобных систем. моё мнение - если у машины памяти от 1 мб и более, то ось должна быть.
касательно компиляторов - про sdcc я лишь указал на то. что он не является столь прекрасным и вкусным. как ты его описываешь. косяки есть, в том числе и у хайтеха (а как же без них). что-то лучше собрать там. что-то тут. собирать какие-либо проекты без применения оптимизаций так же не вижу смысла.
однако я хочу отметить тот факт. что хайтех это ansi c компилятор. к примеру, на msx.org сильно не долюбливают sdcc и z88dk и там привыкли гонять родной ascii c (который вообще K&R) и хайтех. при этом sdcc позиционируется аналогично, как ansi, хотя почему-то начинает ошибки сыпать там, где хайтех согласно стандарта ansi сжирает прекрасно конструкции. при этом есть живой разработчик. которому много кратно указывали на эти ошибки, но воз, как говорится, и ныне там. всё это в сумме лично меня от него отталкивает. хотя вынужден временами им пользоваться. не сказать, что плююсь от него, нет, просто местами он мне сильно портит нервы при поиске косяков (например, не понимаю, почему в xnx у evo sdk при использовании последних билдов sdcc сыпяца ошибки и варнинги на одномерных массивах).
у хайтеха свои гуси, но он, во1х, 80 каких-то годов, т.е. порядочно старше sdcc. во2х, он под цпм (версии для мс доса не использую, т.к. не удобно гонять постоянно dosbox). в 3х, он легко съедает те конструкции, на которых sdcc обычно сваливается. в 4х, если не использовать разные не стандартные фишки sdcc, вроде __naked или __fast_callee чего то там, то sdcc начинает проигрывать в скорости старому хайтеху. в 5х, у хайтеха тоже есть свой оптимизатор. и в 6х, хайтех тоже умеет использовать асмовые вставки и вообще, никто не мешает написать свои функции и процедуры на асме и к ним обращаться.

Oleg N. Cher
08.01.2017, 10:57
моё мнение - если у машины памяти от 1 мб и более, то ось должна быть.Я не знаю, сколько у Ориона памяти :) в моём понимании Орион - это что-то вроде РК86 на проце КР580 с примитивненьким граф. режимом. И, в моём же понимании, Корвет, не говоря уже о машинках на Z80, во многом круче Ориона. Могу ошибаться.


про sdcc я лишь указал на то. что он не является столь прекрасным и вкусным. как ты его описываешь.Ну вообще-то каждый кулик своё болото хвалит, как известно. ;-) К чему привязан, с чем разобрался, с чем связаны приятные тёплые ламповые воспоминания, на чём были сделаны первые шаги и более поздние прорывы - к тому душой и прикипели. Но SDCC реально самый лучший компилятор для встраивания в ZXDev, я не жалею, что использую его. В то же время, никто не мешает прикрутить туда другой компилятор. Может сам займусь этим, но пока хватает SDCC.


что-то лучше собрать там. что-то тут.Во, золотые слова!


собирать какие-либо проекты без применения оптимизаций так же не вижу смысла.Так это же отладочная сборка, прогоночная. Целевая сильно дольше, экономим время. Можно использовать, если без оптимизации хватает памяти. Теоретически для SDCC можно ключик --max-allocs-per-node задрать так сильно, что код будет почти как закодированный вручную ;-) Чем тебе не супер-компиляция. 6 кб кода на оптимизации только по регистрам, это ли не круто. Но зато офигенно долго. Но что же делать, нейронные сети в регистровых аллокаторах для генерации Z80-кода ещё не научились юзать. ;-)


однако я хочу отметить тот факт. что хайтех это ansi c компилятор. к примеру, на msx.org сильно не долюбливают sdcc и z88dk и там привыкли гонять родной ascii c (который вообще K&R) и хайтех. при этом sdcc позиционируется аналогично, как ansi, хотя почему-то начинает ошибки сыпать там, где хайтех согласно стандарта ansi сжирает прекрасно конструкции.Опыт подсказывает, что в стандартах Си есть такие тонкости, про которые не знают даже разработчики Си-компиляторов. Например, в более старых версиях SDCC константные массивы ничем не отличались от обычных неконстантных, даже мувились из одной секции в другую при старте, дублируя данные дважды. Позже эта погрешность была исправлена, но при этом возник спор, который, слава богу, разрешился в правильном и желательном для нас направлении. А одну багу SDCC во фронт-энде (некритичную), которую я зарепортил, Филипп даже не смог исправить, она до сих пор висит наверно. С компиляторами Си всё сложно. Неидеально. Приходится искать компромиссы. Так что всё верно, собираем то тем, то сем. Для винды я плотно сижу на MinGW, иногда поглядывая в сторону новых версий, чего новенького появляется. Но и там есть проблемы, например, с отбрасыванием неиспользуемого кода (не весь отбрасывается). Это практически та же проблема, из-за которой приходится разрезать исходник для компиляции SDCC специальной утилитой, чтобы библиотека смартлинковалась.


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

Кстати, раз хайтех не использует (или использует мало) регистр IY, то, получается, регистр гуляет бесхозный, в то время как его можно было бы использовать для улучшения кода? Как-то нехорошо.

andreyu
08.01.2017, 17:57
почему мои исходники на си писанные под z80 при сборке на sdcc каждый раз нужно тратить время и искать причину ошибок и править исходник?
А можно посмотреть пример такого кода, до и после правки?

Sayman
08.01.2017, 18:43
andreyu, можете в evo sdk заглянуть для примера. это не мой продукт, конечно. но хорошо показывает подобную ситуацию. особенно с xnx и robo.

Alcoholics Anonymous
08.01.2017, 23:50
Он неэкономно передаёт параметры (даже однобайтовые - всегда в двух байтах).


а вот это уже вопрос вкуса - кому то это не экономно, а кому то лишние inc sp не экономно (а именно так sdcc и передаёт 8ми битные аргументы стэком, может посчитаем, как оно более оптимально по тактам передавать, просто на стек кинув значение или кинуть да ещё и стэком отдельно крутить?) мне 1 байт не впадлу со стэка отдать, у меня памяти не 48кб, не жалко.



Я имел обыкновение думать, что это, но после того, как на самом деле пытается это с функции, имеющие более чем один или два параметра я больше не думаю, что это просто дело вкуса.

Я могу вам сказать, что для игры "Piętro Bros" после изменения интерфейса нирванную использовать символы так, чтобы SDCC могли бы объединить два символа в один 16-битное значение в параметрах, размер программы сократился на 400 байт, а код был, вероятно, в целом немного быстрее.

Я покажу вам, почему. Это одна строка C кода, вызывающего в нирване двигателя:


I used to think this but after actually trying this with functions having more than one or two parameters I no longer think it is simply a matter of taste.

I can tell you that for the game "pietro bros" after changing the nirvana interface to use chars so that sdcc could combine two chars into a single 16-bit value in parameters, the program size shrank by 400 bytes and the code was probably overall a little bit faster.

I will show you why. This is one line of C code calling into the nirvana engine:




NIRVANAP_drawT( tmp0 , tmp, hit_col[index_player] );


Если я прототипирование эту функцию принимает "Integer" параметры, как:

extern void NIRVANAP_drawT(unsigned int tile,unsigned int lin,unsigned int col);

генерируемый в одном месте, это было:


If I prototyped this function taking integer parameters as in:
the generated call in one place was this:




ld a,+((_hit_col) & 0xFF)
ld hl,_index_player
add a, (hl)
ld c,a
ld a,+((_hit_col) / 256)
adc a,0x00
ld b,a
ld a,(bc)
ld (ix-3),a
ld (ix-2),0x00
ld hl,_tmp
ld c,(hl)
ld b,0x00
ld hl,_tmp0
ld e,(hl)
ld d,0x00
pop hl
push hl
push hl
push bc
push de
call _NIRVANAP_drawT_callee


Это добавляет до 40 байт и 216 циклов.

Если я прототипирование функцию, принимая мангалов параметры, как:

extern void NIRVANAP_drawT(unsigned char tile,unsigned char lin,unsigned char col);

результат был:


This adds up to 40 bytes and 216 cycles.

If I prototyped the function taking char parameters as in:

the result was:




ld a,(_index_player)
add a,+((_hit_col) & 0xFF)
ld c,a
ld a,+((_hit_col) / 256)
adc a,0x00
ld b,a
ld a,(bc)
push af
inc sp
ld hl,(_tmp - 1)
ld a,(_tmp0)
ld l,a
push hl
call _NIRVANAP_drawT_callee


Это добавляет до 25 байт и 127 циклов. Это совсем немного лучше.

Это с zsdcc (версия z88dk о SDCC), так что SDCC само по себе не так хороша, но она по-прежнему бьет первую версию.


This adds up to 25 bytes and 127 cycles. That's quite a bit better.

This is with zsdcc (z88dk's version of sdcc) so sdcc itself is not quite as good but it still beats the first version.

Smalovsky
10.01.2017, 21:29
Sayman, можешь написать что используешь дляхайтека на цп/м? Геттинг стартид какой.

Sayman
11.01.2017, 07:23
Smalovsky, для запуска компилятора под вендой я использую такой консольный эмулятор цпм: http://www.vector.co.jp/soft/win95/util/se378130.html
он умеет возвращать винде код завершения HitechC, что нужно для make.

Геттинг стартид какой.
что ты имеешь в виду?

Oleg N. Cher
11.01.2017, 08:23
Он имеет в виду мануал для быстрого вруливания в хайтех - что как и за чем делать. Хотя бы на примере ХеллоВорлда - от исходника на Си, пошагово как компилить, как запускать внешний оптимизатор, чуть-чуть тонкостей про ключики. И как получить на выхлопе окончательный сильно оптимизированный бинарь или tap/trd'шку ;-)

Sayman
11.01.2017, 12:15
не. писать мануалы я не буду. можно заглянуть в профильный раздел Ориона. там есть тема про uzix. там есть архив описание как что собирать и есть make файл. опять таки, есть мануал на буржуйском на сам компилятор.

Sayman
21.05.2018, 13:12
Решил на свою голову замутиться парой програмулек на sdcc 3.6.0. в процессе написания натолкнулся на некий неописуемый баг. решил, для теста написать просто пустой си файл с одной main функцией и одной строкой, в ней и проблема:


void main()
{
int a;

a = 400;
}


компилю и вижу строки в asm файле:



; ---------------------------------
; Function main
; ---------------------------------
_main::
;test3.c:28: a = 400;
ret
.area _CODE
.area _INITIALIZER
.area _CABS (ABS)

приехали! эт как? что делать с этим? писал писал, в итоге всё коту под хвост...

Shiny
21.05.2018, 13:22
sdcc похуже z88dk

Bolt
21.05.2018, 13:41
в процессе написания натолкнулся на некий неописуемый баг. решил, для теста написать просто пустой си файл с одной main функцией и одной строкой, в ней и проблема:
...
писал писал, в итоге всё коту под хвост...
Это не баг, это фича. Переменная не используется, поэтому оптимизатор её удалил.

Error404
21.05.2018, 16:04
sdcc похуже z88dk

Но z88dk вроде бы не С ANSI (и даже не K&R) а его некое подмножество, поскай и весьма С-подобное? Т.е. не может считаться инструментом кроссплатформенного портирования (а в-основном за этим и нужен С на Z80, ведь писать на нем с нуля серьезные вещи вряд ли кто-то станет)

Smalovsky
21.05.2018, 16:19
Вообще, я раньше был фаном си, но когда не смог закончить игру, то начал писать на барсике и все ок! А си для меня стал *****м...))

Shiny
21.05.2018, 16:39
Но z88dk вроде бы не С ANSI (и даже не K&R) а его некое подмножество, поскай и весьма С-подобное?

да это фейл вообще - берешь сырок и подгоняешь под анси-неанси стандарт. Итог - ты становишься адептом Си.


а в-основном за этим и нужен С на Z80, ведь писать на нем с нуля серьезные вещи вряд ли кто-то станет

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

Sayman
21.05.2018, 20:02
разобрался с ошибкой. сам виноват, портил в паре место регистр ix, из-за этого местами слетали переменные. а я думал, что компилятор тупо их игнорит.

Oleg N. Cher
21.05.2018, 20:46
А я даже не сомневаюсь, что вот такие бочки на Си-компайлер часто катят не разобравшись. И сам грешен тем же)

Да, IX портить нельзя. Там выбрана грамотная стратегия - IX юзается для адресации локальных переменных. Компилер не сохраняет его перед вызовом каждой процедуры, и правильно делает. Считается, что процедура должна сама позаботиться об этом.

Многие встречаемые мною программисты для Z80 не в курсе этого. Так что нелишне напомнить.

SfS
23.05.2018, 04:31
Да, IX портить нельзя. Там выбрана грамотная стратегия - IX юзается для адресации локальных переменных. Компилер не сохраняет его перед вызовом каждой процедуры, и правильно делает. Считается, что процедура должна сама позаботиться об этом.

Эта "стратегия" привела к невозможности нормальной реализации вызова типа void *alloca(size_t size); для резервирования места на стеке.

Oleg N. Cher
23.05.2018, 19:57
Не согласен. Думаешь, если бы компилер тупо всегда сохранял IX, было бы лучше? Уж лучше умная ф-ция сама об этом позаботится.

alloca, насколько мне известно, в Си для Z80 нет. А если бы была, она была бы конечно написана в машкоде и могла бы в начале своей работы положить в стек дополнительный адрес возврата, который бы при выходе из функции вызвал освобождение памяти, как и задумано.

Раз уж об этом зашла речь, SfS, уж не обессудь, я всё-таки скажу то, что собирался. В твоём проекте SDCC noinit очень топорно устроена работа с аргументами функций. Вот это нехорошо:


void pt3Init(void* mod_adress)__naked{
__asm;
ld hl,#2
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
inc hl

ex de,hl

push ix
call pt3xplayer_init+3
pop ix
ret
__endasm;
}Надо так:


void pt3Init(void* mod_adress)__naked __z88dk_callee{
__asm
pop hl
ex (sp),hl
push ix
call pt3xplayer_init+3
pop ix
ret
__endasm;
}

И если бы это был единичный случай. А вот это ещё хуже:


void spr0_out0(const Sprite0* adr, BYTE x, BYTE y)__naked{
__asm;
push ix
ld ix,#4
add ix,sp
;// adr
ld e,0(ix)
ld d,1(ix)
;// x
ld l,2(ix)
;// y
ld h,3(ix)
...
__endasm;
}Надо так:


void spr0_out0(const Sprite0* adr, BYTE x, BYTE y)__naked __z88dk_callee{
__asm
pop hl ; Адрес возврата
pop de ; Если порядок регистров при снятии аргументов не совсем подходящий
; Всё равно пересылки между регистрами очень дёшевы, в отличие от индексных
ex (sp),hl ; Возвращаем адрес возврата на стек

; Сейчас у нас в hl и de все аргументы
...
__endasm;
}

- - - Добавлено - - -

Кстати, вот это:

void pt3Init(void* mod_adress)__naked __z88dk_callee{
__asm
pop hl
ex (sp),hl
push ix
call pt3xplayer_init+3
pop ix
ret
__endasm;
}Можно переписать ещё короче:


void pt3Init(void* mod_adress)__naked __z88dk_fastcall{
__asm
; Аргумент уже в HL
push ix
call pt3xplayer_init+3
pop ix
ret
__endasm;
}

Sayman
24.05.2018, 06:17
И если бы это был единичный случай. А вот это ещё хуже:

Код:
void spr0_out0(const Sprite0* adr, BYTE x, BYTE y)__naked{
__asm;
push ix
ld ix,#4
add ix,sp
;// adr
ld e,0(ix)
ld d,1(ix)
;// x
ld l,2(ix)
;// y
ld h,3(ix)
...
__endasm;
}

это легко меняется на это:



ld hl,#2
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
inc hl
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
push ix

И вообще, подобные вещи лучше сразу на асме писать и заворачивать в lib файл. если хочется указать компилятору, что функция naked, то в прототипе это можно указать, а можно не указать, что при написании функции на асме является не обязательным (или не является обязательным).
Олег, не рекомендуй человеку багованные конструкции. обрати внимание, что твои конструкции вида pop hl:ex (sp),hl не работают с однобайтными переменными/аргументами.

SfS
24.05.2018, 07:10
В SDCC нет отличий - в отдельном файле делать функции на асме или делать __naked-функцию.

Я много чего в рамках освоения SDCC делал и переписать все либы разом врядли смогу. Хотя много чего требует оптимизации.

Примеры с ex (sp),hl будут работать некорректно, так как вызывающая функция будет думать, что на стеке 4 байта, а не два (параметр мы сняли). И освободит 4 байта. Будет плохо. Пробовал.
В языке С при вызове функций память резервируется и освобождается вызывающей функцией. И ей всё равно, что происходит в вызываемой. Запихала параметры, (SP=SP+размер параметров) вызвала функцию, сняла параметры (SP=SP-размер параметров). Всё.
В вызывающую функцию ты вернёшься после pop hl: ex (sp),hl. А вот потом начнутся чудеса:)

Oleg N. Cher
24.05.2018, 15:52
Sayman, вот это:


ld hl,#2
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
inc hl
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
push ix
легко меняется на это:



pop bc
pop hl
pop de
push de
push hl
push bc
push ixПосчитай такты сам. И то, если лениво по каким-то причинам юзать модель __z88dk_callee, которая заслуживает всяческого уважения.


Олег, не рекомендуй человеку багованные конструкции. обрати внимание, что твои конструкции вида pop hl:ex (sp),hl не работают с однобайтными переменными/аргументами.SDCC юзает для выравнивания стека в подобных случаях INC SP/DEC SP. Поэтому я против термина "багованные конструкции", он тут абсолютно неприменим. А если ты не снимаешь аргументы со стека, то и это без разницы. Просто аргумент ляжет в другой регистр из пары.

Юзать IX в качестве указателя на аргументы иногда тоже есть смысл, но только если обращение к ним происходит глубоко в теле подпрограммы помногу раз. Как правило, такие случаи встречаются крайне редко. Например, я юзаю подобную адресацию в процедуре NewSupercode.LITERY(SHORTCARD x, SHORTCARD y, SHORTCARD xs, SHORTCARD ys, SHORTCARD wdth, CHAR *str) - здесь много параметров, для них явно не хватает регистров общего назначения.

- - - Добавлено - - -


Примеры с ex (sp),hl будут работать некорректно, так как вызывающая функция будет думать, что на стеке 4 байта, а не два (параметр мы сняли). И освободит 4 байта. Будет плохо.Для стандартной модели вызова - всё так. Но если ты укажешь в прототипе функции атрибут __z88dk_callee, компилятор будет знать, что функция сама снимает свои аргументы со стека. А в случае атрибута __z88dk_fastcall, компилятор вообще не будет использовать стек, только регистр L (или пару HL в случае двухбайтового аргумента).


А вот потом начнутся чудеса:)Всё нормально будет. Читай в доках про флажки __z88dk_callee и __z88dk_fastcall, они реально помогают ускорить работу с аргументами.

- - - Добавлено - - -


Олег, не рекомендуй человеку багованные конструкции.Кстати, я действительно не рекомендую (и не рекомендовал) использовать ex (sp),hl для стандартной модели вызова. Только для __z88dk_callee. Дело в том, что лежащие на стеке аргументы в случае стандартной модели вызова лучше вообще не изменять.

SfS
24.05.2018, 19:24
Спасибо. Про __z88dk_callee и __z88dk_fastcall не разбирал.

Собственно, можно и так, только переделывать дофига. На самом деле, я знаю, что у меня там много не оптимального. Ну и фиг с ним пока что)

- - - Добавлено - - -


А в случае атрибута __z88dk_fastcall, компилятор вообще не будет использовать стек, только регистр L (или пару HL в случае двухбайтового аргумента).

А если аргументов 5 или 6 ? Тогда как?

Shiny
24.05.2018, 19:47
Сишники, а насколько сложно собрать сей исходник?

Oleg N. Cher
24.05.2018, 20:45
> А в случае атрибута __z88dk_fastcall, компилятор вообще не будет использовать стек, только регистр L (или пару HL в случае двухбайтового аргумента).
А если аргументов 5 или 6 ? Тогда как?Модель __z88dk_fastcall сейчас допускает только один аргумент. Что конечно жаль. Я говорил с Элвином по поводу маленько это доработать, но им неинтересно.


Сишники, а насколько сложно собрать сей исходник?Для Спека т.е.? Тут будет более уместным не "собрать", а "переписать заново".

- - - Добавлено - - -

Притом реализуя задействованные процедуры на ассемблере.

SfS
25.05.2018, 04:38
Сишники, а насколько сложно собрать сей исходник?

Ну если всё остальное дашь кроме одного файла - можно и собрать попробовать) Там половины типов нет. Заголовочников нет. Описания типов нет. Так что только догадываться что значит тип "final" например. И тип ли это вообще.

Sayman
25.05.2018, 05:42
если лениво по каким-то причинам юзать модель __z88dk_callee, которая заслуживает всяческого уважения.
а в чём вообще смысл использования этой модели? я засунул эту модель в код, собрал. смотрю, результат вообще ничем не отличается от того, что было до этой модели. т.е. передача аргументов такая же. как и до этого. байт в байт, строка в строку. зачем мне лишние записи в исходнике тогда? может и есть какие то особенности использования этой модели, я об этом не знаю, оно не очевидно и в целом мало полезно.

SDCC юзает для выравнивания стека в подобных случаях INC SP/DEC SP.
именно из-за этого стек и уплывает при использовании "pop hl:ex (sp),hl ". я не поленился и для теста поменял пару функций на "это". в результате второй вызов функции привёл к зависанию программы.

здесь много параметров, для них явно не хватает регистров общего назначения.

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

__z88dk_fastcall, компилятор вообще не будет использовать стек, только регистр L (или пару HL в случае двухбайтового аргумента).

а ты точно проверял как это работает? оно хорошо, когда передать нужно 1 аргумент в 1 байт или 2 байта или два аргумента по 1 байту. как только данных становится больше, чем 2 байта, эта модель перестаёт работать.

Только для __z88dk_callee.
насколько я вижу по коду, эта модель не работает с аргументами, не кратными 2 байтам. 1 лишний байт снимается со стека, из-за этого стек уплывает. всё потому, что компилятор юзает лишние inc sp/dec sp. но про это я уже когда то давно говорил (в сравнении с хайтехом).

Shiny
25.05.2018, 06:02
Ну если всё остальное дашь кроме одного файла - можно и собрать попробовать) Там половины типов нет. Заголовочников нет. Описания типов нет. Так что только догадываться что значит тип "final" например. И тип ли это вообще.


в том-то и беда, что нет. Извечная беда Си - кинуть сырок без заголовков.

SfS
25.05.2018, 07:15
в том-то и беда, что нет. Извечная беда Си - кинуть сырок без заголовков.

Это не беда С. Это беда кидателей сырков без заголовков)

Oleg N. Cher
25.05.2018, 18:47
а в чём вообще смысл использования этой модели? я засунул эту модель в код, собрал. смотрю, результат вообще ничем не отличается от того, что было до этой модели. т.е. передача аргументов такая же. как и до этого. байт в байт, строка в строку. зачем мне лишние записи в исходнике тогда? может и есть какие то особенности использования этой модели, я об этом не знаю, оно не очевидно и в целом мало полезно.Как-то ты ограничено и предвзято подошёл к этому вопросу.

Смотри. С моделью __z88dk_callee вызывающей стороне не нужно вытаскивать аргументы из стека. Если ты этого у себя не воспроизвёл, значит мало и по верхушкам ковырялся. То есть имеем профит на вызывающей стороне.

На вызываемой стороне с моделью __z88dk_callee профит есть для кодовых процедур. Я тебе показывал как двумя-тремя командами вытаскивать аргументы. Это кардинально отличается от того, что предлагал ты.

Я говорю об очень очевидных вещах. Если есть желание спорить дальше, тут медицина бессильна.


именно из-за этого стек и уплывает при использовании "pop hl:ex (sp),hl ". я не поленился и для теста поменял пару функций на "это". в результате второй вызов функции привёл к зависанию программы.Мне всё труднее сдерживаться от ругательств. Ну ассемблерщики, хоть вы ему скажите?

Всё говорит о том, что ты менял на "это" без должного понимания того, что ты делаешь. А в ZXDev такой код много лет уже работает. И тебе любой ассемблерщик на пальцах это докажет. Вернее, не тебе, а кому-то умному. :-)


переключиться на альтернативный набор регистров религия не позволяет?Что ты, моя религия не настолько строга. Ты опять придрался к частностям, а я всего лишь утверждал, что индексные регистры тоже можно использовать там, где в этом есть смысл. А чаще всего для получения аргументов смысла в этом мало.


а ты точно проверял как это работает? оно хорошо, когда передать нужно 1 аргумент в 1 байт или 2 байта или два аргумента по 1 байту. как только данных становится больше, чем 2 байта, эта модель перестаёт работать.Я точно проверял как это работает. :v2_dizzy_facepalm:
Мда, доказывать сишнику преимущества Оберона после того, как ему нельзя доказать преимуществ Си...

Опять же, всякая модель хороша для своей цели. А там, где у тебя перестаёт работать или работает плохо, у кого-то другого поумнее - всё хорошо. Например, я умею передавать два однобайтовых аргумента под видом двухбайтового и в модели __z88dk_fastcall.


насколько я вижу по коду, эта модель не работает с аргументами, не кратными 2 байтам.Работает с одним лишненьким inc sp. Который выполняется быстро.


(в сравнении с хайтехом).А твой тупой хайтех вообще неэкономно использует и стек, и регистры.

И вообще жалею, что с тобой разговор затеял. Вот ей-богу, некоторых лучше вообще игнорить, пусть несут пургу сколько угодно.

Sayman
26.05.2018, 04:43
Я говорю об очень очевидных вещах. Если есть желание спорить дальше, тут медицина бессильна
я ни с кем не спорю. ты прибежал в тему и начал кому-то что-то доказывать, хотя тебя об этом не просили. Тебе что-то в sdcc no-init не нравится? исходники на git`е, бери да комить, что не так?

Работает с одним лишненьким inc sp. Который выполняется быстро.
видимо ты и сам не знаешь как оно работает, а других учить пытаешься. inc sp при заворачивании аргументов на стек, думаю логично предположить, что при обратном действии нужно делать dec sp, не?

А твой тупой хайтех вообще неэкономно использует и стек, и регистры.
Ооо всё, началось. Ты и 5 минут не работал с хайтехом, а несёшь какую-то дичь в его адрес.

доказывать сишнику преимущества Оберона после того, как ему нельзя доказать преимуществ Си...
закусывать надо! Никому здесь твой оберон не интересен, хорош уже бредить!

Если есть чё сказать по делу - добро пожаловать на git. нет, до свидания.

Error404
26.05.2018, 15:06
Строго говоря, все эти __z88dk_fastcall отдают деревней. Лет сто как принято объявлять при вызове параметр (или локальную переменную) "register" и тогда он/она передается компилятором не на стеке, а в регистре/регистрах. Именно так общепринято делают все нормальные компиляторы (в т.ч. и hiTech C), при этом при вызове можно сколько угодно переменных объявить как register, но компилятор загрузит в регистры столько их сколько позволяет платформа, а остальные пускай и так объявленные передаст стеком. Это дает совместимость исходников для всех платформ и нет никаких ограничений по количеству или разрядности параметров, например тот же hiTech C генерируя с такого общего исходника код Z80 позволяет только один регистр процессора задействовать, для 8086 уже 3 регистра и т.д.

И это, Олег, все помнят ваш прошлогодний каминаут на тему "я ленив но заносчив и поэтому все с чем не разобрался - виноват hiTech C", так что давайте меньше экспрессии в заявлениях или вникайте в детали (что даст аналогичный эффект). :)

- - - Добавлено - - -

PS. У hiTech C (по крайней мере v3.09 каким пользуюсь я) безусловно больше ограничений чем у современного SDCC, но он, извините, написан в сжатые сроки и при царе горохе (и как написан!), работает в 64кб под CP/M, а не в 64Гб под виндой 30 лет спустя (из которых первые 15 лет тем SDCC пользоваться было нельзя не заплевав монитор)

Shiny
26.05.2018, 15:34
мне думается, что под cp/m Turbo Pascal 3 удобнее.

SfS
26.05.2018, 16:50
Чего вы срётесь? Я в SDC-NOINIT больше концепцию сборки разрабатывал. В принципе - не так важно какая модель.
Если писать на чистом С - вообще не важно какая модель. Их всего две:

1. вызывающая процедура освобождает стек.
2. Вызываемая процедура освобождает стек.

И ни там ни там явно не указано сколько стека занято.

Раз кто-то придумал опции, позволяющие обе модели, значит комуто это было надо.

Oleg N. Cher
27.05.2018, 04:08
но он, извините, написан в сжатые сроки и при царе горохе (и как написан!)Без разницы как он написан. Прелесть инструмента разработки в его открытости, отзывчивости разработчиков и доступности. Смысла в бубнах и register переменных для параметров нет и не было. Кроме того, есть стандарты на модель вызова. А ещё хайтех имеет кривой и глючной оптимизатор, который использовать нельзя вообще. Вы его как юзаете? без оптимизатора или с ним? Беда, беда.

Всех желающих меня учить тонкостям хайтеха приглашаю в команду разработки подсистемы ZXDev3, на нём основанной. Что уже доказывает, что я ему уделил больше 5 минут. А хотя нет, от засратых хайтек-совместимых мозгов лучше держаться подальше. Вот sayman хотел выставить идиотами меня и разработчиков SDCC и z88dk, а выставил клиническим дураком себя.


Если писать на чистом С - вообще не важно какая модель.Мы пишем для Z80, значит весь низкий уровень в кодах. И доля его больше в сравнении с прикладным слоем.


всего две:

1. вызывающая процедура освобождает стек.
2. Вызываемая процедура освобождает стек.Есть больше моделей, например, передача в регистрах. Но не везде, ибо такая модель непереносима.


И ни там ни там явно не указано сколько стека занято.В Паскаль-модели (__stdcall или в z88dk __z88dk_callee) и вызывающий, и вызываемый код точно знают, сколько параметров и каких типов используется. Именно поэтому процедура сама освобождает стек, зная, сколько именно надо освободить. Если ты имеешь в виду прямо из своего машкода узнать сколько стека занято, то в этой модели ты можешь точно узнать - посчитай сумму байт, занимаемую параметрами.

Сишная модель вызова (__cdecl или в z88dk обычная, по умолчанию) характерна тем, что вызываемый код точно не знает, сколько занимают параметры (функции с переменным числом параметров). Поэтому функция может вытащить один, а может несколько, сколько ей нужно. А вот вызывающий код всё равно ведь знает, сколько параметров ложил на стек, поэтому он их и снимает сам.

Для Z80 на машкодовых функциях эффективнее Паскаль-модель, почему - я уже говорил. На Си-функциях вообще неэффективно работать с параметрами, но лучше не придумали. Наверно всё же сишная модель маленько предпочтительнее, ибо не нужно снимать параметры (через адрес возврата, который лежит первее их), а сделать это можно только после завершения рабочего тела, в конце функции.


Раз кто-то придумал опции, позволяющие обе модели, значит комуто это было надо.Ну да.

SfS, извини за ликбез, раз тебе это не надо, умолкаю. Не знал, что эти упыри набегут.

Sayman
27.05.2018, 07:07
Прелесть инструмента разработки в его открытости, отзывчивости разработчиков и доступности.
О! Щикарно! SDCC прям настолько открыт и его разрабы прям отзывчивы-отзывчивы и прям так доступны, что даже вот прям на любое msg отвечают и бегут править все-все баги. ага. удачки. на тот случай если ты не в курсе - автору sdcc давно плевать на компиляцию кода для z80. более того, новые версии - новые баги.

от sayman хотел выставить идиотами меня и разработчиков SDCC и z88dk, а выставил клиническим дураком себя.
лолшто? уважаемый, у вас проблемы с матчастью. не знаешь даже как стек работает. предлагаешь людям два раза делать инкремент стека - один раз компилятор в момент засовывания аргументов на стек и второй раз когда снимать нужно.

Кроме того, есть стандарты на модель вызова.
в эти стандарты __z88dk__чего-тотам не входит и никогда не входило. при этом htc как я помню может использовать регистры a, hl и iy когда переменная register.

глючной оптимизатор, который использовать нельзя вообще.
Давай конкретнее, какие баги в оптимизаторе? или ты не видишь разницы между asm файлом до и после оптимизатора?

Если говорить конкретно про баги sdcc, то вот мой список, который твои любимые афтары sdcc игнорят годами и исправлять не желают:
1. конструкция if(!(val = func1())) func2(); при которой val получает отрицательное число - не работает, т.к. компилятор упорно делает проверку через or a, т.е. на 0, не понимая, что результат может быть отрицательным. при этом с хайтех всё ОК.
2. sdcc не умеет работать с массивами вида char val[]; длинна которых явно не указана, но инициализируется позже. Примером является игра robo от hippiman`а. Эта игра собирается на старом sdcc 2.9.0, где такой проблемы нет. На всех версиях позже игра не работает, хотя и собирается 10 минут. в хайтехе с этим проблем нет!
3. в версии 3.7.0 сломали цикл while().
дальше даже продолжать нет желания. да, нет сомнений, sdcc полезный инструмент, местами и временами. он работает нативно под вендами, что очень удобно. и у хайтеха тоже есть не очень хорошие моменты меня бесящие (типа сколько-то байт мусора в конце файла). но, как уже сказали ранее, ты и 5 минут с ним не работал.
Остальное без комментариев))).

(__stdcall или в z88dk __z88dk_callee)

(__cdecl или в z88dk обычная, по умолчанию)
вот это вообще рукалицо. разрабы видимо вообще не знают стандартов языка и на ходу придумывают свои. __cdecl и __stdcall для sdcc как китайская грамота. но зато решили исковеркать и всё обозвать по своему. ништяг чё. и кстати, это не модель вызова, а соглашение вызова. чтобы более точнее понимать что это такое, вот:
раз (http://qaru.site/questions/115685/what-is-the-meaning-and-usage-of-stdcall)
два (https://igororlov92.livejournal.com/23705.html)

SfS
27.05.2018, 09:12
Есть больше моделей, например, передача в регистрах. Но не везде, ибо такая модель непереносима.

Я про SDCC. Там входящие параметры - считай только стек. Возвращаемые - L или HL. Усё. Нельзя вернуть структуру. Нельзя передать структуру. Только указатель...

- - - Добавлено - - -


Если ты имеешь в виду прямо из своего машкода узнать сколько стека занято, то в этой модели ты можешь точно узнать - посчитай сумму байт, занимаемую параметрами.

Я могу посчитать, конечно. А как быть с функциями с переменным числом аргументов?

- - - Добавлено - - -


SfS, извини за ликбез, раз тебе это не надо, умолкаю.

Да почему) я это - про С-модель и пасквиль-модель в институте проходил. Просто не знал, что в SDCC есть и пасквиль-модель.

На самом деле всё сводится к SP-=N и SP+=N. Делает это вызывающая или вызываемая процедура - не так уж важно. Спор остро-тупоконечников получается:)

Shiny
27.05.2018, 09:53
Кстати, а насколько будет сложно написать свой компилятор с подкидным и школьницами? Наподобие ACTION! ?

mastermind
27.05.2018, 16:48
Кстати, а насколько будет сложно написать свой компилятор с подкидным и школьницами? Наподобие ACTION! ?
На Хаскеле, пожалуй, относительно несложно. Т.к. есть уже готовый парсер для C, препроцессор, и в общем язык для таких задач очень хорош. См.:
1. https://hackage.haskell.org/package/language-c
2. https://hackage.haskell.org/package/cpphs
3. https://stackoverflow.com/questions/2906064/why-is-writing-a-compiler-in-a-functional-language-easier
4. http://www.stephendiehl.com/llvm/

Информация о Haskell на русском: https://github.com/bitemyapp/learnhaskell/blob/master/guide-ru.md

Oleg N. Cher
27.05.2018, 19:48
Я про SDCC. Там входящие параметры - считай только стек. Возвращаемые - L или HL. Усё. Нельзя вернуть структуру. Нельзя передать структуру. Только указатель...А где ещё входящие параметры - не только стек?

В SDCC есть 32-байтный тип long. Результат этого типа возвращается в DE:HL

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


Я могу посчитать, конечно. А как быть с функциями с переменным числом аргументов?Я не уверен, что хоть какой-то компилятор для Z80 их поддерживает. Но если бы поддерживал, ты же в курсе как работать с такими параметрами? Через макросы va_list, va_start, va_arg и va_end. Я не ковырял их, как они устроены, но думаю, что они сами не знают, сколько и каких параметров передано.

А тебе для чего это вообще нужно? Я бы предложил не париться с проблемой, которой в Си для Z80 даже нет.


Просто не знал, что в SDCC есть и пасквиль-модель.Раньше не было. Решили сделать для улучшения совместимости с z88dk.

- - - Добавлено - - -


О! Щикарно! SDCC прям настолько открыт и его разрабы прям отзывчивы-отзывчивыНе жалуюсь. А если хочешь лучше - напиши сам, будет лишний повод тебя поругать.


более того, новые версии - новые баги.Ну уж! Куда лучше - старые версии, старые баги. ;-)

htc использует регистр IY редко и почти никогда, а сохраняет его в каждом входящем фрейме. Каждая сишная функция в htc выполняет при входе код:


csv: pop hl ;return address
push iy
push ix
ld ix,0
add ix,sp ;new frame pointer
indir: jp (hl)

А при выходе из функции - такой:

cret: ld sp,ix
pop ix
pop iy
retВсегда, Карл! Забудь про быструю работу с аргументами как страшный сон.

Кодовые функции напрямую в Си-исходник вставлять нельзя, нужны отдельные асм-файлы. Про баги в оптимизаторе мне писал Элвин Албрехт из команды z88dk, и я ему верю.

Всего этого лично для меня этого достаточно, чтобы закопать htc навсегда.

Sayman
27.05.2018, 20:00
csv: pop hl ;return address
push iy
push ix
ld ix,0
add ix,sp ;new frame pointer
indir: jp (hl)
ну вот я так и думал, что ты именно к этим двум функциям придерёшься. ОК. csv - делает то, что sdcc делает стандартно (соглашение __cdecl), но внутри каждой функции - выравнивает стек. налицо растрата памяти со стороны sdcc, в то время как хайтех экономит, заменяя это всё на 3 байта вызова csv. Аналогично и jp cret - обратное выравнивание стека после выхода из функции - sdcc снова тратит память. но ты упускаешь оджин момент - когда ты говоришь про sdcc, то ты подразумеваешь использование асмовых библиотек и вставок. Почему в контексте хайтеха ты это пропускаешь? тебе никто не запрещает делать внутри своей функции на асме pop:push для выравнивания стека или ld hl,2:add hl,sp и т.д. При выходе сделать ret без обращения к cret. Да, у хайтеха только __cdecl соглашение работает. когда его делали, __stdcall не существовало в природе. sdcc так же как и сам хайтех внутри сишного кода всегда использует ix, постоянно.

Про баги в оптимизаторе мне писал Элвин Албрехт из команды z88dk, и я ему верю.
Я не знаю кто это, но команде z88dk не верю, т.к. их компилятор, мягко говоря, плохой. на порядок хуже качество кода, даже чем у sdcc. поэтому список багов оптимизатора хайтеха в студию.

Oleg N. Cher
28.05.2018, 01:43
налицо растрата памяти со стороны sdcc, в то время как хайтех экономит, заменяя это всё на 3 байта вызова csv.Ты не следишь за развитием SDCC, но хуже то, что ещё и вводишь людей в заблуждение своими устаревшими взглядами. Если использовать ключик --opt-code-size, то SDCC использует ровно те же 3 байта:


call ___sdcc_enter_ixНо, в отличие от htc, не будет сохранять IY, выигрывая на этом такты.

А если код критичен по скорости (--opt-code-speed), то будут выигрываться такты, htc опять в пролёте, ибо так не умеет. Ну упс.


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

Раз ты уж пропагандируешь юзать вставки на асме, то покажи-ка тут всем нам как их использовать без того, чтобы htc для асм-функций генерил call csv. В SDCC для этого есть __naked.

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


sdcc так же как и сам хайтех внутри сишного кода всегда использует ix, постоянно.Но зато может не использовать IY. Это большой профит.


список багов оптимизатора хайтеха в студию.Я не занимаюсь исследованием глюков htc.

Лучше список багов SDCC в студию. Вместе с примерами кода для их воспроизведения. Сделай хоть что-то полезное, а то только ноешь. Исходники свои на Си покажь, что ли. Посмотрим как ты круто кодишь на htc ;-)

Sayman
28.05.2018, 04:38
Но, в отличие от htc, не будет сохранять IY, выигрывая на этом такты.
ок, с этим согласен.

Раз ты уж пропагандируешь юзать вставки на асме, то покажи-ка тут всем нам как их использовать без того, чтобы htc для асм-функций генерил call csv. В SDCC для этого есть __naked.
я не пропагандирую именно вставки. я пропагандирую отдельные асм файлы завёрнутые в либу. и __naked я тоже не использую в sdcc.

не занимаюсь исследованием глюков htc.

Лучше список багов SDCC в студию.
я уже много раз про них говорил. на соседнем форуме с одной известной конфой тоже есть список багов. и я не занимаюсь исследованием багов sdcc, они сами вылезают в процессе написания того или иного кода. могу только ещё раз напомнить про проекты от hippiman. сделай доброе дело - пересобери любой из них, к примеру robo или nomad под современными версиями sdcc.

SfS
28.05.2018, 06:11
Кстати, а насколько будет сложно написать свой компилятор с подкидным и школьницами? Наподобие ACTION! ?

Для меня сложно. А смысл в нем? Просто для удовольствия?

- - - Добавлено - - -


Я не уверен, что хоть какой-то компилятор для Z80 их поддерживает. Но если бы поддерживал, ты же в курсе как работать с такими параметрами?

SDCC и любой другой С. Ибо функция printf() - именно такая. как и scanf() и прочие подобные.
Работать с ними удобно и прекрасно. Зайти в SDCC-NOINIT библиотека conio например.

Sayman
28.05.2018, 07:32
SDCC и любой другой С. Ибо функция printf() - именно такая. как и scanf() и прочие подобные.
кстати, printf() на асме можно увидеть тут (http://zx-pk.ru/threads/24194-alan-koks-predstavil-unix-podobnuyu-os-fuzix-yadro-kotoroj-potreblyaet-okolo-40-kb-ozu/page36.html).
есть и альтернативный вариант.

Shiny
28.05.2018, 08:38
А смысл в нем? Просто для удовольствия?

Упрощение разработки, чем трюки со стеком.

SfS
28.05.2018, 08:52
Упрощение разработки, чем трюки со стеком.

Если надо передать копию параметра и это не int не char и не float - то без стека не обойтись.

Oleg N. Cher
28.05.2018, 21:47
автору sdcc давно плевать на компиляцию кода для z80.Это, мягко говоря, ложная информация. Смотри сюда.

http://sdcc.sourceforge.net/changelog_heads/changelog-head-10413.txt

Филипп Краузе практически каждый день коммитит, и большинство его коммитов относятся к Z80.

Да и автор у SDCC не один. А если ты имеешь в виду основателя проекта SDCC, то он помер. Удовлетворительное основание, чтобы не работать над компилятором?

У меня не было никаких проблем с баг-репортами SDCC. На них всегда реагировали основательно.


SDCC и любой другой С. Ибо функция printf() - именно такая. как и scanf() и прочие подобные.Ага, видишь как. Непродвинуто я использую Си - как бэк-энд для Ofront+, а в Обероне нет переменного числа параметров.

SfS, ты подал баг-репорт насчёт while(1)? Дай кусочек кода для воспроизведения бага.

- - - Добавлено - - -

SfS, не думаешь перевести проект SDCC noinit на HiTech C? Какие "за" и "против", на твой взгляд?

SfS
29.05.2018, 02:59
Блин. Да я стер ту версию компилера. Надо попробовать восстановить.

- - - Добавлено - - -

Никогда не работал с hitech c.
Чем он лучше не знаю.

Sayman
29.05.2018, 08:12
Филипп Краузе практически каждый день коммитит, и большинство его коммитов относятся к Z80.
Каждый день, говоришь? А как давно ты проверял собственную ссылку? Для справки, последний коммит для z80 датируется 27м марта, исправлен библиотечный вызов ralloc(). Предыдущие коммиты даже смотреть не стал, уже и так на форумах разных пишут, что автор посылает всех с багами по части кодогенерации для z80 либо игнорит.

Непродвинуто я использую Си
ты уже определись, как ты им пользуешься. То у тебя годами работают __z88dk_callee с фасткаллом, то их не так давно внедрили, то ты пишешь горы кода на асме. то только чистый си используешь. И ещё, тоже для справки, когда пишешь код именно на си, т.е. "void func_name(type arg1, type arg2){ код на си }", то имей ввиду, что __z88dk_fastcall не работает, даже если аргумент один и он однобайтный. Работает, но только частично, __z88dk_callee - компилятор убирает выравнивание стека после вызова функции, но внутри вызываемой функции всё как обычно:
ld ix,#2:add ix,sp и т.д. Ничего нового и интересного.

Oleg N. Cher
29.05.2018, 20:25
уже и так на форумах разных пишут, что автор посылает всех с багами по части кодогенерации для z80 либо игнорит.Думаешь, я просто так спрашиваю? Я собираюсь доказать на практике как они реагируют на баг-репорт. Поэтому давай код, который воспроизводит багу на самой новой версии SDCC.

Вдруг ты не в курсе, но каждый баг-репорт приводит к тому, что наполняется база регресс-тестов. И они выполняются для каждой сборки. Там есть цветной прямоугольничек, который показывает, насколько удачно пройдены все тесты. Для htc в старые времена не было таких возможностей. Я ещё почему не боюсь остановки развития SDCC. Ну замрёт он, допустим. Тогда уж кто-то вылижет найденные баги и будет у нас хороший открытый компилятор. htc перестал развиваться, тебя же это не смущает? Главное тут - вложиться в инструмент разработки, которым пользуешься. Ничего бесплатного нет, у всего своя скрытая стоимость. Раз ты пользуешься SDCC, но не помогаешь сделать его лучше, ты халявщик и паразит. Тем более, это Z80, его сейчас почти нигде не используют в промышленности.


То у тебя годами работают __z88dk_callee с фасткаллом, то их не так давно внедрилиНе надо мои слова перевирать. Они работают уже несколько лет, и это сравнительно недавно. Когда я начинал пользоваться SDCC, этого не было. Всё. А если ты бухтишь почему __z88dk_callee не обозначен как __stdcall, то кто тебе доктор?

#define __stdcall __z88dk_callee


то ты пишешь горы кода на асме. то только чистый си используешь.Я пишу на Обероне. Асм по необходимости. Си-исходник создаёт мне транслятор Ofront+. Писать на Си руками я уже давно не хочу.


__z88dk_fastcall не работает, даже если аргумент один и он однобайтный. Работает, но только частичноБабушку свою учи. __z88dk_fastcall и __z88dk_callee только для функций на ассемблере. Там, где они имеют профит.

Sayman
30.05.2018, 04:01
Они работают уже несколько лет, и это сравнительно недавно.
А несколько лет это сколько? Олег, завязывай уже. эти фичи появились в 16м году и то не в самом его начале. Даже двух лет толком нет.

я устал. всё. продолжай кодить на обероне...

Знахарь
30.05.2018, 19:41
слушайте, друзья, а вот скажите мне, кто-то из вас использует что-то из всего здесь упомянутого где-то в работе... Есть в стране вообще работа для таких специалистов?

Error404
31.05.2018, 01:35
слушайте, друзья, а вот скажите мне, кто-то из вас использует что-то из всего здесь упомянутого где-то в работе... Есть в стране вообще работа для таких специалистов?

Пару десятилеток назад я как системщик с парой студентов и парой прикладников сделал проект для одного крупного банка страны на С+OracleEmbSQL (3 платформы: DEC VAX C, AIX VACPP, Win MS Vstudio CPP) который продался за 150К$ (правда проработал он очень не долго - у них случилась реорганизация и вышестоящей организации по принципу "сделано не нами" всё это не понадобилось). Студентов пришлось научить всему, начиная от использования экранного дебагера заканчивая логикой программ - ну там очереди, треды, IPC, ловушки и т.п. Там было несколько миллионов строк кода (самописного из них порядка 10% - собственно сервера 3-звенки, платформенно-зависимые вещи, GUI на curses {мой труд в-основном, и студентов} остальное полученное source-level транслятором с DEC VAX C и Oracle RDB {прикладниками} на целевые платформы). Позже С пользовался только для души, а вообще больше люблю Паскаль (именно Борландовские компиляторы). И вообще я не программист (просто любую тему как ту временную начинаю с максимального расширения кругозора в теме перед тем как начинать зарываться вглубь), тем паче мне странно видеть какое тут иной раз задвигают программеры которые некоторые узкие вещи наверняка знают гораздо лучше меня, но надо же и вширь думать тоже.

Oleg N. Cher
31.05.2018, 23:10
слушайте, друзья, а вот скажите мне, кто-то из вас использует что-то из всего здесь упомянутого где-то в работе... Есть в стране вообще работа для таких специалистов?Имеешь в виду Си для Z80?

Я - коммерческий Оберон-программист. Мне за это платят деньги. И это интересная работа, творческая.

Как применять в коммерции Си для Z80 в наше время - я ответить затрудняюсь. Сейчас все ринулись на ARM'ы, в основном.

Alcoholics Anonymous
01.06.2018, 09:06
Просто добавьте сюда:

В z88dk есть два компилятора c. Один из них - sccz80, который не является оптимизирующим компилятором и совместим с C89 с некоторыми расширениями. Он также примет некоторые K & R C. Другим компилятором является zsdcc, который является вилкой sdcc-z80. zsdcc C89 совместим с расширениями на C99 и C11. zsdcc является оптимизирующим компилятором, был изменен из родительского sdcc, создает лучший код, чем сам sdcc, и исправил многие проблемы генерации кода, которые были в sdcc. sdcc устраняет многие из этих ошибок, а также за последние 6 месяцев.

О том, насколько хорошо поддерживается z80 в рамках проекта sdcc, он уделяет большое внимание. Один из основных разработчиков sdcc (Philip) интересуется z80. Он очень чувствителен ко всем вопросам, которые мы поднимаем, и даже решил модифицировать генератор кода z80, чтобы настроить новые инструкции в zx next, который является очень нишевым.

Три соглашения вызова, которые поддерживают zsdcc, sdcc и sccz80, являются стандартными c, z88dk_callee и z88dk_fastcall. Соглашения z88dk_callee и z88dk_fastcall были добавлены в sdcc для z88dk, потому что z88dk имеет очень большую библиотеку ассемблера (> 1000 функций), которая использует z88dk_callee и z88dk_fastcall для эффективного вызова функций языка ассемблера. Добавление позволило нам включить часть компилятора s sdcc в z88dk.

Хотя z88dk_callee и z88dk_fastcall предназначены для взаимодействия с функциями языка ассемблера, оба zsdcc и sccz80 могут генерировать код для связи z88dk_fastcall.

Стандартная привязка c дает ответчику ответственность за очистку параметров, переданных в стек. Последовательность вызовов: нажмите параметры в стеке, вызовите функцию и вытащите параметры из стека. Эта привязка должна использоваться для функций vararg, таких как printf и для указателей функций.

Связь z88dk_fastcall имеет один параметр, передаваемый через регистр в подмножестве DEHL. Параметр может быть длиной 8, 16 или 32 бит.

Связь z88dk_callee несет ответственность за очистку стека от вызываемой функции. Таким образом, последовательность вызовов: нажмите параметры в стеке и вызовите функцию. Вызываемая функция реализована в ассемблере, и она просто добавит параметры в регистры, которые очистят стек одновременно.

Как fastcall, так и callle linkage ускоряют программы и уменьшают размер программы на большое количество. Заголовки в z88dk гарантируют, что привязка и связь fastcall всегда выбираются, когда это возможно. Нет проблем с нажатием одного байта или двух или четырех параметров.

Что касается того, почему больше параметров не передается через регистр, нет смысла делать это, если первое, что нужно сделать компилятору, - это нажать их на стек из-за давления в регистре. В архитектуре z80 нет бесконечного количества регистров. Для функций языка ассемблера это может быть полезно, но вам нужно помнить, что вызывающему абоненту необходимо собрать эти параметры в регистрах перед выполнением вызова. По мере того, как больше значений помещаются в регистры перед вызовом, у компилятора больше трудностей возникает сбор дополнительных параметров в остальных регистрах. Возможно, придется прибегать к нажатию параметров на стек, а затем выталкивать их перед вызовом, который не лучше, чем привязка. Олег предположил, что несколько параметров одного байта могут быть легко собраны в регистрах перед вызовами, и это может быть так.


Есть некоторая путаница в связи с вызовами функций. Для этого нет никаких стандартов, кроме некоторых конкретных операционных систем / процессоров, может быть определена ABI, которая стандартизирует привязку для определенных платформ. Взаимодействие в противном случае зависит от компилятора. «register» не является ключевым словом для определения связи вызова функции. Он предназначен как подсказка для компилятора, когда автоматические переменные, объявленные внутри функции, лучше всего помещать в регистр, а не в стек. В стандарте C ничего не говорится о связи вызова функций и о том, что вы видели как «cdecl», а также привязка pascal не являются стандартными, но имеют вес, потому что Microsoft или другие доминирующие компиляторы используют его. Вы можете просмотреть https://en.wikipedia.org/wiki/X86_calling_conventions список перечней популярных ссылок вызовов функций для архитектуры архитектуры x86.


Ни sdcc, ни sccz80 не позволяют передавать структуры по значению. Это рассматривается как низкий приоритет, потому что очень неэффективно передавать структуры по значению, и вместо этого они скорее должны быть переданы указателем. Передача структуры по значению означает использование ldir для копирования исходной структуры в память, зарезервированную в стеке внутри целевой функции. Чтобы вернуть структуру, функция должна использовать ldir для копирования локальной структуры в память, ожидающей в памяти памяти вызывающего. Это не очень эффективно. Однако sdcc / zsdcc делают это внутренне для 64-битных длинных целых чисел в списках параметров и в возвращаемых значениях. В z88dk мы потратили некоторое усилие, сохранив размер кода для этих случаев.

2134/5000
О printf и scanf, библиотека sdcc предназначена для кросс-платформенности (работает на всех целевых процессорах) и предназначена для таргетинга на встроенные системы, которые считаются «необоснованными», что означает отсутствие базовой операционной системы. В большинстве случаев это означает, что scanf (и sdcc не имеет scanf) мало нуждается, и printf просто переходит к одной процедуре putchar, не имеющей понятия рулевого вывода для разных ФАЙЛОВ. Кросс-платформенное требование для sdcc также означает, что его библиотека должна оставаться почти полностью написанной на C, что является большим недостатком по сравнению с, скажем, z88dk, iar и даже hitech cpm.

Однако z88dk не имеет таких требований, и его библиотека полностью написана в asm, включая printf и scanf, которая проходит через FILE * и устройства, созданные на файловых дескрипторах, следующих за моделью unix. Stdio также объектно ориентирован, поэтому вы можете подклассировать драйверы, чтобы изменить их поведение.

Реализация asm printf поддерживает эти конвертеры, включая все параметры форматирования, указанные в стандарте:

% d,% u,% x,% X,% o,% n,% i,% p,% B (двоичный),% s,% c,% I (интернет IPv4),% ld,% lu,% lx,% lX,% lo,% ln,% li,% lp,% lB,% lld,% llu,% llx,% llX,% llo,% lli,% a,% A,% e,% E, % f,% F,% g,% G

Список аналогичен для scanf. Как вы можете видеть, там есть float, а также 64-битные целые числа.

Пользователь контролирует, сколько из этих конвертеров включено в программу во время компиляции. Если вы хотите только% s, вы можете так сказать.


Hitech C (cpm или msdos) редко производит быстрый или малый код, чем z88dk / zsdcc, и я бы никогда не говорил в контексте большой программы из моего опыта в компиляции некоторых больших тестовых программ для сравнения. Есть одно исключение: hitech c, похоже, имеет очень быструю поплавковую реализацию. К сожалению, это также ненадежно, так как оно часто имеет большие ошибки и иногда неправильные результаты для трансцендентных функций.


Для спектра в частности, около 50 игр были написаны с использованием z88dk в C, и многие из них довольно велики. Мы достаточно уверены, что самые важные ошибки были устранены. Избавление от них - всегда постоянный процесс.


original in english:

Just to add here:

Within z88dk there are two c compilers. One is sccz80 which is not an optimizing compiler and is C89 compliant with some extensions. It will accept some K&R C as well. The other compiler is zsdcc which is a fork of sdcc-z80. zsdcc is C89 compliant with extensions into C99 and C11. zsdcc is an optimizing compiler, has been modified from the parent sdcc, produces better code than sdcc itself and has fixed a lot of the code-generation issues that were in sdcc. sdcc has been eliminating a lot of those bugs as well in the past 6 months.

About how well supported the z80 is within the sdcc project, it sees a great deal of attention. One of the main sdcc developers (Philip) has an interest in the z80. He is very responsive to all issues we raise and has even committed to modifying the z80 code generator to target the new instructions in the zx next, which is a very niche machine.

The three calling conventions that zsdcc, sdcc and sccz80 support are standard c, z88dk_callee and z88dk_fastcall. The z88dk_callee and z88dk_fastcall conventions were added to sdcc for z88dk because z88dk has a very large assembly language library (> 1000 functions) that uses z88dk_callee and z88dk_fastcall to efficiently call assembly language functions. The addition allowed us to incorporate the c compiler portion of sdcc into z88dk.

Although z88dk_callee and z88dk_fastcall are intended for interfacing to assembly language functions, both zsdcc and sccz80 can generate code for z88dk_fastcall linkage.

The standard c linkage gives the caller responsibility for clearing parameters passed on the stack. The call sequence is: push parameters on the stack, call the function and pop the parameters off the stack. This linkage must be used for vararg functions like printf and for function pointers.

The z88dk_fastcall linkage has one parameter passed via register in a subset of DEHL. The parameter can be 8, 16 or 32 bits long.

The z88dk_callee linkage gives responsibility for cleaning up the stack to the called function. So the call sequence is: push parameters on the stack and call the function. The called function is implemented in assembler and it will simply pop the parameters into registers which will clear the stack at the same time.

Both fastcall and callee linkage speed up programs and reduce program size by a large amount. The headers in z88dk ensure that callee and fastcall linkage are always selected when possible. There are no problems with pushing one byte or two or four for parameters.

As for why more parameters don't get passed via register, there's no point in doing that if the first thing the compiler needs to do is push them on the stack because of register pressure. There is not an infinite supply of registers available in the z80 architecture. For assembly language functions there may be a use for it but you do have to keep in mind the caller needs to gather those parameters into registers before making the call. As more values are placed in registers before the call, the compiler has more difficulty gathering further parameters into the remaining registers. It may have to resort to pushing params onto the stack and then popping them before the call which is no better than callee linkage. Oleg has suggested that multiple single byte parameters could easily be gathered in registers before calls and that may be the case.


There's some confusion about function call linkage. There is no standard for this except for some specific operating systems / processors there may be an ABI defined that standardizes linkage for specific platforms. The linkage is otherwise up to the compiler. "register" is not a keyword for defining function call linkage. It's intended as a hint to the compiler when automatic variables declared inside a function would best be placed in a register rather than in the stack. The C standard says nothing about function call linkage and things you've seen like "cdecl" and pascal linkage are non-standard too but have weight because Microsoft or other dominant compilers use it. You can see https://en.wikipedia.org/wiki/X86_calling_conventions for a list of some popular function call linkages for the x86 architecure.


Neither sdcc nor sccz80 allows structures to be passed by value. This is seen as a low priority because it's very inefficient to pass structs by value and these should rather be passed by pointer instead. Passing a struct by value means using ldir to copy the source struct into memory reserved on the stack inside the target function. To return a struct, the function must use ldir to copy the local struct to memory waiting in the caller's memory space. This is not very efficient. However, sdcc/zsdcc are doing this internally for 64-bit long long integers in parameter lists and in return values. In z88dk we spent some effort keeping the code size down for these cases.


About printf and scanf, sdcc's library is meant to be cross platform (working on all processors it targets) and is meant to target embedded systems which are considered "unhosted" meaning there is no underlying operating system. In most situations this means there is little need for scanf (and sdcc does not have scanf) and printf simply goes to a single putchar routine with no concept of steering output to different FILEs. The cross-platform requirement for sdcc also means its library must remain written almost entirely in C which is a large disadvantage compared to, say, z88dk, iar, and even hitech cpm.

However, z88dk has no such requirements and its library is written entirely in asm, including printf and scanf which passes through FILE* and devices instantiated on file descriptors following the unix model. Stdio is also object oriented so you can subclass drivers to change their behaviour.

The asm printf implementation supports these converters including all the formatting options specified in the standard:

%d, %u, %x, %X, %o, %n, %i, %p, %B (binary), %s, %c, %I (internet IPv4), %ld, %lu, %lx, %lX, %lo, %ln, %li, %lp, %lB, %lld, %llu, %llx, %llX, %llo, %lli, %a, %A, %e, %E, %f, %F, %g, %G

The list is similarly comprehensive for scanf. As you can see there is float in there as well as 64-bit integers.

The user has control over how many of these converters are included in the program at compile time. If you only want %s you can say so.


Hitech C (cpm or msdos) rarely produces faster or small code than z88dk/zsdcc and I would say never in the context of a large program from my experience in compiling some large test programs for comparison. There is one exception: hitech c seems to have a very fast float implementation. Unfortunately it's also unreliable since it quite often has large errors and sometimes wrong results for transcendental functions.


For the spectrum specifically, around 50 games have been written using z88dk in C and many are quite large. We're fairly confident that the most important bugs have been eliminated. Getting rid of them all is always an ongoing process.

Sayman
01.06.2018, 10:31
В контексте больших программ - назрел вопрос. Когда код раздувается сильно, настаёт время задуматься о том, куда и как его перемещать. Поскольку можно включить в 0е окно проца ещё какую-то страницу, то хотелось бы туда скинуть часть сишного кода. Т.е. допустим, часть функций сидит в адресах 0x8000..., часть кода в 0x0000. На стадии загрузчика я бы мог скинуть этот код туда, в 0. Например, на старом асме M80 была такая директива .phase и .dephase, в ужасме есть аналогичная директива, благодаря которой код указанный внутри директивы собирается на указанный директивой адрес. соответственно, загрузчик этот код скидывает на нужный адрес. Если делать через org, то в бинарном файле дует овердофига нулей. Какие есть вариант при помощи sdcc разогнать части кода по памяти по разным, каким мне надо адресам?

s_kosorev
01.06.2018, 12:50
1. Блобы и при старте раскидывать по адресам?
2. Линковать разные модули в разные бинарники с разных адресов?
3. .... ?

Alcoholics Anonymous
01.06.2018, 19:27
В контексте больших программ - назрел вопрос. Когда код раздувается сильно, настаёт время задуматься о том, куда и как его перемещать. Поскольку можно включить в 0е окно проца ещё какую-то страницу, то хотелось бы туда скинуть часть сишного кода. Т.е. допустим, часть функций сидит в адресах 0x8000..., часть кода в 0x0000. На стадии загрузчика я бы мог скинуть этот код туда, в 0. Например, на старом асме M80 была такая директива .phase и .dephase, в ужасме есть аналогичная директива, благодаря которой код указанный внутри директивы собирается на указанный директивой адрес. соответственно, загрузчик этот код скидывает на нужный адрес. Если делать через org, то в бинарном файле дует овердофига нулей. Какие есть вариант при помощи sdcc разогнать части кода по памяти по разным, каким мне надо адресам?


.phase и .dephase не подходят для этого. .фаза - это изменение адреса сборки и сохранение собранного результата по другому адресу памяти. При запуске CPU перед запуском копирует раздел .phase на правильный адрес назначения. Тогда в памяти есть две копии.

z88dk имеет это тоже, и он наиболее часто используется в бездисковых системах без дисков, чтобы скопировать некоторые исполняемые файлы в оперативную память перед тем, как выложить ром и начать. Здесь приведен пример такой системы: https://github.com/RC2014Z80/RC2014/.../cpm22.asm#L69, где cpm 2.2 хранится в ROM-изображении, которое копируется в ram после включения питания. Человек, делающий это, упустил трюк, потому что было бы лучше сохранить изображение cpm в сжатой форме.

sdcc сама определяет карту памяти, используя области. Это уже цитировалось в нескольких местах, но я думаю, что это плохо понимается. областям дается org, чтобы определить, где они находятся в пространстве памяти. Вы можете определить несколько областей с тем же или перекрывающимся диапазоном адресов, чтобы покрыть пространство памяти> 64k. Выходной файл sdcc является файлом hex hex, который генерирует представление этого пространства памяти в компактном виде (т.е. без заполнения нуля). Вы можете использовать стандартные инструменты, чтобы превратить это в несколько двоичных файлов.

Инструменты z88dk более продвинутые. Внутри он имеет представление любого пространства памяти, которое может быть определено индивидуально для каждой цели. Вывод обрабатывается через отдельную программу «appmake», которая может превратить это представление в подходящий вывод, будь то ленточный образ, исходные двоичные файлы, шестнадцатеричный ключ, моментальные снимки, образы дисков и т. Д. Но центральным для этого является СЕКЦИЯ, которая функционально такая же, как и область Sdcc.

Чтобы увидеть, как это делается, вот краткий пример для zx next. Zx next имеет несколько пространств памяти, но наиболее важным является организация ram на 224 страницы по 8 k каждый. Каждая из этих страниц может быть помещена в любой диапазон 8k в 64-килограммовом пространстве z80. Я не хочу вдаваться в подробности здесь, но для понимания этого примера должно быть достаточно информации.

В asm я поместил некоторые вещи на некоторые 8k-страницы:


.phase and .dephase are not the right tool for this. .phase is for changing the assemble address and storing the assembled result at another memory address. At startup, the cpu copies the .phase section to the correct destination address before starting. Then there are two copies in memory.

z88dk has this too and it is most frequently used in rom-only diskless systems to copy some executable into ram before paging out the rom and starting. There is an example of such a system here: https://github.com/RC2014Z80/RC2014/blob/master/ROMs/CPM-IDE/sio/cpm22.asm#L69 where cpm 2.2 is stored in the rom image which is copied into ram after power up. The person doing this missed a trick because it would have been better to store the cpm image in compressed form.

sdcc itself defines a memory map using areas. This has been quoted in several places already but I think it is poorly understood. areas are given an org to define where in the memory space they reside. You can define multiple areas with the same or overlapping address range to cover a memory space > 64k. The output from sdcc is an intel hex file which generates a representation of this memory space in a compact manner (ie no zero padding). You can use standard tools to turn this into multiple binaries.

z88dk's tools are more advanced. Internally it has a representation of any memory space which can be defined individually for each target. The output is processed through a separate program "appmake" that can turn this representation into a suitable output whether that be tape image, raw binaries, intel hex, snapshots, disk images and so on. But central to this is the SECTION, which is functionally the same as sdcc's AREA.

To see how it is done, here is a short example for the zx next. The zx next has several memory spaces but the most important is the organization of ram into 224 pages of 8k each. Each of these pages can be placed into any 8k range in the z80's 64k space. I don't want to get into details here but that should be enough information to understand this example.

In asm, I've placed some things into some of the 8k pages:




SECTION BANK_5

defs 2048,0xaa

SECTION PAGE_30

defs 128, 0
defs 128, 30
defs 128, 0xff

SECTION PAGE_41

defs 128, 0
defs 128, 41
defs 128, 0xff

SECTION PAGE_125

defs 128, 0
defs 128, 125
defs 128, 0xff

SECTION DIV_1

defm "DIV1", 0


Вы можете сделать то же самое для c - вы также можете скомпилировать c-код на определенные страницы памяти.

«DIV_1» представляет собой память «divmmc». Память RAM-памяти zx next также может быть организована как 16k-страницы для совместимости с спектром 128k. Пространство PAGE и пространство BANK совпадают с BANK_5, что соответствует PAGE_10 и PAGE_11. Это называется BANK_5 здесь, потому что это то, как программисты спектра обычно понимают местоположение экрана. В этом случае 2k данных, присвоенных BANK_5, будут отображаться как вертикальные полосы на экране улы.

Простой пример, который проверяет содержимое этих банков во время выполнения:


You can do the same for c - you can compile c code into specific memory pages too.

"DIV_1" represents divmmc memory. The zx next's ram memory can also be organized as 16k pages for compatibility with the 128k spectrum. The PAGE space and the BANK space are the same with BANK_5 corresponds to PAGE_10 and PAGE_11. It's called BANK_5 here because this is how spectrum programmers normally understand the location of the screen. In this case the 2k of data assigned to BANK_5 will appear as vertical bars on the ula screen.

A simple example that verifies the contents of those banks at runtime is this:




#include <stdio.h>
#include <stdlib.h>
#include <arch/zxn/esxdos.h>
#include <arch/zxn.h>
#include <errno.h>

void print_page(unsigned char page)
{
ZXN_WRITE_MMU3(page); // place the page into address range 24k-32k

printf("Page %u\n\n", page);

for (unsigned char *p = 0x6000; p != 0x6180; ++p)
printf("%02x", *p);

printf("\n\n");

ZXN_WRITE_MMU3(11); // restore bank 5 into address range 24k-32k
}

int main(void)
{
extended_sna_load(0);
esx_f_close(0);

if (errno)
{
printf("Error: %u\n", errno);
exit(1);
}

print_page(30);
print_page(41);
print_page(125);

return 0;
}


Вся программа скомпилирована в расширенный файл sna 128k, в который добавлены дополнительные банки памяти. Программа загружает дополнительные банки памяти при запуске с помощью функции «extended_sna_load».

Если я скомпилирую эту программу с z88dk без какой-либо обработки, выход будет представлять собой набор двоичных файлов, представляющих память:


The entire program is compiled into an extended 128k sna file that has the extra memory banks appended to it. The program loads the extra memory banks at startup using function "extended_sna_load".

If I compile this program with z88dk without any processing, the output will be a set of binary files representing memory:


sna__.bin - main() in banks 5,2,0
sna__DIV_001.bin
sna__PAGE_010.bin
sna__PAGE_030.bin
sna__PAGE_041.bin
sna__PAGE_125.bin

Для sdcc вы вручную определяете области, охватывающие каждую из страниц в crt. Результатом будет один файл hex hex, а не набор двоичных файлов. Как вы извлекаете двоичные данные из файла hex hex, зависит от вас. Это не означает, что вам нужно получить один большой двоичный код с нулевым заполнением между областями.

Если я скомпилирую эту программу с помощью z88dk и запрошу расширенный sna как результат, результат будет следующим:


For sdcc you would manually define the areas covering each of the pages in the crt. The output would be a single intel hex file rather than a set of binaries. How you extract the binary data from the intel hex file is up to you. It does not mean you have to get one large binary out with zero padding between areas.

If I compile this program with z88dk and ask for an extended sna as output, the result is:


sna.sna - 153k containing all the PAGEs and BANKs
sna__DIV_001.bin

Sna содержит всю память и готов к исполнению на реальной машине. Двоичный диск DIV по-прежнему является отдельным, поскольку пространство памяти «divmmc» не является частью «sna». Программа отвечает за получение этого двоичного кода в память при запуске.

В sdcc нет дополнительного шага для автоматического создания вывода правильной формы. Он имеет возможность определять пространства памяти в crt с помощью директив AREA. z88dk идет дальше с возможностью отделить «org» адрес от физической памяти (PAGE); это можно сделать с помощью PHASE, но лучше сделать это с помощью других средств, которые не мешают компоновщику.


The sna contains the entire memory space and is ready for execution on the real machine. The DIV binary is still separate because the divmmc memory space is not made part of the sna. The program is responsible for getting that binary into memory when started.

sdcc does not have an extra step to automatically generate output of the correct form. It does have the ability to define memory spaces in the crt with AREA directives. z88dk goes further with the ability to separate the org address from the physical memory location (PAGE); this could be done with PHASE but it's better done with other means that don't impede the linker.

SfS
02.06.2018, 11:13
В контексте больших программ - назрел вопрос. Когда код раздувается сильно, настаёт время задуматься о том, куда и как его перемещать. Поскольку можно включить в 0е окно проца ещё какую-то страницу, то хотелось бы туда скинуть часть сишного кода. Т.е. допустим, часть функций сидит в адресах 0x8000..., часть кода в 0x0000. На стадии загрузчика я бы мог скинуть этот код туда, в 0. Например, на старом асме M80 была такая директива .phase и .dephase, в ужасме есть аналогичная директива, благодаря которой код указанный внутри директивы собирается на указанный директивой адрес. соответственно, загрузчик этот код скидывает на нужный адрес. Если делать через org, то в бинарном файле дует овердофига нулей. Какие есть вариант при помощи sdcc разогнать части кода по памяти по разным, каким мне надо адресам?

Я поппытался решить эту проблему в SDCC-NOINIT. В процессе (ещё до конца не доделано).

Идеология такая: имеется "перемещаемая библиотека", которую можно загрузить с любого адреса, кратного 0x100. Она содержит в себе функции и таблицу перемещений.
При загрузки библиотеки она настраивается на адрес загрузки.

В основной программе хранится специальная маленькая процедурка, которая позволяет вызвать функцию по любому адресу. Эта процедурка настраивается при загрузки библиотеки.

То есть библиотека представлена в виде двух файлов:
1. Загружаемый .bin модуль - собственно библтотека.
2. Встраиваемая в основную программу часть библиотеки .rel.

Вызов функций из основной программы - прозрачный. То есть не надо самому переключать странички, что-то настраивать. При загрузки библиотеки всё настраивает загрузчик.

В принципе - работает. Но есть нюансы.

Самое сложное было автоматизировать генерацию кода для вызовов. Но bash справился:)

Sayman
02.06.2018, 15:13
Да чую мне проще будет накалякать нужный код на ужасме и бинарь потом в нужный адрес пихать, чем тут парится. z88dk вообще не вариант и никогда не будет вариантом.

SfS
03.06.2018, 05:51
Там не важно С или АСМ.
Таблица перемещения генерится автоматом.
Если программа многостраничная, то накладные расходы не велики. Зато удобство.
Проблема сейчас как это хорошо совместить с менеджером памяти.

Error404
03.06.2018, 13:46
Таблица перемещения генерится автоматом.


Так как в итоге решилась проблема с генерацией этой таблицы? Или осталось в варианте нахождения абсолютных адресов разностью двух бинарных кусков?

SfS
03.06.2018, 15:06
Генерится из двух бинарных файлов. Отсюда и ограничение на адрес загрузки кратный 256

Sayman
03.06.2018, 19:08
Релоцируемые исполняемые файлы были ещё в MPM (многопользовательская цпм). Там такая же таблица 256 байт в конце файла. так что ничего нового не изобретено.

SfS
04.06.2018, 05:30
Релоцируемые исполняемые файлы были ещё в MPM (многопользовательская цпм). Там такая же таблица 256 байт в конце файла. так что ничего нового не изобретено.

1. Таблица столько байт, сколько надо. Не обязательно 256.
2. Адрес загрузки кратен 256 (например 0x8000, 0x8100, 0xC200 и так далее).
3. Целью было не "изобрести", а реализовать возможность загрузки библиотек.

Oleg N. Cher
04.06.2018, 17:18
А вот как бы вы предложили связать SDCC и движок типа Nirvana, привязанный к определённому адресу в памяти?

[скомпилированный Си-код] [00 00 00 много нулей 00 00 00] [Nirvana]

Си-код растёт, уменьшая размер пустого блока нулей.

Самое простое, что можно придумать - загружать код и движок отдельными блоками - LOAD ""CODE 2 раза.

Решил набросать утилитку, которая будет сливать два бинаря с указанием их адресов в один блок, показывать размер пустого блока нулей между ними. И если Си-код, растущий вверх, наполз на начало следующего блока (отрицательный размер буфера нулей), сигнализировать об этом.

Может есть ещё какие-то варианты? (хочется только один LOAD ""CODE)

Reobne
04.06.2018, 18:24
Может есть ещё какие-то варианты? (хочется только один LOAD ""CODE)
После загрузки раздвинуть блоки LDIR-ом. :)
Или другие, более продвинутые методы упаковки. :)

Sayman
04.06.2018, 18:38
А вот как бы вы предложили связать SDCC и движок типа Nirvana, привязанный к определённому адресу в памяти?

[скомпилированный Си-код] [00 00 00 много нулей 00 00 00] [Nirvana]

Си-код растёт, уменьшая размер пустого блока нулей.

Самое простое, что можно придумать - загружать код и движок отдельными блоками - LOAD ""CODE 2 раза.

Решил набросать утилитку, которая будет сливать два бинаря с указанием их адресов в один блок, показывать размер пустого блока нулей между ними. И если Си-код, растущий вверх, наполз на начало следующего блока (отрицательный размер буфера нулей), сигнализировать об этом.

Может есть ещё какие-то варианты? (хочется только один LOAD ""CODE)
Думаю, что тут поможет только подход аля evosdk. ДУмаю, что в любом случае без изменений тут не обойтись. Придётся в исходники лезть и править вызов тех функций, которые будут распиханы по страницам.

Oleg N. Cher
04.06.2018, 19:40
После загрузки раздвинуть блоки LDIR-ом. :)
Или другие, более продвинутые методы упаковки. :)Да, так можно. Заодно и упаковать код - хорошая мысль.

s_kosorev
05.06.2018, 09:33
Может есть ещё какие-то варианты?
Если линкер SDCC нормально поддерживает секции с абсолютным адресом, можно бинарник конвертнуть в rel формат и линковать как и все остальное,
Описать точки входа и создать хидер

- - - Добавлено - - -

Для совсем прозрачного, нужна прослойка с маршалингом параметров

Error404
05.06.2018, 11:35
А вот как бы вы предложили связать SDCC и движок типа Nirvana, привязанный к определённому адресу в памяти?

[скомпилированный Си-код] [00 00 00 много нулей 00 00 00] [Nirvana]

Си-код растёт, уменьшая размер пустого блока нулей.

Самое простое, что можно придумать - загружать код и движок отдельными блоками - LOAD ""CODE 2 раза.

Решил набросать утилитку, которая будет сливать два бинаря с указанием их адресов в один блок, показывать размер пустого блока нулей между ними. И если Си-код, растущий вверх, наполз на начало следующего блока (отрицательный размер буфера нулей), сигнализировать об этом.

Может есть ещё какие-то варианты? (хочется только один LOAD ""CODE)

Это будет сильно зависеть от того какая используется ОС (ну или хотя бы окружение) и особенностей компилятора. Там ведь не только С-код растет в область нулей, с ним то как раз проще всего. Обычно выше кода еще размещается куча, рост и освобождение которой в процессе выполнения кода конечно можно просчитать, но довольно муторно. А навстречу куче с верхнего предела пользовательской области растет стек который в таком случае тоже надо бы по-хорошему контролировать (или просчитать).

Поэтому например в CP/M лет пятьдесят назад было принято такие "драйвера" загружать так. В начале адресного пространства стояло 2 JMP на начало (огрубляю для упрощения) BIOS и BDOS ОС (их ставила ОС - она занимала верхние адреса ОЗУ). С-код при своей инициализации по ним всегда определял верхнюю границу пользовательской памяти и далее назначал кучу и стек. Т.е. было достаточно перед стартом C-кода под потолком пользовательского ОЗУ (т.е. ниже реального начала ОС) разместить тот "драйвер" (который включает в начале своего кода JMP BDOS; JMP BIOS) и переназначить те 2 адреса в начале адресного пространства на переходы в начале кода "драйвера". Далее при старте С-кода всё происходило само и не было никаких привязок ни к размеру пользовательского ОЗУ, ни к размеру того "драйвера", ни к размеру C-кода, ни необходимости чего-то просчитывать: С-процессу тупо либо хватало места в ОЗУ, либо нет (т.е. при достаточности ОЗУ никогда ничего ни на что не наползало).

SfS
06.06.2018, 19:20
Оффтопик. В связи с тем, что github был куплен микрософтом, а всё, что покупает микрософт, превращается в *****, я переезжаю на gitlab: https://gitlab.com/salextpuru/

В порядке бреда: а почему ещё тут нет репозитория? Тогда все спекпроекты могли бы сюда кидать и к вики привязывать. Достоинства просты: люди видели бы что делают другие и ничего бы не терялось. ну это так.. мыслищи вслух...

SfS
18.06.2018, 09:29
Тишина. Сразу видно, лето наступило) Народ разбежался)

Shiny
18.06.2018, 09:57
срочно ищи компилер!

Shiny
18.06.2018, 18:56
https://pp.userapi.com/c841630/v841630731/7bc03/4J44ZUncMWk.jpg

SfS
19.06.2018, 07:25
Что с твоей уверенностью?) Кто её так?)

Shiny
19.06.2018, 08:42
Что с твоей уверенностью?) Кто её так?)

просто аноят невнятные сообщения из компилеров sdcc и прочее.

SfS
12.08.2018, 19:37
Пока что бессвязное, но уже всё-таки хоть какое-то описание исходников инвитры для CSP2018. Вдруг кому поможет в чём-нибудь. https://github.com/salextpuru/sdcc-noinit/blob/master/doc/sdcc-csp2018invitro.pdf