Главная arrow Начинающим arrow Пробуем программировать arrow Этюды на ассемблере AVR  
19.01.2025 г.
Главная
Проекты
Статьи
Начинающим
Архив новостей
Ссылки
Контакты
Поиск
Файлы
Форум
Карта сайта
Авторизация
Админцентр
Поддержи наш сайт!
Через WebMoney

 R785211844650
 Z210696637574
 E368177590409

Этюды на ассемблере AVR Печать E-mail
Рейтинг: / 19
ХудшаяЛучшая 
Автор ARV   
27.01.2008 г.

Предлагаю несколько примеров, которые иначе, как этюды на ассемблере, не назовешь. Задачи простые, однако, я старался сделать их решения красивыми. Красивым я называю такой код, который либо реализует оригинальный алгоритм, либо имеет наименьший размер, либо обладает наибольшим быстродействием, либо обладает еще какими-то неординарными параметрами. Этюды имеют и вполне реальную ценность, т.к. посвящены довольно часто встречающимся в практике ситуациям.

ЭТЮД.
1. Произведение вспомогательного характера - рисунок, картина или скульптура - и обычно небольшого размера, выполненное с натуры.
2. Инструментальная пьеса виртуозного характера, предназначенная для концертного исполнения.
3. Небольшое литературное произведение или научное исследование, посвященное какому-л. частному вопросу.
4. Упражнение, служащее для развития и совершенствования техники какого-л. искусства: актерского, шахматного, музыкального и т.п. (обычно импровизационного характера).

Толково-словообразовательный словарь русского языка.

В предложенных этюдах подразумеваются, что имеется следующий код-преамбула:

.DEF V = <Любой регистр>
.DEF VL = <Любой регистр>
.DEF VH = <Любой регистр>
.DEF Temp=<Регистр R16...R31>
.DEF Temp1=<Регистр R16...R31>

1. Умножение чисел на 1.25, 1.5, 1.75.

Ассемблер микроконтроллеров реализует целочисленную арифметику, однако часто требуется увеличить или уменьшить в дробное число раз. Очень многие сразу бросаются писать программы на Си с использованием float-переменных, однако для некоторых частных случаев существуют довольно элегантные решения и на ассемблере.
Умножение на 1.25, если вдуматься, это всего-навсего сложение числа с собственной четвертью. И этот алгоритм для байтовых чисел без знака реализуется так:

; VH = VH*1.25
MOV Temp, VH
LSR Temp
LSR Temp
ADD VH, Temp

Для двухбайтного числа VH:VL умножение на 1.25 осуществляется следующим кодом:

; (VH:VL) = (VH:VL)*1.25
MOV Temp, VL
MOV Temp1, VH
LSR Temp1
ROR Temp
LSR Temp1
ROR Temp
ADD VL, Temp
ADC VH, Temp1

Аналогично решаются и другие задачи:

;VH=VH*1,5
MOV Temp, VH
LSR Temp
ADD VH, Temp

;(VH:VL)=(VH:VL)*1,5
MOV Temp, VL
MOV Temp1, VH
LSR Temp1
ROR Temp
ADD VL, Temp
ADC VH, Temp1

;VH=VH*1,75
MOV Temp, VH
LSR Temp
ADD VH, Temp
LSR Temp
ADD VH, Temp

;(VH:VL)=(VH:VL)*1,75
MOV Temp, VL
MOV Temp1, VH
LSR Temp1
ROR Temp
ADD VL, Temp
ADC VH, Temp1
LSR Temp1
ROR Temp
ADD VL, Temp
ADC VH, Temp1

2. Циклические сдвиги.

Ассемблер микроконтроллеров AVR не содержит команды, осуществляющей циклический сдвиг байта вправо и влево, а необходимость в этом возникает довольно часто. Вот как это можно реализовать:

;Циклический сдвиг вправо VH
PUSH VH
LSR VH
POP VH
ROR VH

;Циклический сдвиг влево VH (вариант 1)
PUSH VH
LSL VH
POP VH
ROL VH

;Циклический сдвиг влево VH (вариант 2)
CLR V
LSL VH
ADC VH, V

Как видите, сдвиг влево можно осуществить двумя способами: без использования дополнительного регистра или с использованием. Первый вариант более медленный и более объемный, зато второму требуется свободный регистр.
Попробуйте самостоятельно решить задачу для сдвига вправо, добившись более быстрого кода, по образцу сдвига влево.

Циклические сдвиги бывает необходимо выполнять и над двухбайтными числами, и вот варианты реализации таких сдвигов:

;Циклический сдвиг вправо (VH:VL)
PUSH VL
LSR VL
POP VL
ROR VH
ROR VL

;Циклический сдвиг влево (VH:VL) - вариант 1
PUSH VH
LSL VH
POP VH
ROL VL
ROL VH

;Циклический сдвиг влево (VH:VL) - вариант 2
CLR V
LSL VL
ROL VH
ADC VL, V

И снова сдвиг влево реализован разными способами, а для сдвига вправо, надеюсь, вам будет интересно поломать голову и самим.

3. Обращение порядка битов.

Иногда требуется получить «зеркальное» отражение битов в байте, т.е. когда нулевой бит обменивается местами с 7-ым, 1-й с 6-ым и т.д. Условно это можно обозначить так, заменив значения битов буквами: ABCDEFGH --> HGFEDCBA. Даже любители Си знают, что красиво решить эту задачу не так-то просто. И, не смотря на то, что при грамотной записи на языке Си многие компиляторы генерируют весьма компактный код, ассемблер все-же позволяет добиться еще лучших результатов. Решению этой задачи посвящалось много тем на различных форумах, однако я решил эту задачу самостоятельно, причем двумя способами, с которыми предлагаю познакомиться и вам.

;Перестановка порядка битов [ABCDEFGH]-->[ HGFEDCBA] в Temp
; максимум скорости - 14 тактов, 14 команд
SWAP Temp
MOV  Temp1, Temp
ROR  Temp
ROL  Temp1
ROR  Temp
ROL  Temp1
ROR  Temp
ROL  Temp1
ROR  Temp
ROL  Temp1
ROR  Temp
ANDI Temp, 0xF0
ANDI Temp1, 0x0F
OR    Temp, Temp1

;Перестановка порядка битов [ABCDEFGH]-->[ HGFEDCBA] в Temp
; минимум кода - 11 команд, 26 тактов
.DEF    Temp2 = <Регистр R16...R31>
SWAP Temp
MOV   Temp1, Temp
LDI    Temp2, 4
m1:
ROR   Temp
ROL   Temp1
DEC   Temp2
BRNE m1
ROR   Temp
ANDI  Temp, 0xF0
ANDI  Temp1, 0x0F
OR    Temp, Temp1

Недавно я обнаружил, что найден еще один способ - пока что самый быстродействующий: всего 13 тактов! Но найти его предлагаю вам самостоятельно.


Добавить в любимые (0) | Просмотров: 33537

  Коментарии (3)
 1 Написал(а) mamonth, в 02:58 28.01.2008
Отлично!!! Побольше бы такого!
 2 Написал(а) Александр Разумовский, в 18:11 11.03.2008
Красиво ! Жаль мне это не доступно - пишу на Си просто умножить на 1.75 и получаю результат. Правда только начал программировать по урокам на http://avr123.nm.ru 
 
Надеюсь и мне станет подвластен полный контроль над МК.
 3 Написал(а) ae, в 08:26 08.11.2008
bst v, 7 
lsl v 
bld v, 0 
 
bst v, 0 
lsr v 
bld v, 7 
 
bst vh, 7 
lsl vl 
rol vh 
bld vl, 0 
 
bst vl, 0 
lsr vh 
ror vl 
bld vh, 7

Только зарегистрированные пользователи могут оставлять коментарии.
Пожалуйста зарегистрируйтесь или войдите в ваш аккаунт.

 
« Пред.   След. »
Полезные материалы по сходным темам
Кто на сайте?
Сейчас на сайте находятся:
1 гость
Помощь on-line
BannerFans.com