Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для 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 и подобные).
<< Назад В начало Далее >> |
|