Итак, начнем.
По умолчанию 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
- - - Добавлено - - -

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

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

Сообщение от
Shiny
На cp/m HiTech-C программа работает, если поменять типы данных с int на long.
Так а почему на sdcc подругому? Меняем - и работает
И ещё вывод просто %d, а не %.4d.