Снял слепки с Avoset, sdcc, z88dk. В ближайшее время попробую проанализировать и их код. У кого еще какие компилеры завалялись?
Снял слепки с Avoset, sdcc, z88dk. В ближайшее время попробую проанализировать и их код. У кого еще какие компилеры завалялись?
Что заметно дешевле KEIL. Так что как сказать...Сообщение от jdigreze
Hitech могу дать.Сообщение от caro
Итак, препарируемый- Avocet. Этот компилятор не понял старого синтаксиса теста (см. заголовки функций), поэтому пришлось слегка его подработать напильником.
Вот что он нагенерил (лишние директивы вырезаны).
0.Пролог
1.Размножение констант и копийКод:;не суть важно, все равно один раз делается... push ix push de push hl ld ix,-?TSC0 add ix,sp push af
2.Свертка константКод:ld hl,2 ld (_j4),hl ;лишняя операция ld de,(_j4) ld hl,(_i2) and a ;использование нативных операций- плюс в копилку sbc hl,de ;хитровымудренная система переходов- жирный минус jp p,$+8 jp pe,?BOL0 jr +3 jp po,?BOL0 ?ACC0: .equal $ ld de,(_j4) ld hl,(_i4) and a sbc hl,de jp p,$+8 jp pe,?BOL0 jr +3 jp po,?BOL0 ?PLC0: .equal $ ld hl,2 ld (_i2),hl ?BOL0: .equal $ ;короче, никаких размножений констант не применяется ;и этот кусок- практически полная копия предыдущего ld hl,(_k5) ld (_j4),hl ld e,l ld d,h ld hl,(_i2) and a sbc hl,de jp p,$+8 jp pe,?BOL1 jr +3 jp po,?BOL1 ?ACC1: .equal $ ld de,(_j4) ld hl,(_i4) and a sbc hl,de jp p,$+8 jp pe,?BOL1 jr +3 jp po,?BOL1 ?PLC1: .equal $ ld hl,3 ld (_i5),hl ?BOL1: .equal $
3.Лишнее присваиваниеКод:;благополучно свернул целочисленные константы ld hl,3 ld (_i3),hl .const_data ?CGL0: .double 8.69999999999999930000 .program ;также свернул дробную ld de,?CGL0 ld hl,_flt_1 call __store_double ;просто константа ld hl,5 ld (_i2),hl ;а это убожество... ld de,0 ld hl,(_i) add hl,de ld (_j2),hl ;здесь не сообразил что на 1 делить не надо... ld de,1 ld hl,(_i) call __div_int ld (_k2),hl ;да и умножать тоже... ld de,1 ld hl,(_i) call __mult_int ld (_i4),hl ;а это вообще хохма ld de,0 ld hl,(_i) call __mult_int ld (_i5),hl ;и на 0 мы делить тоже умеем! :) ;как целочисленно... ld de,0 ld hl,(_i) call __div_int ld (_i2),hl .const_data ?CGL1: .double 0.0 .program ;...так и с плавающей запятой ld de,?CGL1 ld hl,_flt_1 call __div_double ex de,hl ld hl,_flt_2 call __store_double .const_data ?CGL2: .double 2.39999999999999990000 .program ;вот деление константы на константу он свернул ld de,?CGL2 ld hl,_flt_3 call __store_double .const_data ?CGL3: .double 1.00000010000000010000 .program ;сложение тоже ld de,?CGL3 ld hl,_flt_4 call __store_double .const_data ?CGL4: .double 0.0 .program ;но вот умножение на 0 не догадался облагородить ld de,?CGL4 ld hl,_flt_6 call __mult_double ex de,hl ld hl,_flt_5 call __store_double ;ничего интересного ld de,_flt_3 ld hl,_flt_2 call __mult_double ex de,hl ld hl,_flt_6 call __store_double
4.Снижение мощностиКод:;за такое надо руки отрывать... ld hl,1 ld (_k3),hl ld hl,1 ld (_k3),hl
5.Простой циклКод:;никакой фантазии... ld de,(_j5) ld hl,4 call __mult_int ld (_k2),hl ld hl,0 ld (_i),hl ?FLC2: .equal $ ld de,5 ld hl,(_i) and a sbc hl,de ;опять сложная система переходов jr z,+11 jp p,$+8 jp pe,?BOL2 jr +3 jp po,?BOL2 jp ?FLB2 ?FLA2: .equal $ ;регистровые переменные не поддерживаются, ;по крайней мере здесь ld hl,(_i) inc hl ld (_i),hl jp ?FLC2 ?FLB2: .equal $ ;это просто мрак... ld de,2 ld hl,(_i) call __mult_int ld (ix+0),l ld (ix+0+1),h ld hl,(_i) add hl,hl ld bc,_ivector4 add hl,bc ld e,l ld d,h ;люди, не смотрите на это :) ld l,(ix+0) ld h,(ix+0+1) push de pop iy ld (iy+0),l ld (iy+1),h jp ?FLA2 ?BOL2: .equal $
6.Управление переменной индукции циклаКод:ld hl,0 ld (_j5),hl ld hl,10000 ld (_k5),hl ?TOL3: .equal $ ;просто ни ума, ни фантазии... ld de,1 ld hl,(_k5) and a sbc hl,de ld (_k5),hl ld de,1 ld hl,(_j5) add hl,de ld (_j5),hl ld de,3 ld hl,(_k5) call __mult_int ld (ix+0),l ld (ix+0+1),h ld de,5 ld hl,(_j5) call __mult_int ld e,l ld d,h ld l,(ix+0) ld h,(ix+0+1) call __div_int ld (_i5),hl ?DCL3: .equal $ ;просто верх кодерского разума- сравнение на 0... ld de,0 ld hl,(_k5) and a sbc hl,de jp z,?BOL3 jp p,$+8 jp po,?BOL3 jr +3 jp pe,?BOL3 ?PLC2: .equal $ jp ?TOL3 ?BOL3: .equal $
7. Глубокие подвыраженияКод:;достаточно приличный заголовок цикла ld hl,0 ld (_i),hl ?FLC4: .equal $ ld de,100 ld hl,(_i) and a sbc hl,de jp p,$+8 jp pe,?BOL4 jr +3 jp po,?BOL4 jp ?FLB4 ?FLA4: .equal $ ld hl,(_i) inc hl ld (_i),hl jp ?FLC4 ?FLB4: .equal $ ;а здесь начинаются страшные вычисления без каких ;бы то ни было следов оптимизации ld de,2 ld hl,(_i) call __mult_int ld e,l ld d,h ld hl,3 add hl,de add hl,hl ld bc,_ivector5 add hl,bc ld e,l ld d,h ld hl,5 push de pop iy ld (iy+0),l ld (iy+1),h jp ?FLA4 ?BOL4: .equal $
8.Генерация адреса переменной с константным индексом, размножение копий и регистровКод:;без слов. все и так видно... ld de,10 ld hl,(_i) and a sbc hl,de jp p,$+8 jp pe,?BOL5 jr +3 jp po,?BOL5 ?PLC3: .equal $ ld de,(_i2) ld hl,(_i5) add hl,de ld (_j5),hl jp ?EOI5 ?BOL5: .equal $ ld de,(_i2) ld hl,(_i5) add hl,de ld (_k5),hl ?EOI5: .equal $
9.Удаление общих подвыраженийКод:ld hl,_ivector+0 ld e,l ld d,h ld hl,1 ;ребята наверное не знают про команду ld (hl),.. push de pop iy ld (iy+0),l ld (iy+1),h ld hl,(_i2) add hl,hl ld bc,_ivector add hl,bc ld e,l ld d,h ld hl,2 push de pop iy ld (iy+0),l ld (iy+1),h ld hl,(_i2) add hl,hl ld bc,_ivector add hl,bc ld e,l ld d,h ld hl,2 push de pop iy ld (iy+0),l ld (iy+1),h ld hl,_ivector+4 ld e,l ld d,h ld hl,3 push de pop iy ld (iy+0),l ld (iy+1),h
10.Вынесение инвариантного кодаКод:ld de,(_k3) ld hl,(_h3) add hl,de ld de,0 and a sbc hl,de jp p,$+8 jp po,?PLC4 jr +3 jp pe,?PLC4 ?OCC2: .equal $ ld de,(_k3) ld hl,(_h3) add hl,de ld de,5 and a sbc hl,de jp z,?BOL6 jp p,$+8 jp po,?BOL6 jr +3 jp pe,?BOL6 ?PLC4: .equal $ .const_data ?PLC5: .byte "Common subexpression elimination",0ah,0 .program ld hl,?PLC5 call _printf jp ?EOI6 ?BOL6: .equal $ ;иными словами, никаких выделений не производится ld de,(_k3) ld hl,(_h3) add hl,de ld de,(_i3) call __div_int ld (_m3),hl ld de,(_k3) ld hl,(_h3) add hl,de ld e,l ld d,h ld hl,(_i3) add hl,de ld (_g3),hl ?EOI6: .equal $
Код:;приемлимое начало цикла ld hl,0 ld (_i4),hl ?FLC7: .equal $ ld de,2 ld hl,(_i4) and a sbc hl,de jr z,+11 ;но его структура в коде просто ужасна! jp p,$+8 jp pe,?BOL7 jr +3 jp po,?BOL7 jp ?FLB7 ?FLA7: .equal $ ld hl,(_i4) inc hl ld (_i4),hl jp ?FLC7 ?FLB7: .equal $ ;никакого вынесения нет- вычисления на каждой итерации ld de,(_k) ld hl,(_j) call __mult_int ld (ix+0),l ld (ix+0+1),h ld hl,(_i4) ld bc,_ivector2 add hl,bc ld e,l ld d,h ld l,(ix+0) ld h,(ix+0+1) ld a,l ld (de),a jp ?FLA7
11.Вызов функции с аргументами. Определение недостижимого кода
Код:.const_data ?PLC6: .byte "This line should not be printed",0 .program ;хоть тут никаких изысков, параметры в регистрах ld de,?PLC6 ld hl,1 call _dead_code12.Вызов функции без аргументов. Исключение цикловКод:_dead_code: .equal $ ;страшный пролог! push ix push de push hl ld ix,-?TSC1 add ix,sp push af ld l,(ix+0+?TSC1) ld h,(ix+0+?TSC1+1) ld (ix-2),l ld (ix-2+1),h ;страх и ужас! ld a,0 cp a,0 jp z,?BOL8 ?PLC7: .equal $ .const_data ?PLC8: .byte "%s",0ah,0 .program ld e,(ix+2+?TSC1) ld d,(ix+2+?TSC1+1) ld hl,?PLC8 call _printf ?BOL8: .equal $ ?BOF1: .equal $ ;и не менее страшный эпилог pop bc pop bc pop bc pop ix ret
Код:;как обычно, ничего никуда не передаем call _unnecessary_loop13. Слияние заголовков цикловКод:_unnecessary_loop: .equal $ push ix ld ix,-?TSC2 add ix,sp push af ;все тот же кошмарный пролог... ld hl,0 ld (ix-2),l ld (ix-2+1),h ld hl,0 ld (_i),hl ?FLC9: .equal $ ld de,5 ld hl,(_i) and a sbc hl,de jp p,$+8 jp pe,?BOL9 jr +3 jp po,?BOL9 jp ?FLB9 ?FLA9: .equal $ ld hl,(_i) inc hl ld (_i),hl jp ?FLC9 ?FLB9: .equal $ ;постоянные вычисления, тут даже пресловутое ;примечание опускает руки :) ld de,(_j5) ld l,(ix-2) ld h,(ix-2+1) add hl,de ld (_k5),hl jp ?FLA9 ?BOL9: .equal $ ?BOF2: .equal $ pop bc pop ix ret
14.Разворачивание цикловКод:_loop_jamming: .equal $ push ix push hl ld ix,-?TSC3 add ix,sp ld hl,0 ld (_i),hl ?FLC10: .equal $ ld de,5 ld hl,(_i) and a sbc hl,de jp p,$+8 jp pe,?BOL10 jr +3 jp po,?BOL10 jp ?FLB10 ?FLA10: .equal $ ld hl,(_i) inc hl ld (_i),hl jp ?FLC10 ?FLB10: .equal $ ld de,(_i) ld hl,(_j5) call __mult_int ld e,l ld d,h ld l,(ix+0+?TSC3) ld h,(ix+0+?TSC3+1) add hl,de ld (_k5),hl jp ?FLA10 ?BOL10: .equal $ ;никакого слияния плюс страшные вычисления ld hl,0 ld (_i),hl ?FLC11: .equal $ ld de,5 ld hl,(_i) and a sbc hl,de jp p,$+8 jp pe,?BOL11 jr +3 jp po,?BOL11 jp ?FLB11 ?FLA11: .equal $ ld hl,(_i) inc hl ld (_i),hl jp ?FLC11 ?FLB11: .equal $ ld de,(_k5) ld l,(ix+0+?TSC3) ld h,(ix+0+?TSC3+1) call __mult_int ld e,l ld d,h ld hl,(_i) call __mult_int ld (_i5),hl jp ?FLA11 ?BOL11: .equal $ ?BOF3: .equal $ pop bc pop ix ret
15.Сжатие цепочки переходовКод:_loop_unrolling: .equal $ push ix push hl ld ix,-?TSC4 add ix,sp ld hl,0 ld (_i),hl ?FLC12: .equal $ ;разворота нет ld de,6 ld hl,(_i) and a sbc hl,de jp p,$+8 jp pe,?BOL12 jr +3 jp po,?BOL12 jp ?FLB12 ?FLA12: .equal $ ld hl,(_i) inc hl ld (_i),hl jp ?FLC12 ?FLB12: .equal $ ;да еще и вычисления страшные ld hl,(_i) ;хоть не догадался умножать на 2 процедурой... add hl,hl ld bc,_ivector4 add hl,bc ld e,l ld d,h ld hl,0 push de pop iy ld (iy+0),l ld (iy+1),h jp ?FLA12 ?BOL12: .equal $ ?BOF4: .equal $ pop bc pop ix ret
Итоговая оценка- 4/10. Поставил бы 3/10, да понравился достаточно легкий заголовок цикла.Код:_jump_compression: .equal $ push ix push de push hl ld ix,-?TSC5 add ix,sp .c_start 0ba1h,260 ?beg_1: .equal $ ld e,(ix+2+?TSC5) ld d,(ix+2+?TSC5+1) ld l,(ix+0+?TSC5) ld h,(ix+0+?TSC5+1) and a sbc hl,de jp p,$+8 jp pe,?BOL13 jr +3 jp po,?BOL13 ?PLC9: .equal $ ld e,(ix+8+?TSC5) ld d,(ix+8+?TSC5+1) ld l,(ix+2+?TSC5) ld h,(ix+2+?TSC5+1) and a sbc hl,de jp p,$+8 jp pe,?BOL14 jr +3 jp po,?BOL14 ?PLC10: .equal $ ld e,(ix+10+?TSC5) ld d,(ix+10+?TSC5+1) ld l,(ix+8+?TSC5) ld h,(ix+8+?TSC5+1) and a sbc hl,de jp p,$+8 jp pe,?BOL15 jr +3 jp po,?BOL15 ?PLC11: .equal $ ld e,(ix+12+?TSC5) ld d,(ix+12+?TSC5+1) ld l,(ix+10+?TSC5) ld h,(ix+10+?TSC5+1) and a sbc hl,de jp p,$+8 jp pe,?BOL16 jr +3 jp po,?BOL16 ?PLC12: .equal $ ld e,(ix+12+?TSC5) ld d,(ix+12+?TSC5+1) ld l,(ix+10+?TSC5) ld h,(ix+10+?TSC5+1) add hl,de ld (ix+10+?TSC5),l ld (ix+10+?TSC5+1),h jp ?EOI16 ?BOL16: .equal $ ;нет оптимизации jp ?end_1 ?EOI16: .equal $ jp ?EOI15 ?BOL15: .equal $ ld e,(ix+10+?TSC5) ld d,(ix+10+?TSC5+1) ld l,(ix+8+?TSC5) ld h,(ix+8+?TSC5+1) add hl,de ld (ix+8+?TSC5),l ld (ix+8+?TSC5+1),h ?EOI15: .equal $ jp ?EOI14 ?BOL14: .equal $ ld e,(ix+8+?TSC5) ld d,(ix+8+?TSC5+1) ld l,(ix+2+?TSC5) ld h,(ix+2+?TSC5+1) add hl,de ld (ix+2+?TSC5),l ld (ix+2+?TSC5+1),h ?end_1: .equal $ jp ?beg_1 ?EOI14: .equal $ jp ?EOI13 ?BOL13: .equal $ ld e,(ix+2+?T ;а дальше текст почемуто потерян...
Плюс данный компилятор распространяетя со средой разработки и отладки под винду. Опций настройки я не нашел- они задавались в настройках проекта, но в хелпе я нашел не все указанные опции. Про оптимизацию там не было сказано ни слова. Итого- это просто транслятор с примитивной сверткой констант (и только!). Выходной ассемблерный файл без указания строк исходного файла, весьма неудобно по нему лазить.
Короче, использовать не рекомендуется![]()
Следующий кандидат- Small Device C Compiler
Испытания проводились с оптимизацией по размеру и по скорости- результат одинаковый.
0. Пролог.
1. Тест на размножение констант и копий.Код:;классика жанра для переменных в стеке _main: push ix ld ix,#0 add ix,sp
2.Свертка константКод:;жирный-жирный минус- использование тяжелой ;артиллерии в виде индексных регистров ;test.c:59: j4 = 2; ld iy,#_j4 ld 0(iy),#0x02 ld 1(iy),#0x00 ;test.c:60: if( i2 < j4 && i4 < j4 ) ;вот оно- распространение констант в действии!!! ld iy,#_i2 ;вместо вычитания j4 используется вычитание константы ld a,0(iy) sub a,#0x02 ld a,1(iy) sbc a,#0x00 jp p,00102$ ;аналогично вторая половина ld iy,#_i4 ld a,0(iy) sub a,#0x02 ld a,1(iy) sbc a,#0x00 jp p,00102$ ;test.c:61: i2 = 2; ;опять IY... ld iy,#_i2 ld 0(iy),#0x02 ld 1(iy),#0x00 00102$: ;test.c:63: j4 = k5; ;ну почему загрузка сделана нормально, но сохранение ;так лажово? ld hl,(_k5) ld iy,#_j4 ld 0(iy),l ld 1(iy),h ;test.c:64: if( i2 < j4 && i4 < j4 ) ;просто страшная перезагрузка!!! нет использования ;предыдущего операнда в hl!!! ld iy,#_i2 ld a,0(iy) ld iy,#_j4 sub a,0(iy) ld iy,#_i2 ld a,1(iy) ld iy,#_j4 sbc a,1(iy) jp p,00105$ ;то же самое... ld iy,#_i4 ld a,0(iy) ld iy,#_j4 sub a,0(iy) ld iy,#_i4 ld a,1(iy) ld iy,#_j4 sbc a,1(iy) jp p,00105$ ;test.c:65: i5 = 3; ld iy,#_i5 ld 0(iy),#0x03 ld 1(iy),#0x00 00105$:
3.Лишнее присваиваниеКод:;test.c:72: i3 = 1 + 2; ;свернул ld iy,#_i3 ld 0(iy),#0x03 ld 1(iy),#0x00 ;test.c:73: flt_1 = 2.4 + 6.3; ;вот здесь использование индексных регистров можно ;оправдать, да и то с натяжкой... ld iy,#_flt_1 ld 0(iy),#0x33 ld 1(iy),#0x33 ld 2(iy),#0x0B ld 3(iy),#0x41 ;test.c:74: i2 = 5; ld iy,#_i2 ld 0(iy),#0x05 ld 1(iy),#0x00 ;test.c:75: j2 = i + 0; ;0 не стал добавлять, просто копирование ld hl,(_i) ld iy,#_j2 ld 0(iy),l ld 1(iy),h ;test.c:76: k2 = i / 1; ;и на 1 делить не стал ld hl,(_i) ld iy,#_k2 ld 0(iy),l ld 1(iy),h ;test.c:77: i4 = i * 1; ;да и умножать тоже ld hl,(_i) ld iy,#_i4 ld 0(iy),l ld 1(iy),h ;test.c:78: i5 = i * 0; ;сообразительный малый :) ld iy,#_i5 ld 0(iy),#0x00 ld 1(iy),#0x00 ;test.c:88: printf( "This compiler handles divide-by-zero as ;деление на 0 не словил на этапе комппиляции, пытается ;печатать ;передача параметров через стек- не очень хорошо... ld hl,#__str_0 push hl call _printf ;и очистка вызывающей функцией- классическая ;парадигма _cdecl pop af ;test.c:91: flt_3 = 2.4 / 1.0; ;с плавающей запятой константы тоже сворачивает ld iy,#_flt_3 ld 0(iy),#0x9A ld 1(iy),#0x99 ld 2(iy),#0x19 ld 3(iy),#0x40 ;test.c:92: flt_4 = 1.0 + 0.0000001; ld iy,#_flt_4 ld 0(iy),#0x01 ld 1(iy),#0x00 ld 2(iy),#0x80 ld 3(iy),#0x3F ;test.c:93: flt_5 = flt_6 * 0.0; ;молодец :) ld iy,#_flt_5 ld 0(iy),#0x00 ld 1(iy),#0x00 ld 2(iy),#0x00 ld 3(iy),#0x00 ;test.c:94: flt_6 = flt_2 * flt_3; ;распространение константы flt_3 = 2.4 ld hl,#0x4019 push hl ld hl,#0x999A push hl ld hl,(_flt_2 + 2) push hl ld hl,(_flt_2) push hl call ___fsmul ;заволновался по поводу hl... ld b,h ld c,l ;освобождение стека- 8 байт pop af pop af pop af pop af ld iy,#_flt_6 ld 0(iy),c ld 1(iy),b ld 2(iy),e ld 3(iy),d
4.Снижение мощностиКод:;test.c:101: k3 = 1; ;было благополучно удалено! ld iy,#_k3 ld 0(iy),#0x01 ld 1(iy),#0x00
5.Простой циклКод:;test.c:107: k2 = 4 * j5; ;это просто "шедевр"! это надо видеть!!! ld iy,#_j5 ld a,0(iy) ld iy,#_k2 ld 0(iy),a ld iy,#_j5 ld a,1(iy) ld iy,#_k2 ld 1(iy),a ;впервые на манеже ТАКИЕ извращения при попытке ;заменить умножение сдвигами :) ld a,#0x02+1 jp 00146$ 00145$: ld iy,#_k2 sla 0(iy) rl 1(iy) 00146$: dec a jp nz,00145$ ;test.c:108: for( i = 0; i <= 5; i++ ) ;переменная цикла тоже в индексном... грустно... ld iy,#_i ld 0(iy),#0x00 ld 1(iy),#0x00 00117$: ld a,#0x05 ld iy,#_i sub a,0(iy) ld a,#0x00 sbc a,1(iy) jp m,00120$ ;test.c:109: ivector4[ i ] = i * 2; ;мрачно... ld c,0(iy) ld b,1(iy) sla c rl b ld hl,#_ivector4 add hl,bc ;так и не понял, для чего эти две команды... ld e,l ld d,h ld (hl),c inc hl ld (hl),b ;test.c:108: for( i = 0; i <= 5; i++ ) ;а вот это небольшой финт- полупересчетка ld iy,#_i inc 0(iy) jp nz,00149$ inc 1(iy) 00149$: jp 00117$ 00120$:
6.Управление переменной индукции циклаКод:;test.c:115: j5 = 0; ld iy,#_j5 ld 0(iy),#0x00 ld 1(iy),#0x00 ;test.c:116: k5 = 10000; ld iy,#_k5 ld 0(iy),#0x10 ld 1(iy),#0x27 ;test.c:117: do { 00107$: ;test.c:118: k5 = k5 - 1; ;ну достаточно логичная конструкция- почему в остальных ;местах IY???? ld hl,(_k5) dec hl ld (_k5),hl ;test.c:119: j5 = j5 + 1; ;например, здесь???? ld iy,#_j5 inc 0(iy) jp nz,00150$ inc 1(iy) 00150$: ;test.c:120: i5 = (k5 * 3) / (j5 * constant5); ;ну просто конфетка! :) ld de,(_k5) ld l,e ld h,d add hl,hl add hl,de ld c,l ld b,h ;он даже константу развернул!!! ld de,(_j5) ld l,e ld h,d add hl,hl add hl,hl add hl,de ld e,l ld d,h ;параметры через стек push de push bc call __divsint_rrx_s ;непонятного назначения конструкция... ld b,h ld c,l pop af pop af ld iy,#_i5 ld 0(iy),c ld 1(iy),b ;test.c:121: } while ( k5 > 0 ); ;страшная конструкция... ld a,#0x00 ld iy,#_k5 sub a,0(iy) ld a,#0x00 sbc a,1(iy) jp m,00107$
7.Глубокие подвыраженияКод:;test.c:126: for( i = 0; i < 100; i++ ) ;стандартный заголовок цикла ld iy,#_i ld 0(iy),#0x00 ld 1(iy),#0x00 00121$: ld iy,#_i ld a,0(iy) sub a,#0x64 ld a,1(iy) sbc a,#0x00 jp p,00124$ ;test.c:127: ivector5[ i * 2 + 3 ] = 5; ;выделение индукции нет, но интересно- сообразил, что ; переменная цикла помещается в один байт ld c,0(iy) ld a,c add a,a ld c,a ;эх, не догадался базу массива сместить :) inc c inc c inc c ;не забываем про размер ld a,c add a,a ld c,a ;вот это интересно- использование полуслов адреса ld a,#<_ivector5 add a,c ld c,a ld a,#>_ivector5 adc a,#0x00 ld b,a ;бережет он HL непонятно с какими целями... ld l,c ld h,b ld (hl),#0x05 inc hl ld (hl),#0x00 ;test.c:126: for( i = 0; i < 100; i++ ) ;стандарный инкремент inc 0(iy) jp nz,00151$ inc 1(iy) 00151$: jp 00121$ 00124$:
8.Генерация адреса переменной с константным индексом, размножение копий и регистровКод:;test.c:133: if( i < 10 ) ld iy,#_i ld a,0(iy) sub a,#0x0A ld a,1(iy) sbc a,#0x00 jp p,00111$ ;test.c:134: j5 = i5 + i2; ;страхолюдная конструкция... ld hl,#_i2 push de ld iy,#_j5 push iy pop de ld iy,#_i5 ld a,0(iy) add a,(hl) ld (de),a ld a,1(iy) inc hl adc a,(hl) inc de ld (de),a pop de jp 00112$ 00111$: ;test.c:136: k5 = i5 + i2; ;иными словами- никакого выделения общего подвыражения нет ld hl,#_i2 push de ld iy,#_k5 push iy pop de ld iy,#_i5 ld a,0(iy) add a,(hl) ld (de),a ld a,1(iy) inc hl adc a,(hl) inc de ld (de),a pop de 00112$:
9.Удаление общих подвыраженийКод:;test.c:144: ivector[ 0 ] = 1; ;ну почему в обычном варианте этого нет??? ld hl,#_ivector ld (hl),#0x01 inc hl ld (hl),#0x00 ;test.c:145: ivector[ i2 ] = 2; ;страсти-то какие... ld iy,#_i2 ld c,0(iy) ld b,1(iy) sla c rl b dec hl add hl,bc ld c,l ld b,h ld (hl),#0x02 inc hl ld (hl),#0x00 ;test.c:146: ivector[ i2 ] = 2; ;эти две команды лишние, но в целом используется ;результат предыдущих вычислений ld l,c ld h,b ld (hl),#0x02 inc hl ld (hl),#0x00 ;test.c:147: ivector[ 2 ] = 3; ;почему так странно? ld bc,#_ivector + 4 ld l,c ld h,b ld (hl),#0x03 inc hl ld (hl),#0x00
10.Вынесение инвариантного кодаКод:;test.c:154: if(( h3 + k3 ) < 0 || ( h3 + k3 ) > 5 ) ;советую присмотреться внимательно- компилятор ;запомнил, что k3 не менялся и равен 1- размножение ;константы плюс сокращенные вычисления плюс сразу ;два сравнения ;ЗЫ. закрывайте глаза на реализацию идеи :) ld iy,#_h3 ld c,0(iy) ld b,1(iy) ;вот это мы добавляем к3 inc bc ;проверка на <0 - проще простого ld a,b bit 7,a jp nz,00113$ ;а также на >5 ld a,#0x05 sub a,c ld a,#0x00 sbc a,b jp p,00114$ 00113$: ;test.c:155: printf("Common subexpression elimination\n"); ;параметры через стек ld hl,#__str_1 push hl call _printf pop af jp 00115$ 00114$: ;test.c:157: m3 = ( h3 + k3 ) / i3; ;выделение общих подвыражений действует!- выражение ;в скобках не вычисляется повторно, а хранится в bc push bc ld hl,(_i3) push hl push bc call __divsint_rrx_s ld d,h ld e,l pop af pop af pop bc ld iy,#_m3 ld 0(iy),e ld 1(iy),d ;test.c:158: g3 = i3 + (h3 + k3); ;аналогично и здесь ld hl,#_g3 ld iy,#_i3 ld a,0(iy) add a,c ld (hl),a ld a,1(iy) adc a,b inc hl ld (hl),a 00115$:
Код:;test.c:166: for( i4 = 0; i4 <= max_vector; i4++) ld iy,#_i4 ld 0(iy),#0x00 ld 1(iy),#0x00 00125$: ld a,#0x02 ld iy,#_i4 sub a,0(iy) ld a,#0x00 sbc a,1(iy) jp m,00128$ ;test.c:167: ivector2[ i4 ] = j * k; ;весьма оригинальное разыменование указателя ld hl,#_i4 ld a,#<_ivector2 add a,(hl) ld c,a ld a,#>_ivector2 inc hl adc a,(hl) ld b,a ;но вынесения инвариантной части нет- каждый цикл ;выполняются вычисления ld iy,#_j ld e,0(iy) ld iy,#_k ld d,0(iy) push bc push de inc sp ld a,e push af inc sp call __mulschar_rrx_s ld e,l pop af pop bc ld a,e ld (bc),a ;test.c:166: for( i4 = 0; i4 <= max_vector; i4++) ld iy,#_i4 inc 0(iy) jp nz,00154$ inc 1(iy) 00154$: jp 00125$ 00128$:
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
11.Вызов функции с аргументами. Определение недостижимого кода
Код:;test.c:173: dead_code( 1, "This line should not be printed" ); ;обычная передача параметров через стек и очистка ld hl,#__str_2 push hl ld hl,#0x0001 push hl call _dead_code pop af pop af12.Вызов функции без аргументов. Исключение цикловКод:_dead_code: ;лишнее выделение стекового места, но полная оптимизация ;внутренностей функции push ix ld ix,#0 add ix,sp ;test.c:196: printf( "%s\n", b ); 00103$: pop ix ret
Код:;test.c:179: unnecessary_loop(); call _unnecessary_loop 00129$:13. Слияние заголовков цикловКод:_unnecessary_loop: ;test.c:212: for( i = 0; i < 5; i++ ) ld iy,#_i ;обратите внимание- компилятор перевернул цикл! ld 0(iy),#0x05 ld 1(iy),#0x00 00103$: ;test.c:214: k5 = x + j5; ;размножение константы х = 0 ;но повторная загрузка имеется, простительно ld hl,(_j5) ld iy,#_k5 ld 0(iy),l ld 1(iy),h ld hl,(_i) dec hl ld (_i),hl ;test.c:212: for( i = 0; i < 5; i++ ) ;оригинальная концовка! ld iy,#_i ld a,0(iy) or a,1(iy) jp nz,00103$ ;а этот код потому что i является глобально переменной ld 0(iy),#0x05 ld 1(iy),#0x00 00104$: ret
14.Разворачивание цикловКод:_loop_jamming: push ix ld ix,#0 add ix,sp ;test.c:226: for( i = 0; i < 5; i++ ) ld iy,#_i ld 0(iy),#0x00 ld 1(iy),#0x00 00101$: ld iy,#_i ld a,0(iy) sub a,#0x05 ld a,1(iy) sbc a,#0x00 jp p,00104$ ;test.c:227: k5 = x + j5 * i; ld hl,(_i) push hl ld hl,(_j5) push hl call __mulint_rrx_s ld b,h ld c,l pop af pop af ;переменная x хранится в стеке ld hl,#_k5 ld a,4(ix) add a,c ld (hl),a ld a,5(ix) adc a,b inc hl ld (hl),a ;test.c:226: for( i = 0; i < 5; i++ ) ld iy,#_i inc 0(iy) jp nz,00115$ inc 1(iy) 00115$: jp 00101$ 00104$: ;test.c:228: for( i = 0; i < 5; i++ ) ;слияния заголовков нет ld iy,#_i ld 0(iy),#0x00 ld 1(iy),#0x00 00105$: ld iy,#_i ld a,0(iy) sub a,#0x05 ld a,1(iy) sbc a,#0x00 jp p,00109$ ;test.c:229: i5 = x * k5 * i; ld hl,(_k5) push hl ld l,4(ix) ld h,5(ix) push hl call __mulint_rrx_s ld b,h ld c,l pop af pop af ld hl,(_i) push hl push bc call __mulint_rrx_s ld b,h ld c,l pop af pop af ld iy,#_i5 ld 0(iy),c ld 1(iy),b ;test.c:228: for( i = 0; i < 5; i++ ) ld iy,#_i inc 0(iy) jp nz,00116$ inc 1(iy) 00116$: jp 00105$ 00109$: pop ix ret
15.Сжатие цепочки переходовКод:_loop_unrolling: push ix ld ix,#0 add ix,sp ;test.c:243: for( i = 0; i < 6; i++ ) ;разворота нет ld iy,#_i ld 0(iy),#0x00 ld 1(iy),#0x00 00101$: ld iy,#_i ld a,0(iy) sub a,#0x06 ld a,1(iy) sbc a,#0x00 jp p,00105$ ;test.c:244: ivector4[ i ] = 0; ;экзотическая загрузка :) ld c,0(iy) ld b,1(iy) sla c rl b ld hl,#_ivector4 add hl,bc ld c,l ld b,h ld (hl),#0x00 inc hl ld (hl),#0x00 ;test.c:243: for( i = 0; i < 6; i++ ) ld iy,#_i inc 0(iy) jp nz,00111$ inc 1(iy) 00111$: jp 00101$ 00105$: pop ix ret
Итоговая оценка- 7/10. Умное распространение констант, сжатие переходов, приемлимый заголовок цикла, различная оптимизация, но повсеместное использование индексного регистра для хранения глобальных переменных все портит. Надо будет проверить как он себя ведет на статических переменных и возможно ли убрать работу с индексными регистрами. Если получится, то данный компилятор можно рекомендовать к применению!Код:_jump_compression: push ix ld ix,#0 add ix,sp ;test.c:256: beg_1: ld a,8(ix) sub a,10(ix) ld a,9(ix) sbc a,11(ix) ;интересный финт- в С результат сравнения k и l rlca and a,#0x01 ld c,a ld a,10(ix) sub a,12(ix) ld a,11(ix) sbc a,13(ix) ;а в А результат сравнения l и m rlca and a,#0x01 ;только он почему-то не используется, а теряется... 00101$: ;test.c:257: if( i < j ) ld a,4(ix) sub a,6(ix) ld a,5(ix) sbc a,7(ix) jp p,00113$ ;test.c:259: if( j < k ) ld a,6(ix) sub a,8(ix) ld a,7(ix) sbc a,9(ix) jp p,00110$ ;test.c:261: if( k < l ) ;использование предыдущего результата xor a,a or a,c jp z,00106$ ;test.c:263: if( l < m ) ;очень странный код... не понимаю как работает.... or a,a ;есть свертка перехода! jp z,00101$ ;test.c:264: l += m; ld a,10(ix) add a,12(ix) ld 10(ix),a ld a,11(ix) adc a,13(ix) ld 11(ix),a jp 00114$ ;test.c:266: goto end_1; ; genLabel 00106$: ;test.c:269: k += l; ld a,8(ix) add a,10(ix) ld 8(ix),a ld a,9(ix) adc a,11(ix) ld 9(ix),a jp 00114$ 00110$: ;test.c:273: j += k; ld a,6(ix) add a,8(ix) ld 6(ix),a ld a,7(ix) adc a,9(ix) ld 7(ix),a ;test.c:275: goto beg_1; jp 00101$ 00113$: ;test.c:279: i += j; ld a,4(ix) add a,6(ix) ld 4(ix),a ld a,5(ix) adc a,7(ix) ld 5(ix),a 00114$: ;test.c:280: return( i + j + k + l + m ); ld a,4(ix) add a,6(ix) ld c,a ld a,5(ix) adc a,7(ix) ld b,a ld a,c add a,8(ix) ld c,a ld a,b adc a,9(ix) ld b,a ld a,c add a,10(ix) ld c,a ld a,b adc a,11(ix) ld b,a ld l,12(ix) ld h,13(ix) add hl,bc 00115$: pop ix ret![]()
Последний из имеющихся пациент- z88dk. Порядком помучался пока заставил его генерить исходник ассемблера. Если попросить, вставляет в исходный текст строки на С, но честно предупреждает, что в таком случае некоторая оптимизация не получится. Я буду уточнять, в каких местах возникла разница.
Использовался уровень оптимизации 2
0.Пролог
Его просто нет. Сразу идет код main.
1. Тест на размножение констант и копий.
2.Свертка константКод:;j4 = 2; ld hl,2 ;const ld (_j4),hl ;if( i2 < j4 && i4 < j4 ) ;нет размножения констант плюс функции для сравнения ld de,(_i2) ld hl,(_j4) call l_lt jp nc,i_4 ld de,(_i4) ld hl,(_j4) call l_lt ;обратите внимание- использование коротких команд ;перехода ;но в то же время систему переходов можно (и нужно) ;было бы оптимизировать jr c,i_5_i_4 .i_4 jp i_3 .i_5_i_4 ;i2 = 2; ld hl,2 ;const ld (_i2),hl ;j4 = k5; .i_3 ;та же картина ld hl,(_k5) ld (_j4),hl ;if( i2 < j4 && i4 < j4 ) ld de,(_i2) ld hl,(_j4) call l_lt jp nc,i_7 ld de,(_i4) ld hl,(_j4) call l_lt jr c,i_8_i_7 .i_7 jp i_6 .i_8_i_7 ;i5 = 3; ld hl,3 ;const ld (_i5),hl .i_6
3.Лишнее присваиваниеКод:;i3 = 1 + 2; ;свернул ld hl,3 ;const ld (_i3),hl ;flt_1 = 2.4 + 6.3; ;оп-па! не свернул! ld hl,i_2+0 call dldpsh ld hl,i_2+6 call dload call dadd ld hl,_flt_1 call dstore ;i2 = 5; ;загрузка константы ld hl,5 ;const ld (_i2),hl ;j2 = i + 0; ;0 не стал прибавлять ld hl,(_i) ld (_j2),hl ;k2 = i / 1; ;а вот на 1 поделить не побрезговал.... ld hl,(_i) ld de,1 ;const ex de,hl call l_div ld (_k2),hl ;i4 = i * 1; ;и умножить тоже ld hl,(_i) ld de,1 call l_mult ld (_i4),hl ;i5 = i * 0; ;и на ноль тоже... ld hl,(_i) ld de,0 call l_mult ld (_i5),hl ;printf( "This compiler handles divide-by-zero as an error\n"); ;да, он прохавал деление на нулевую константу ;параметры через стек ld hl,i_1+0 push hl call _printf pop bc ;flt_3 = 2.4 / 1.0; ;мрак... на 1 тоже делит, да еще и в реальном времени... ld hl,i_2+0 call dldpsh ld hl,i_2+12 call dload call ddiv ld hl,_flt_3 call dstore ;flt_4 = 1.0 + 0.0000001; ;без слов... ld hl,i_2+12 call dldpsh ld hl,i_2+18 call dload call dadd ld hl,_flt_4 call dstore ;flt_5 = flt_6 * 0.0; ;...одни эмоции ld hl,_flt_6 call dldpsh ld hl,i_2+24 call dload call dmul ld hl,_flt_5 call dstore ;flt_6 = flt_2 * flt_3; ;ну тут по другому никак ld hl,_flt_2 call dldpsh ld hl,_flt_3 call dload call dmul ld hl,_flt_6 call dstore
4.Снижение мощностиКод:;k3 = 1; ld hl,1 ;const ld (_k3),hl ;k3 = 1; ;в худших традициях... ld hl,1 ;const ld (_k3),hl
5.Простой циклКод:;k2 = 4 * j5; ;не заметил возможности умножения "малой кровью" ld hl,(_j5) ld de,4 call l_mult ld (_k2),hl ;for( i = 0; i <= 5; i++ ) ;реализация цикла for в лучших традициях! ld hl,0 ;const ld (_i),hl jp i_11 .i_9 ;ivector4[ i ] = i * 2; ;хорошо что хоть догадался сдвигами умножать на размер ;типа, а не функциями, но лишние операции со стеком ld hl,_ivector4 push hl ld hl,(_i) add hl,hl pop de add hl,de push hl ld hl,(_i) add hl,hl pop de call l_pint ;классика! ld hl,(_i) inc hl ld (_i),hl dec hl .i_11 ;мрак... ld hl,(_i) ld de,5 ;const ex de,hl call l_le jp c,i_9 .i_10
6.Управление переменной индукции циклаКод:;j5 = 0; ld hl,0 ;const ld (_j5),hl ;k5 = 10000; ld hl,10000 ;const ld (_k5),hl ;do { .i_14 ;k5 = k5 - 1; ;распознал вычитание единицы! ld hl,(_k5) dec hl ld (_k5),hl ;j5 = j5 + 1; ;и ее прибавление ld hl,(_j5) inc hl ld (_j5),hl ;i5 = (k5 * 3) / (j5 * 5); ;ну ведь можешь же умножать когда хочешь! ld hl,(_k5) ld b,h ld c,l add hl,bc add hl,bc push hl ld hl,(_j5) ld b,h ld c,l add hl,hl add hl,hl add hl,bc pop de call l_div ld (_i5),hl ;} while ( k5 > 0 ); .i_12 ;оригинальная проверка на конец цикла ld hl,(_k5) xor a or h jp m,i_13 or l jp nz,i_14 .i_13
7.Глубокие подвыраженияКод:;for( i = 0; i < 100; i++ ) ld hl,0 ;const ld (_i),hl jp i_17 .i_15 ;ivector5[ i * 2 + 3 ] = 5; ;специфично, но в целом терпимо ld hl,_ivector5 push hl ld hl,(_i) add hl,hl inc hl inc hl inc hl add hl,hl pop de add hl,de ld (hl),#(5 % 256) inc hl ld (hl),#(5 / 256) ld hl,(_i) inc hl ld (_i),hl ;а это зачем??? dec hl .i_17 ;оптимизацию for не доделали... ld hl,(_i) ld de,100 ;const ex de,hl call l_lt jp c,i_15 .i_16
8.Генерация адреса переменной с константным индексом, размножение копий и регистровКод:;if( i < 10 ) ;хреново сравнивает! ld hl,(_i) ld de,10 ;const ex de,hl call l_lt jp nc,i_18 ;j5 = i5 + i2; ;зато хоть складывает нормально ld de,(_i5) ld hl,(_i2) add hl,de ld (_j5),hl ;else jp i_19 .i_18 ;k5 = i5 + i2; ;выделения подвыражений нет ld de,(_i5) ld hl,(_i2) add hl,de ld (_k5),hl .i_19
9.Удаление общих подвыраженийКод:;ivector[ 0 ] = 1; ;правильно ld hl,1 ;const ld (_ivector),hl ;ivector[ i2 ] = 2; ;лишние операции со стеком, простая перестановка дала ;бы прирост эффективности ld hl,_ivector push hl ld hl,(_i2) add hl,hl pop de add hl,de ld de,2 ;const ex de,hl ;да что за мрак! call l_pint ;ivector[ i2 ] = 2; ;не воспользовался результатом предыдущей операции ld hl,_ivector push hl ld hl,(_i2) add hl,hl pop de add hl,de ld de,2 ;const ex de,hl call l_pint ;ivector[ 2 ] = 3; ;тут все правильно ld hl,3 ;const ld (_ivector+4),hl
10.Вынесение инвариантного кодаКод:;if(( h3 + k3 ) < 0 || ( h3 + k3 ) > 5 ) ;хорошее начало, но дальше не очень ld de,(_h3) ld hl,(_k3) add hl,de ld de,0 ;const ex de,hl call l_lt jp c,i_21 ;не используются результаты... ld de,(_h3) ld hl,(_k3) add hl,de ld de,5 ;const ex de,hl call l_gt jp nc,i_20 .i_21 ;printf("Common subexpression elimination\n"); ;параметры через стек ld hl,i_1+63 push hl call _printf pop bc ;else { jp i_23 .i_20 ;m3 = ( h3 + k3 ) / i3; ;совсем не используются... ld de,(_h3) ld hl,(_k3) add hl,de ex de,hl ld hl,(_i3) call l_div ld (_m3),hl ;g3 = i3 + (h3 + k3); ld hl,(_i3) push hl ld de,(_h3) ld hl,(_k3) add hl,de pop de add hl,de ld (_g3),hl ;} .i_23
Код:;for( i4 = 0; i4 <= 2; i4++) ld hl,0 ;const ld (_i4),hl jp i_26 .i_24 ;ivector2[ i4 ] = j * k; ;обычная обработка индекса массива ld de,_ivector2 ld hl,(_i4) add hl,de push hl ;но вынесения кода нет ld de,(_j) ld hl,(_k) call l_mult pop de ld a,l ld (de),a ld hl,(_i4) inc hl ld (_i4),hl dec hl .i_26 ld hl,(_i4) ld de,2 ;const ex de,hl call l_le jp c,i_24 .i_25
11.Вызов функции с аргументами. Определение недостижимого кода
Код:;dead_code( 1, "This line should not be printed" ); ;параметры через стек, слева направо (хотя должно быть наоборот...) ld hl,1 ;const push hl ld hl,i_1+97 push hl call _dead_code pop bc pop bc12.Вызов функции без аргументов. Исключение цикловКод:;void dead_code( a, b ) ;int a; ;char *b; ._dead_code ;{ ;int idead_store; ;idead_store = a; ld hl,6-2 ;const add hl,sp call l_gint ; push hl ;if( 0 ) ;переход выполняет jp i_27 ;printf( "%s\n", b ); ;но код для пустышки генерит! ld hl,i_1+129 push hl ld hl,6 ;const add hl,sp call l_gint ; push hl call _printf pop bc pop bc ;} .i_27 pop bc ret
Код:call _unnecessary_loop13. Слияние заголовков цикловКод:;void unnecessary_loop() ;{ ._unnecessary_loop ;int x; ;x = 0; ;регистровая переменная- хорошо ld hl,0 ;const ;но в стеке- плохо push hl ;for( i = 0; i < 5; i++ ) ld hl,0 ;const ld (_i),hl jp i_30 .i_28 ;k5 = x + j5; ;прикольно :) pop de push de ld hl,(_j5) add hl,de ld (_k5),hl ld hl,(_i) inc hl ld (_i),hl dec hl .i_30 ld hl,(_i) ld de,5 ;const ex de,hl call l_lt jp c,i_28 .i_29 ;} pop bc ret
14.Разворачивание цикловКод:;void loop_jamming( x ) ;int x; ._loop_jamming ;{ ;for( i = 0; i < 5; i++ ) ld hl,0 ;const ld (_i),hl jp i_33 .i_31 ;k5 = x + j5 * i; ;наверное ошибка- на стеке на один параметр меньше pop bc pop hl push hl push bc push hl ld de,(_j5) ld hl,(_i) call l_mult pop de add hl,de ld (_k5),hl ld hl,(_i) inc hl ld (_i),hl dec hl .i_33 ld hl,(_i) ld de,5 ;const ex de,hl call l_lt jp c,i_31 .i_32 ;for( i = 0; i < 5; i++ ) ;второй цикл точная копия первого ld hl,0 ;const ld (_i),hl jp i_36 .i_34 ;i5 = x * k5 * i; pop bc pop hl push hl push bc ex de,hl ld hl,(_k5) call l_mult ex de,hl ld hl,(_i) call l_mult ld (_i5),hl ld hl,(_i) inc hl ld (_i),hl dec hl .i_36 ld hl,(_i) ld de,5 ;const ex de,hl call l_lt jp c,i_34 .i_35 ;} ret
15.Сжатие цепочки переходовКод:;void loop_unrolling( x ) ;int x; ._loop_unrolling ;{ ;for( i = 0; i < 6; i++ ) ld hl,0 ;const ld (_i),hl jp i_39 .i_37 ;ivector4[ i ] = 0; ;нет разворота, да и загрузка достаточно тяжела ld hl,_ivector4 push hl ld hl,(_i) add hl,hl pop de add hl,de ld (hl),#(0 % 256) inc hl ld (hl),#(0 / 256) ld hl,(_i) inc hl ld (_i),hl dec hl .i_39 ld hl,(_i) ld de,6 ;const ex de,hl call l_lt jp c,i_37 .i_38 ;} ret
Итоговая оценка- 5/10. Туповатый компилятор, на который изредка находит озарение и он генерит неплохой код. К применению не рекомендуется...Код:;int jump_compression( i, j, k, l, m ) ;int i, j, k, l, m; ._jump_compression ;{ ;beg_1: .i_40 ;if( i < j ) ;вот тут бы не помешали индексные регистры, да не ;используются совсем... ld hl,10 ;const add hl,sp ld e,(hl) inc hl ld d,(hl) push de ld hl,10 ;const add hl,sp call l_gint ; pop de call l_lt jp nc,i_41 ;{ ;if( j < k ) ld hl,8 ;const add hl,sp ld e,(hl) inc hl ld d,(hl) push de ld hl,8 ;const add hl,sp call l_gint ; pop de call l_lt jp nc,i_42 ;{ ;if( k < l ) ld hl,6 ;const add hl,sp ld e,(hl) inc hl ld d,(hl) push de ld hl,6 ;const add hl,sp call l_gint ; pop de call l_lt jp nc,i_43 ;{ ;if( l < m ) ld hl,4 ;const add hl,sp ld e,(hl) inc hl ld d,(hl) push de ld hl,4 ;const add hl,sp call l_gint ; pop de call l_lt jp nc,i_44 ;l += m; ld hl,4 ;const add hl,sp push hl ld e,(hl) inc hl ld d,(hl) push de ld hl,6 ;const add hl,sp call l_gint ; pop de add hl,de pop de call l_pint ;else jp i_45 .i_44 ;goto end_1; ;нет оптимизации переходов jp i_46 .i_45 ;} ;else jp i_47 .i_43 ;k += l; ld hl,6 ;const add hl,sp push hl ld e,(hl) inc hl ld d,(hl) push de ld hl,8 ;const add hl,sp call l_gint ; pop de add hl,de pop de call l_pint .i_47 ;} ;else jp i_48 .i_42 ;{ ;j += k; ld hl,8 ;const add hl,sp push hl ld e,(hl) inc hl ld d,(hl) push de ld hl,10 ;const add hl,sp call l_gint ; pop de add hl,de pop de call l_pint ;end_1: .i_46 .i_49 ;goto beg_1; jp i_40 ;} .i_48 ;} ;else jp i_50 .i_41 ;i += j; ld hl,10 ;const add hl,sp push hl ld e,(hl) inc hl ld d,(hl) push de ld hl,12 ;const add hl,sp call l_gint ; pop de add hl,de pop de call l_pint .i_50 ;return( i + j + k + l + m ); ld hl,10 ;const add hl,sp ld e,(hl) inc hl ld d,(hl) push de ld hl,10 ;const add hl,sp call l_gint ; pop de add hl,de ex de,hl ld hl,8-2 ;const add hl,sp call l_gint ; add hl,de ex de,hl ld hl,6-2 ;const add hl,sp call l_gint ; add hl,de ex de,hl ld hl,4-2 ;const add hl,sp call l_gint ; add hl,de ret ;}
Спасибо, интересное исследование. Значит sdcc... Но вот меня смущает, что на sdcc.sf.net постоянно упоминается "freeware", несмотря на его GPL'ность.
А по поводу переменных, наверное в реальных проектах будет много глобальных статических, чтобы компилятор их просто клал в память, не извращаясь со стеком или IX/IY.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)