Скачал версию от 20 августа. К кодогенератору имеются следующие замечания:
1) Инициализация данных. Объявив глобальную статическую переменную следующей инструкцией:
static char s[] = "Hello world!";
Я получил процедуру инициализации этой переменной вида:
ld hl, _s
LD (HL), 'H'
ld hl, _s+1
LD (HL),'e'
Что чрезвычайно неэффективно как по скорости исполнения, так и по занимаемой памяти. Более оптимальное решение - это сохранить исходное значение константы в сегменте инициализированных (константных) данных, а потом копировать с помощью LDIR.
---------- Post added at 03:59 ---------- Previous post was at 03:48 ----------
2) Деление на 2 переменной. Инструкция вида
k/=2
где k - стековая 8-битная переменная, привела к генерации кода:
LD A,(IX+6)
SRL A
LD (IX+6),A
Что лучше заменить на
SRL (IX+6)
3) Возведение в квадрат числа. Инструкция вида:
t*=t
где t - unsigned short, привела к генерации кода:
PUSH HL
LD C,(IX+4)
LD B,(IX+5)
PUSH BC
LD C,(IX+4)
LD B,(IX+5)
PUSH BC
CALL __mulint_rrx_s
POP AF
POP AF
LD D,L
LD E,H
POP HL
LD (IX+4),D
LD (IX+5),E
В этом коде, во-первых, нет необходимости загружать BC второй раз, потому что в него загружается одна и та же информация. Обе команды LD между PUSH BC можно выкинуть.
Во-вторых, после возврата из подпрограммы умножения, результат сначала копируется в регистр DE, а потом сохраняется на фрейм. Вместо этого можно сначала сохранить результат прямо из HL, а потом выполнить POP HL. Экономится две команды LD.
Вместе с тем отмечаю, что кодогенератор стал существенно лучше, чем был, и в некоторых моментах я был приятно удивлен результатами его работы. Почти как человек написал. Например, вот так получилась функция strlen:
unsigned short mstrlen(const char* s)
{
unsigned short a = 0;
while(*s++)
a++;
return a;
}
Сгенерированный код:
;test.c:21: unsigned short mstrlen(const char* s)
; ---------------------------------
; Function mstrlen
; ---------------------------------
._mstrlen_start
._mstrlen
;test.c:24: while(*s++)
ld de,$0000
pop bc
pop hl
push hl
push bc
.l_mstrlen00101
ld a,(hl)
inc hl
or a, a
jp Z,l_mstrlen00103
;test.c:25: a++;
inc de
jp l_mstrlen00101
.l_mstrlen00103
;test.c:26: return a;
ex de,hl
.l_mstrlen00104
ret
._mstrlen_end
Что не оставляет желать ничего лучшего. Ну разве что можно было бы продублировать заголовок цикла, как это делается в некоторых современных компиляторах, но нельзя требовать всего сразу![]()




Ответить с цитированием