PDA

Просмотр полной версии : Взялся я писать статью... SDCC как всегда:)



SfS
26.12.2018, 17:43
Итак, взялся я писать статью, забыв про новый год. И меня понесло. 12 страниц про динамическое связывание и подгружаемые модули на SDCC (SDCC-NOINIT). С примерами.

С одной стороны мне горетно, что в новогодние издания она не войдет. С другой - радостно, что всё ж написал.

Так что выкладываю её на обзор. Опечаток там наверное много и других оговорок. Но что получилось, то получилось. Вдруг кому интересно.

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

----------------------------------------------------------------------------------------------------
Итак статья https://github.com/salextpuru/sdcc-noinit/blob/master/doc/sdcc-art2.pdf
----------------------------------------------------------------------------------------------------

Примеры там же:
https://github.com/salextpuru/sdcc-noinit/tree/master/apps/test-so
https://github.com/salextpuru/sdcc-noinit/tree/master/libsrc/libtestso
https://github.com/salextpuru/sdcc-noinit/tree/master/libsrc/libso

Другая дока по SDCC-NOINIT:
https://github.com/salextpuru/sdcc-noinit/tree/master/doc
https://github.com/salextpuru/sdcc-noinit

JV-Soft
26.12.2018, 19:12
SfS, теперь ядро надо и графический интерфейс :)

SfS
26.12.2018, 19:26
SfS, теперь ядро надо и графический интерфейс :)

Пока бы менеджер памяти осилить. Там проблема - как данные между страничками передавать при вызове...

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

Да и в одного както грустно творить чтото большое.:)

Shiny
26.12.2018, 19:58
https://www.meme-arsenal.com/memes/7a85b7146ccff9d2ce47d2372c6c65fd.jpg

Oleg N. Cher
26.12.2018, 22:06
SfS, красава! Направление взял чёткое, без базара.
Придерусь к частности. ИМХО зря использовал HL вот здесь:

http://i.piccy_.info/i9/010e0689b9deaeaaa9d699f42b68aee8/1545851152/31065/1214670/DynLib.png
Лучше взять BC или DE. Чтобы иметь возможность использовать в функциях модель вызова __z88dk_fastcall с передачей аргумента в паре HL.

Barmaley_m
27.12.2018, 01:37
Отличный проект и красивая реализация! Спасибо! Очень пригодится как компонент будущей ОСи.

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

Также присоединяюсь к мнению Oleg N. Cher:


Придерусь к частности. ИМХО зря использовал HL вот здесь:
...
Лучше взять BC или DE.
А по-моему лучше вообще не использовать никаких регистров. Кроме программистов на Си встречаются ещё программисты на ассемблере, которые передают параметры в регистрах. Например, "резидентная интерфейсная часть" (в английском используется термин "Import Library") может состоять из команд JP 0, JP 3, JP 6 и т.д., которые изменяются в ходе настройки основной программы на фактический адрес загрузки модулей.

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

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


Там проблема - как данные между страничками передавать при вызове...
Я тоже думал над этой проблемой. Пришел к следующим идеям:

1) Исполняемые файлы и динамические библиотеки состоят из сегментов. Paged Code/data - код или данные, которые можно размещать в страницах (C000-FFFF); Nonpaged Code/data - то, что необходимо размещать вне страниц, в резидентной памяти. Сегменты реализованы в современных исполняемых форматах (Windows EXE, ELF). Упомянутый подход реализован для драйверов Винды, где часть кода или данных загрузчик размещает в "дорогой" резидентной памяти (Nonpaged Pool), а остальные - в той памяти, которая может свопиться.

2) Системный менеджер памяти принимает параметр - какая требуется память: резидентная (которой мало), страничная в текущей странице (которой тоже мало, но предпочтительно использовать её) или же страничная в любой странице (которой много, но доступ неудобный).

3) Программист должен стремиться свести к минимуму перемещения данных между страницами и использование Nonpaged Memory. Вызовы функций можно разделить на "близкие" (когда вызываемый код находится в резидентной памяти или той же странице); и "далёкие" - посредством системной функции, переключающей страницу перед вызовом и после возврата.

4) Для крайних случаев сделать системные функции вроде "Far memory Read" и "Far memory Write", которые перемещают данные из "чужой" или "в чужую" страницы.

5) Резидентный код может вызывать системные фукнции переключения страниц и иметь непосредственный доступ к памяти из любых страниц.

Да и в одного както грустно творить чтото большое.:)
Ну дык, аналогично. Давай скооперируемся. Я уже выкладывал прототип диспетчера многозадачности. С тех пор пришло много идей его улучшения, грустно только было за это браться ввиду отсутствия единомышленников! Также я недавно выложил свой оконный интерфейс, драйверы клавиатур, диска. Этот код старый, но тоже может быть тщательно переработан и выведен на современные стандарты качества. За последнюю неделю занимался функциями быстрого вывода текста. Выложить только не успел еще.

SfS
27.12.2018, 05:30
А по-моему лучше вообще не использовать никаких регистров. Кроме программистов на Си встречаются ещё программисты на ассемблере, которые передают параметры в регистрах. Например, "резидентная интерфейсная часть" (в английском используется термин "Import Library") может состоять из команд JP 0, JP 3, JP 6 и т.д., которые изменяются в ходе настройки основной программы на фактический адрес загрузки модулей.

Отвечу сразу обоим.

Не может резидентная часть "состоять из команд JP 0, JP 3, JP 6 и т.д., которые изменяются в ходе настройки основной программы" и вот почему. Я там кратко упомянул (потом дополню), что задача резидентной части не просто переход, но и обращение к менеджеру памяти для впечатывания нужной странички, той, в которой лежит данная библиотека. Поэтому, там придётся много чего использовать. И fastcall не выйдет. Опять же ограничение - стек должен быть в НЕПЕРЕКЛЮЧАЕМОЙ странице на момент обращения к библиотеке.

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

Тут выбор простой - или "все предельно быстро" или "всё стандартно и по возможности быстро".

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

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


Кроме программистов на Си встречаются ещё программисты на ассемблере, которые передают параметры в регистрах

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

Если немного философии-болтологии, то так. Как бы нам ни хотелось - любой ЯВУ это прежде всего стандарт. А стандарт - это рамки и ограничения. Зато и возможности быстро соединять разные модули воедино. Собственно, отсутствие стандартов на порты, системные вызовы и прочее и убило в своё время спектрум. Точнее убило возможности логичного расширения его аппаратной и программной архитектуры.

Поэтому для "программистов на ассемблере" - остаётся ассемблер. Пусть хоть jump через stack себе там засовывают по ret на call. Но если они хотят, чтобы их модуль использовали другие, то им не сложно будет сделать интерфейсную часть, совместимую со стандартом - например забрать параметры со стека или отдать их в нужном регистре.

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


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

Я не против кооперации. Но есть проблема - мой абсолютно непредсказуемый и невменяемый график. Я вот несколько месяцев вообще ни за что не брался. Загруз был полный. Появилось время - за недельку по вечерам накидал описалово и доработал модульность. Кстати, описалово я больше для себя делаю. Пока код пишешь вроде все логично. А как возмешься его объяснять - другим и себе - сразу начинают косяки всплывать, которые не заметил.

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

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

О каком "тулчейне венды" речь? Если о SDCC-NOINIT - то https://www.cygwin.com/ должен пойти.

SfS
27.12.2018, 18:48
В общем как сделать прозрачный и удобный вызов функций при мягком связывании, если есть много страничек памяти - голову ломаю...

Shiny
27.12.2018, 21:22
Для Shiny

О каком "тулчейне венды" речь? Если о SDCC-NOINIT - то https://www.cygwin.com/ должен пойти.

кхм. а можно привести пример компиляции сырка для чайников и сковородок?

Barmaley_m
28.12.2018, 03:41
Не может резидентная часть "состоять из команд JP 0, JP 3, JP 6 и т.д., которые изменяются в ходе настройки основной программы" и вот почему. Я там кратко упомянул (потом дополню), что задача резидентной части не просто переход, но и обращение к менеджеру памяти для впечатывания нужной странички, той, в которой лежит данная библиотека. Поэтому, там придётся много чего использовать. И fastcall не выйдет.
Понятно. Ну что ж, соглашусь. Если всякий раз сохранять регистры, используемые при переключении страницы, в стек, а потом их восстанавливать - то это будет по скорости не лучше, чем передача параметров сразу через стек.

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

С остальным сказанным согласен.

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

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


В общем как сделать прозрачный и удобный вызов функций при мягком связывании, если есть много страничек памяти - голову ломаю...
У тебя же есть точка входа _hl_jumper. Вот и возвращать её адрес и требуемое значение hl из твоего аналога функции GetProcAddress.

Ну или добавить к резидентной части каждого модуля функцию "CallProcModule", которая будет принимать один параметр и прыгать на _hl_jumper. Значение же этого параметра будет возвращать GetProcAddress.

SfS
28.12.2018, 07:07
У тебя же есть точка входа _hl_jumper. Вот и возвращать её адрес и требуемое значение hl из твоего аналога функции GetProcAddress.

Ну или добавить к резидентной части каждого модуля функцию "CallProcModule", которая будет принимать один параметр и прыгать на _hl_jumper. Значение же этого параметра будет возвращать GetProcAddress.

Она есть только если есть есть резидентная часть. Если я просто загрузил модуль и нашёл в нем функцию по имени, то ни точки _hl_jumper нет.
Наверное придётся в библиотеку libso какойто универсальный кусочек пихать для вызова функций. Я подумаю, в общем.

SfS
31.12.2018, 11:29
В общем долго думал. Придется делать отдельную функцию, синтезирующую код вызова библиотеки на страничке. Все равно идеально не выходит.
Да и надо начать с менеджера кучи. Без менеджера памяти (страничка+куча) вообще не получится.

Shiny
31.12.2018, 11:48
кстати, а как проще реализовать вывод на экран? переписать crt0.s?

SfS
31.12.2018, 12:51
кстати, а как проще реализовать вывод на экран? переписать crt0.s?

Нет. Стандартная процедура вывода (через printf) требует функции putchar(char c). У меня она реализована (для стандартного экрана) в файле libsrc/libconio/conio_s.s

Если хочется свою - напиши свою процедуру в отдельной библиотеке и линкуй библиотеку в программу.

Но на стандартный экран вывод идет сразу. Цвета можно выставлять процедурами libconio - color(цвет) и ccls(цвет)

Shiny
31.12.2018, 13:45
гляну попозже. все-же неясно - бинарь получен, и как обойтись с печатью
глянул внутрь - весь long работает через (IX+nn), несмотря на Hitech-C *facepalm*

SfS
31.12.2018, 14:57
Там и тапки и хобеты генерятся. Если ты про SDCC-NOINIT

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

Ну не весь. Взвращается лонг в dehl

Shiny
31.12.2018, 15:19
"Там" не для меня

SfS
31.12.2018, 15:35
А чего ты делаешь то?

Shiny
31.12.2018, 16:01
https://s00.yaplakal.com/pics/pics_original/0/6/5/4566560.jpg
Эксперимент это был. На предмет рационализаторского предложения

SfS
31.12.2018, 17:41
Ничего не понял)
Кому чего предложили?)

Shiny
31.12.2018, 18:00
Хм. надо сделать отдельный трэд "sdcc для чайников" xD

просто хочется разобраться самому, а не на готовом.

SfS
01.01.2019, 10:01
Шиня, ты напиши список внятных вопросов, что тебя волнует в SDCC.
Я попробую на них ответить. Ну конечно то, что знаю и понимаю.
Так и тебе и другим полезно будет.
Можно на основе их и сделать для кофейников статью или руководство.

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

https://github.com/salextpuru/sdcc-noinit/blob/master/doc/sdcc-noinit.pdf

Здесь в разделах c 3 по 5 подробно описано как из исходников получается бинарь. Для SDCC вообще. Спроси что непонятно.

Shiny
02.01.2019, 12:26
Что-то вышло замудрено.

сборка:


set PATH=d:\!!____________prj\SDCC\bin\;%PATH%
sdcc -mz80 --no-std-crt0 --code-loc 0x8000 --data-loc 0 pi.c

hexameter pi.ihx
pause


в итоге получаю



?ASlink-Warning-Undefined Global '_putchar' referenced by module 'vprintf'


Как подпихнуть crt0.s ? и как его нужно изменить для печати? сов7 туплю.

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

ага, на сайте CPC было решение:

putchar_zx.s


;; FILE: putchar.s
;; Modified to suit execution on the Amstrad CPC
;; by H. Hansen 2003
;; Original lines has been marked out!

.area _CODE
_putchar::
_putchar_rr_s::
ld hl,#2
add hl,sp

ld a,(hl)
rst 16 ; call 0xBB5A
ret

_putchar_rr_dbs::

ld a,e
rst 16 ; call 0xBB5A
ret



причем ассемблер так прост, что давится на rst 10h

сборка:


set PATH=d:\!!____________prj\SDCC\bin\;%PATH%

sdasz80 -o putchar_zx.s

sdcc -mz80 --code-loc 0xA000 --data-loc 0 --no-std-crt0 putchar_zx.rel pi.c

hexameter pi.ihx
pause


Тащемта, новые способы создания носителей не интересны, наверное можно взять appmake.exe из z88 или собрать scl/trd на ужясме.

Вот только непонятна инициализация печати:



ld a,2
call $1601

которую приходится впихивать в загрузчик.

Дальше смешнее. Вот исходник(pi.c):


#include <stdio.h>

int main()
{
int r[2800 + 1];
int i, k;
int b, d;
int c;

c=0;
for (i = 0; i < 2800; i++) {
r[i] = 2000;
}

for (k = 2800; k > 0; k -= 14) {
d = 0;

i = k;
for (;;) {
d += r[i] * 10000;
b = 2 * i - 1;

r[i] = d % b;
d /= b;
i--;
if (i == 0) break;
d *= i;
}
printf("%.4d", c + d / 10000);
c = d % 10000;
}

return 0;
}


Всё компилится, но при запуске печатается сплошное непотребство. На cp/m HiTech-C программа работает, если поменять типы данных с int на long.
Меняю так же, получаю фигувам.
http://nsn.fm/upload/iblock/940/9402f5c13d8b4a7759bb927e34a66380.jpg

В чем причина неясно - то ли сам накосячил, то ли в другом?

SfS
03.01.2019, 10:32
А что именно должно печататься и что печатается?

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

Можно отдельно скомпилировать файл для putchar и отдельно программу. Получить отдельно два *.rel файла и потом слиноковать их.

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

Я сейчас не дома. Приеду завтра домой и проверю твою прогу.

Shiny
03.01.2019, 12:34
в идеале должно быть 31415927.

SfS
04.01.2019, 14:57
Итак, начнем.

По умолчанию printf() в SDCC вообще не печатает float-чисел.

Умолчательный crt0.s ни фига не подходит для ZX-SPECTRUM. Надо его чуть отрехтовать. Дело в том, что умолчательный crt0.s рассчитан на ПЗУ с адреса 0.

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

В общем, главная ошибка в том, что у тебя в алгоритме PI переполнение.
В SDCC int - 16битный. А у тебя сразу 2000 на 10000 множится. И вуаля - косяк.

Надо long int. И все работает. Но медленно.

Короче, работает так:



#include <stdio.h>

void pitest(){
long int r[2800 + 1];
long int i, k;
long int b, d;
long int c;
c=0;

for (i = 0; i < 2800; i++) {
r[i] = 2000;
}

for (k = 2800; k > 0; k -= 14) {
d = 0;
i = k;

for (;;) {
d += r[i] * 10000;
b = 2 * i - 1;
r[i] = d % b;
d /= b;
i--;

if (i == 0) break;

d *= i;
}

printf("%d", (int)(c + d / 10000) );
c = d % 10000;
}
}

int main(){
printf("Hello world\nOk.\n%u %i %d %f\nRunning PI test\nPI=",0xFFFF,0xFFFF,0xFFFF,1.123456);
pitest();
return 0;
}



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

Правильный crt0.s (ну более правильный) такой:



;--------------------------------------------------------------------------
; crt0.s - Generic crt0.s for a Z80
;--------------------------------------------------------------------------

.module crt0
.globl _main

.area _CODE
;; Reset vector
jp init

init:
;; Set stack pointer directly above top of memory.
ld sp,#0x0000

;; Initialise global variables
call gsinit
call _main
jp _exit

;; Ordering of segments for the linker.
.area _HOME
.area _CODE
.area _INITIALIZER
.area _GSINIT
.area _GSFINAL

.area _DATA
.area _INITIALIZED
.area _BSEG
.area _BSS
.area _HEAP

.area _CODE
_exit::

1$:
halt
jr 1$

.area _GSINIT
gsinit::
ld bc, #l__INITIALIZER
ld a, b
or a, c
jr Z, gsinit_next
ld de, #s__INITIALIZED
ld hl, #s__INITIALIZER
ldir
gsinit_next:

.area _GSFINAL
ret



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

PUTCHAR такой прекрасно работает (и \n тоже)



;; FILE: putchar.s

.area _CODE
_putchar::
_putchar_rr_s::
ld hl,#2
add hl,sp

ld a,(hl)

cp #10
jr nz,nocr
ld a,#13
nocr:
rst 16 ; call 0xBB5A
ret



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

ЧТобы все это собрать, надо сделать так. Так, конечно, коряво, зато все по шагам понятно:




# Компилируем С-файл (получаем main.rel)
sdcc -Os -c -mz80 main.c

# Начальный загрузчик и putchar() (получаем crt0.rel и putchar_zx.rel)
sdasz80 -g -l -s -o crt0.rel crt0.s
sdasz80 -g -l -s -o putchar_zx.rel putchar_zx.s

# Получаем hex-файл (main.ihx) с помощью линковки rel-файлов
# Внимание! crt0.rel ДОЛЖЕН БЫТЬ первым в списке линкуемых rel-файлов
sdcc --code-loc 0x6000 --no-std-crt0 -mz80 -o main.ihx crt0.rel putchar_zx.rel main.rel

# 0x6000 = 24576 (Получаем бинарь из HEX-файла)
hex2bin -p 0 -s 0x6000 main.ihx

# Это просто утилита для получения TAP-файла из бинаря в бейсик-загрузчиком.
bin2tap -b -a 24576 -r 24576 main.bin


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

67545

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

67546

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


На cp/m HiTech-C программа работает, если поменять типы данных с int на long.

Так а почему на sdcc подругому? Меняем - и работает:)

И ещё вывод просто %d, а не %.4d.

Shiny
04.01.2019, 15:46
ересь какая-то вышла.
печать неверная и прога валится при расчетах.

SfS
04.01.2019, 16:50
ересь какая-то вышла.
печать неверная и прога валится при расчетах.

То, что я скинул - точно работает. Скриншоты приложил.

Давай по шагам - что делал, как компилил?

Shiny
04.01.2019, 17:06
по твоему описанию так же. Даже версию обновил. вот файлы

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


И ещё вывод просто %d, а не %.4d.

странно. печать неверная по идее.

SfS
04.01.2019, 17:38
странно. печать неверная по идее.

Да, точно. Надо %.4d. Иначе кусочки, начинающиеся с нулей будут теряться.

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

Но твой файл работает. Может прога "hexameter.exe" глючит? Я то в линукс собираю. hex2bin использую. Или SCL как-то не так создаётся?

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

ВРУ. Для печати ведущих нулей надо %04d

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

ну как бы там ни было - твои команды дают нормальный хекс. а потом может бин кривой или SCL ?

Shiny
04.01.2019, 17:40
Вангую, что .bin

.scl компилится ужасмом.

SfS
04.01.2019, 17:48
Кстати, а как насчет clear ? ты ж бейсиковый принт используешь.
по идее, у меня бейсик-загрузчик в tap-файле такой:

10 CLEAR 24575
20 load "" code 24576
30 run USR 24576

В у тебя в SCL ничего не трётся?

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

Попробуй это использовать. У меня оно https://github.com/salextpuru/speccy-toochain/tree/master/src/hex2bin

Точнее hex2bin. Собери под венду.

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

кстати, а SDCC какая версия ? У меня 3.6.0. Может какой глюк самого компилера?

Shiny
04.01.2019, 19:36
Сегодня не мой день(:

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

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


Кстати, а как насчет clear ? ты ж бейсиковый принт используешь

при чем тут clear? стек назначается заранее, а при печати третьей пары цифр глюк на экране.

sdcc такой версии: sdcc-20190103-10790-setup

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

мать моя женщина, проскочило вроде

printf("%4d", (long int)(c + d / 10000) );

SfS,спасибо за терпение и подсказки.
Завтра будет ещё вопросик.

SfS
05.01.2019, 01:51
В hex2bin адрес нужен чтобы он не забивал пустые байты нулем. Вроде так.

Для %d нужен int. То есть printf("%04d", (int)(c + d / 10000) );

Shiny
05.01.2019, 11:07
В общем с (int) те же косяки с печатью. у (long int) нули не печатаются.
"мнение ухудшилось".

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

не, .4d прокатило

SfS
05.01.2019, 16:03
Странно. %d печатает int, а не long по идее.

Shiny
05.01.2019, 16:42
ох, вот сигуру угорают над трэдомhttp://glair.narod.ru/smile/crazy.gif

SfS
05.01.2019, 18:39
Сигуру врядли знают особенности реализации sdcc.

Oleg N. Cher
05.01.2019, 18:49
Да выкиньте вы этот printf, он небось кил 10 весит.

Shiny
05.01.2019, 19:57
Сигуру врядли знают особенности реализации sdcc.

ну не торт, явно. откуда .rel пошли? из cp/m?

по скорости в вычислении pi проигрывает z88 и Hi-Tech C.
вот только засада с разработкой Hi-Tech.

SfS
06.01.2019, 00:51
.rel это просто объектный файл. То же что и .о в юникс например. Формат только другой.
короче скомпилированный код с таблицей перемещения по секциям.
Поскольку ни фига актуального кроме sdcc для z80 нет - используем.

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


Да выкиньте вы этот printf, он небось кил 10 весит.

Чтото около 3К. Но дело то не в принтфе вроде.
У меня все работает.

Shiny
06.01.2019, 12:56
Ну вот видишь, ты разобрался в тонкостях и знаешь, как скомпилировать. Поэтому я и спросил тулчейн, не переходить же на линупс (:

SfS
07.01.2019, 08:58
Ну я использую то, что у меня в гитхабе. Я имею ввиду утилиты.
Ну и гнутые команды - они в cygwin все есть.

Эх. Придется видимо попробовать самому все на цигвине собрать попытаться.

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

Кстати, а что бы и не перейти на линукс?)

Shiny
07.01.2019, 09:20
cygwin'a хватило по уши, когда я взялся за компиляцию одного эмулятора под mini-gw.

про линупс можно сказать много доброго, но это будет офтопом.

Вопрос в том же: как втиснуть код открытия потока:


ld a,2
call $1601


Добавить в crt0.s или куда-то еще?

SfS
08.01.2019, 17:55
Лучше отдельным файлом ассемблера в секцию

.area _GSINIT

Или отдельну функцию сделать.

Но зачем тебе вообще этот поток? На спеке и так все на экран выводится.

Shiny
08.01.2019, 18:19
Но зачем тебе вообще этот поток? На спеке и так все на экран выводится.

Это по старому принципу - "Работает? ради Бога, ничего не трогай!". Ну. или "Так надо".
Просто при загрузке кассеты вывод пойдет на поток, а вот при старте с диска не факт.

и еще вопрос - как удобнее изменить печать текста по позициям? не проще через printf?

SfS
08.01.2019, 18:42
Факт. На экран по умолчанию.

Вставляй управляющие коды и изменяй позицию, цвета.

Только ноль не вставишь.

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

Я не проверял, но printf("\x16\x2\x3"); должно работать как AT 2,3

Shiny
08.01.2019, 19:14
с нулем извечная засада.

А как передаются функции параметры? из putchar() понятно, что через стек.

SfS
08.01.2019, 19:51
Там все через стек передается. А возвращаться может и регистрами.

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

Просто на стек ложатся параметры в том же порядке и того же размера, что описаны в функции. Потом вызов.

Возвращается L - байт, HL - слово. DEHL - двойное слово (32 бит). Вроде так.