ВходНаше всё Теги codebook PARTS Поиск Опросы Закон Пятница
12 августа
1159203 Топик полностью
Adept (27.12.2021 14:41, просмотров: 142) ответил ssr на Какие алгоритмы оптимизации? Хочется применить их "вручную". Понятно, что повторяющиеся куски кода на уровне ассемблера можно вынести в подпрограммы. PIC16. Компилятор XC8 v1.32 (без оптимизации, занято 93% памяти программ) пишет, что если включить оптимизацию будет занято 59%. Не понимаю, за счет чего так много можно сократить.
Да много за счёт чего, в частности сильно экономит использование даже метких п/п взамен макросов. Если макрос нечасто используется (не в каком-нить критическом ко времени выполнения цикле, многократно), то почти всегда выгоднее заменить его на п/п, пусть даже и с двумя-тремя асемблерными командами всего. не исключаю, что компилятор может без оптимизации именно задействовать макросы (которые тиражируются по всей программе), а с оптимизацией заменять их на call/ret 

в итоге - всего пара байт, в простейшем случае, вместо десятка(ов) при каждом использовании макроса.

У меня практически каждый макрос (а я использую их много и часто, для лучшей читабельности кода и исключения ошибок), если он больше 2-3 команд - сделан в виде вызова п/п.

Вот. к примеру (ещё и вложенные макросы :)) правда подготовка и вызов макроса 6 байт - но это сложная функция, универсальная - декремент ячейки с контролем нуля. Сохранение Z сделано "чтоб не думать об этом и не влететь где-нить в прерывании на порчу регистра" (а бывают и большие п/п обработки, но это уже в общем-то "написание своего языка" :)). Излишества привнесены в угоду универсальности :)) можно конечно покороче сделать, для конкретного применния.

- только не пинайте сильно, что так нельзя :) - "да ла-а-адно, - можно" (С) :))


;Декремент ячейки ОЗУ, как таймера (однократный отсчет до "0").
;Параметр - ячейка ОЗУ.
;При достижении ячейкой значения "0", счет приостанавливается.
;Синтаксис: TIMER_onceCountDown	SRAM_Address
;!! Результат возвращается в регистре TMP, и может быть проанализирован.
;08/II.19
;
.macro	TIMER_onceCountDown
	PUSH_Z
	LDZ	@0
	rcall	decrement_timerCell
	POP_Z
.endmacro
;---
;П/П для макроса "TIMER_onceCountDown"
;  адрес ячейки RAM передается в регистре "Z", результат возвращается в
;  регистре "TMP" (значение числа в ячейке памяти с указанным адресом).
;  Если достигли "0", то "0" и остается в ячейке.
;26/IX.06
decrement_timerCell:
	ld	TMP,Z
	subi	TMP,1
	brcc	store_counted_down_Cell	;Отсчитали ли таймаут? Если НЕТ, то сохраняем
	clr	TMP			;  счетчик, иначе стопорим его значение на "нуле".
store_counted_down_Cell:
	st	Z,TMP			;Сохраняем TMP, по адресу изменяемого счетчика.
	ret

;


если посмотреть ассемблерный код моих программ, то там call на call-е и call-ом погоняет :)) - сплошные вызовы п/п, как минимум процентов 30-40 кода :) - ужас для реверсинжиниринга :))

И вообще интенсивное использование подпрограмм - нашеФсё :) - сильно экономит объём, исключает ошибки, затрудняет "реверс", при достаточной в 99.99% случаев производительности :))

Пример - компактный "шитый код" форт-программ.

...делать нужно так, как нужно. А как ненужно - делать не нужно (С) Винни-Пух :)