Хм. надо сделать отдельный трэд "sdcc для чайников" xD
просто хочется разобраться самому, а не на готовом.
Хм. надо сделать отдельный трэд "sdcc для чайников" xD
просто хочется разобраться самому, а не на готовом.
Шиня, ты напиши список внятных вопросов, что тебя волнует в SDCC.
Я попробую на них ответить. Ну конечно то, что знаю и понимаю.
Так и тебе и другим полезно будет.
Можно на основе их и сделать для кофейников статью или руководство.
- - - Добавлено - - -
https://github.com/salextpuru/sdcc-n...dcc-noinit.pdf
Здесь в разделах c 3 по 5 подробно описано как из исходников получается бинарь. Для SDCC вообще. Спроси что непонятно.
Что-то вышло замудрено.
сборка:
в итоге получаюКод:set PATH=d:\!!____________prj\SDCC\bin\;%PATH% sdcc -mz80 --no-std-crt0 --code-loc 0x8000 --data-loc 0 pi.c hexameter pi.ihx pause
Как подпихнуть crt0.s ? и как его нужно изменить для печати? сов7 туплю.Код:?ASlink-Warning-Undefined Global '_putchar' referenced by module 'vprintf'
- - - Добавлено - - -
ага, на сайте CPC было решение:
putchar_zx.s
причем ассемблер так прост, что давится на rst 10hКод:;; 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
сборка:
Тащемта, новые способы создания носителей не интересны, наверное можно взять appmake.exe из z88 или собрать scl/trd на ужясме.Код: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
Вот только непонятна инициализация печати:
которую приходится впихивать в загрузчик.Код:ld a,2 call $1601
Дальше смешнее. Вот исходник(pi.c):
Всё компилится, но при запуске печатается сплошное непотребство. На cp/m HiTech-C программа работает, если поменять типы данных с int на long.Код:#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; }
Меняю так же, получаю фигувам.
В чем причина неясно - то ли сам накосячил, то ли в другом?
А что именно должно печататься и что печатается?
- - - Добавлено - - -
Можно отдельно скомпилировать файл для putchar и отдельно программу. Получить отдельно два *.rel файла и потом слиноковать их.
- - - Добавлено - - -
Я сейчас не дома. Приеду завтра домой и проверю твою прогу.
в идеале должно быть 31415927.
Итак, начнем.
По умолчанию 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
- - - Добавлено - - -
- - - Добавлено - - -
Так а почему на sdcc подругому? Меняем - и работает
И ещё вывод просто %d, а не %.4d.
ересь какая-то вышла.
печать неверная и прога валится при расчетах.
Да, точно. Надо %.4d. Иначе кусочки, начинающиеся с нулей будут теряться.
- - - Добавлено - - -
Но твой файл работает. Может прога "hexameter.exe" глючит? Я то в линукс собираю. hex2bin использую. Или SCL как-то не так создаётся?
- - - Добавлено - - -
ВРУ. Для печати ведущих нулей надо %04d
- - - Добавлено - - -
ну как бы там ни было - твои команды дают нормальный хекс. а потом может бин кривой или SCL ?
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)