Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Если энергосбережение не разрешено, то команда sleep ничего не делает (и притом сработает, только если она вызывается из основной программы, а не из прерывания), и это позволяет "поиграть" возможностями. Например, при необходимости передачи последовательности байт по относительно медленному UART, можно разрешить МК "заснуть", только когда последний байт будет передан. Тогда основной цикл может включать в себя единственную команду sleep, а разрешать "спящий" режим мы будем перед выходом из процедуры прерывания "передача завершена" (ТХ Complete) после передачи последнего байта.

Выполнение типовых процедур на ассемблере
К типовым в данном случае мы отнесем процедуры, которые на языках высокого уровня записываются просто и понятно, а в ассемблере требуют специальных ухищрений. Пример такой процедуры, имитирующей сложный оператор выбора CASE, мы уже встречали немного раньше в этой главе, в разделе "Команды проверки-пропуска". Также из предыдущего материала понятно, как реализовать простейшую конструкцию типа "if ... then" с помощью команд условных переходов. Подытожим пройденное, а также рассмотрим несколько других типовых конструкций (листинги 6.10-6.14).

Листинг 6.10. Условная конструкция типа "if ... then ... else"
if_then___else: cpi temp,Const_l brne elsel
<что-то делаем,
если temp меньше Const_l>
rjmp if_then_else ;обратно
elsel:
<что-то делаем,
если temp равен Const_l>
ret ;выход из процедуры
if then else:
cpi temp,Const_l brio elsel
<что-то делаем, если temp больше или равен Const_l> rjmp if_then_else ;обратно elsel:
<что-то делаем,
если temp меньше Const_l>
ret ;выход из процедуры

Листинг 6.11. Простой оператор выбора СА..-Е

cpi temp,Const_l
breq cont_l
cpi temp,Const_2
breq cont_2
cpi temp,Const_3
breq cont_3
cpi temp,Const_4
breq cont_4
cont_l: rcall proc_l
cont_2: rcall proc_2
cont_3: rcall proc_3
cont_4: rcall proc_4

Здесь учитывается ограниченность действия команд brxx: если процедуры ргосх, помеченные метками contx, занимают много места, то их выделяют в отдельные процедуры, а после меток ставят только их вызовы командой rcaii. Если процедура занимает всего пару команд, то без дополнительного структурирования можно, конечно, обойтись.
Листинг 6,12. Цикл с предусловием типа While
clr count
while_proc:
inc count
cpi count,Const_l
breq end_while
<что-то делаем,
пока count меньше Const_l>
rjmp while_proc ;обратно
end_while:
<что-то делаем, если цикл окончен> ret ;выход из процедуры ldi count,Const_l while_proc: dec count breq end_while
<что-то делаем, пока не ноль> rjmp while_proc ;обратно end_while:
<что-то делаем, если цикл окончен> ret ;выход из процедуры

I Листинг 6.13. Цикл с постусловием типа REPEAT
clr count Repeat_proc : <что-то делаем> inc count cpi count,Const_l brne Repeat_proc
Этот вариант мы также уже разбирали ранее в этой главе (разумеется, возможен его вариант и.с применением команды dec).
; Листинг 6.14. Цикл типа for ... next (язык Basic):
ldi count,Nx ;Nx — число повторений цикла f orjproc: <что-то делаем> dec count brne forjproc
Другие типовые процедуры, из которых наиболее важны различные арифметические действия, мы разберем в последующих главах по ходу дела.

О стеке, локальных и глобальных переменных
Стек — одно из самых употребительных понятий в программировании. Наличие программного стека позволяет, например, организовать привычное для языков высокого уровня разделение переменных на локальные и глобальные. Во всех последующих программах в этой книге мы будем пользоваться только глобальными переменными, и если регистров общего назначения для них не хватает— задействовать ячейки SRAM.
(Привычку пользоваться преимущественно глобальными переменными автор даже перенес в свой стиль программирования на Delphi.) Однако в больших проектах без локальных переменных бывает просто не обойтись (например, когда одна и та же процедура вызывается в разных местах с исходными данными, хранящимися в различных регистрах). Механизм организации локальных переменных с помощью стека иллюстрирует листинг 6.15 (он в точности такой же, как это происходит при компиляции в "настоящих" языках программирования).

push var_l ;переменная var_l в программе помещается в стек
push var_2 ;переменная var_2 в программе помещается в стек
rcall procedure /вызывается процедура
pop var_2 ;после нее результат извлекается из стека
pop var_l /второй результат извлекается из стека
procedure: ;в процедуре извлекается локальная
pop var_loc2 /переменная var_loc2 со значением var_2
pop var_locl ;и переменная var_locl со значением var_l
расчеты, расчеты...
push var_locl /результат — в стек push var_loc2 /результат — в стек ret /возврат из процедуры

В качестве переменных vari и var_2 допустимы любые регистры, при этом действия внутри процедуры всегда будут совершаться с заданными регистрами varioc. Обратите внимание, что когда таких переменных несколько, важно соблюдать правильный порядок их помещения в стек и извлечения оттуда, согласно принципу "первым вошел— последним вышел" (в программах на языках высокого уровня за порядком переменных в стеке следят специальные форматы вызова функций типа stdcall и подобные).



     
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru