Пишу для PIC10F20x небольшой алгоритм - на Си это 10 строчек. Но пишу на ассемблере и основательно задолбался с goto и и мельканием movwf/movf/movlw. Решил попробовать написать на Си и посмотреть, как с этим справится компилятор. В MPLAB Studio много инструментов. Я выбрал HI-TECH ANSI C Compiler.
И так, исходный код на Си:
///*
char test_func(void);
int main(void)
{
char r;
r = test_func();
}
//*/
char test_func(void)
{
char v, z, d, s;
v = 100;
z = 0;
if (v < z)
{
d = z - v;
s = 0;
}
else
{
d = v - z;
s = 1;
}
if (d < 2)
return v;
if (d > 25)
d = 25;
if (s == 0)
{
v = v + d;
if (v > 100)
return 100;
return v;
}
else
{
if (v < d)
return 0;
return v - d;
}
}
Так замучено писать заставил компилятор - он не понимает сравнений "d < 0", хотя char, вроде бы, тип знаковый. Возможно у него он по умолчанию бесзнаковый.
Посмотрим, что наиндусил компилятор...
(Ненужные директивы я убрал, а макросы развернул.)
;_test.c: 14: char v, z, d, s;
;_test.c: 16: v = 100;
movlw (064h)
movwf (test_func@v)
Логично.
l72:
;_test.c: 17: z = 0;
bcf status, c
movlw 0
btfsc status, с
movlw 1
movwf (test_func@z)
А это что?
1. Сбрасываем флаг переноса.
2. Загружаем в регистр W "0".
3. Проверяем флаг переноса и есть он чист, то пропускаем след. команду (переход на п.5)
4. Загружаем в регистр W "1".
5. Записываем в переменную.
А теперь сократим код (просто очистим переменную):
clrf test_func@z
Или так (загрузим ноль в переменную):
movlw 0
movwf test_func@z
Аналогичный код:
;_test.c: 22: s = 0;
bcf status, c
movlw 0
btfsc status,0
movlw 1
movwf (test_func@s)
Следующий перл:
;_test.c: 19: if (v < z)
movf (test_func@z),w
subwf (test_func@v),w
btfsc status, c
goto u71
goto u70
u71:
goto l80
u70:
Зачем тут двойной переход (goto u71 / goto l80)?..
Еще "оптимизация":
;_test.c: 21: d = z - v;
movf (test_func@z),w
movwf btemp+3
decf (test_func@v),w
xorlw 0ffh
addwf btemp+3,w
movwf (test_func@d)
1. W = test_func@z
2. (btemp+3) = W
3. W = test_func@v - 1
4. W ^= 0xff
5. W += (btemp+3)
6. test_func@d = W
Замысловато...
Я бы сделал так:
movf test_func@v, w
subwf test_func@z, w
movwf test_func@d
Неправда ли, это короче и понятнее?
Аналогичный код:
;_test.c: 26: d = v - z;
movf (test_func@v),w
movwf btemp+3
decf (test_func@z),w
xorlw 0ffh
addwf btemp+3,w
movwf (test_func@d)
Еще пример расточительства:
;_test.c: 34: d = 25;
movlw (019h)
movwf (test_func@d)
goto l94
l12:
l94:
;_test.c: 36: if (s == 0)
Представляю, какой продукт будет на выходе с таким компилятором. У меня, замечу, оперативки всего 16 байт и программной памяти на 255 команд.