Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Вымогатель припоя
Сообщения: 602
Зарегистрирован: Сб июл 07, 2012 23:01:25

Сообщение сокол »

:facepalm:
Реклама
Встал на лапы
Сообщения: 124
Зарегистрирован: Пн мар 22, 2010 18:07:52

Сообщение vit007 »

Ребята подскажите,...
Если я использую директиву dseg, то должен и начало в ней указывать (org) и также должен смещать начало сегмента cseg, относительно этого... ? И да, один адрес - это один байт?
Реклама
Потрогал лапой паяльник
Сообщения: 314
Зарегистрирован: Пн окт 26, 2020 08:37:51
Откуда: г.Волгоград

Сообщение С.Н. »

[uquote="vit007",url="/forum/viewtopic.php?p=4530398#p4530398"]Ребята подскажите,...
Если я использую директиву dseg, то должен и начало в ней указывать (org) и также должен смещать начало сегмента cseg, относительно этого... ? И да, один адрес - это один байт?[/uquote]
Насколько понимаю, это так, кроме слов о смещении сегмента cseg. Это разные области памяти и размеры разные и не связанные. Для dseg - org по байтам. В cseg - org словами из двух байт.
Да и заморачиваться по этому поводу незачем. Есть метки. В своих проектах на asm использую двух файловое построение (ядро и основная программа)
Ядро:

Код: Выделить всё

.Dseg
.org 0x100
;До 100H использовать нельзя - там РОН и порты ввода-вывода, отраженные на ОЗУ
;Переменные разной  размерности
; 			byte	N	
EndCoreDseg:						;Адрес конца сегмента данных   в файле UNIT
.CSEG
.org 0x00								
;	interrupt
;       и прочее
;Основной LOOP
;и прочие подпрограммы
EndCoreCSeg:						;Адрес конца кодового сегмента в файле UNIT
Основная программа

Код: Выделить всё

;Определение контроллера
.include "m328pdef.inc"                    
;секция всяких define и org 
;#define 
.include "unit.inc"
;Сегмент данных MAIN. Продолжаем с адреса конца сегмента UNIT
.Dseg				
;Переменные разной  размерности
; 			byte	N	
.org EndCoreDseg
;Сегмент кода MAIN. Продолжаем с адреса конца сегмента UNIT
.CSEG
.org EndCoreCSeg
;код 
Файлов в проекте может быть и много. В любом случае каждый сегмент должен где-то начаться. Cseg c своего 0 (вектора и начало в случае полного проекта), а Dseg со своей 100H или дальше.
ФУОЗ на платформе Ардуино: https://radiokot.ru/forum/viewtopic.php ... 6#p4366626
ВК - "ФУОЗ на микроконтроллере Atmega328P (МПСЗ)"
Это не хвост, это антенна
Сообщения: 1490
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

CSEG пространство памяти программ. Flash память.
DSEG Пространство SRAM. ОЗУ.

Начальный адрес для DSEG можно не указывать. Компилятору по заголовочному файлу на конкретный МК известен начальный адрес SRAM.

Адрес это начало. А один байт или два и так далее для этого тоже есть директивы.

Скачайте книгу Вольфганг Трамперт. AVR-RISC микроконтроллеры. Архитектура, аппаратные ресурсы, система команд, программирование, применение.

Там подробно расписано. И примеры на ассемблере. Эта книга долгое время была у меня настольной.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Сообщения: 124
Зарегистрирован: Пн мар 22, 2010 18:07:52

Сообщение vit007 »

Спасибо.
Реклама
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 23
Зарегистрирован: Чт июн 17, 2010 07:40:31
Откуда: Россия

Сообщение Gennadiy »

Использование флагов, переменных, констант из области SRAM можно описать директивой .EQU.
Где .EQU имя_параметра = адрес_в_SRAM. В таком случае обращение (чтение/запись/модификация) к ячейке памяти можно выполнять по имени параметра.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Определять переменные и константы находящиеся с области памяти (не важно RAM, EEPROM или FLASH) через .equ можно, но не очень удобно и есть опасность нарушить границы переменных, о чем вам компилятор не сообщит. Лучше делать метками это в соответствующих сегментах DSEG, ESEG и CSEG соответствующими директивами (.db, .dw, .byte и т.д.). Так и нагляднее и размер переменной легко задать и адрес следующей сам вычисляется, и определение адреса другой переменной из другого модуля программы в этот адрес не залезет.

.org обычно нужно ставить только если кусок памяти до этого адреса нужно пропустить, например в таблице векторов прерываний, чтобы не забивать пустые векторы NOP-ами или RJMP-ами на обработчик ошибки - просто делаете .org "имя прерывания" (которое из файла XXdef.inc берется) а потом RJMP на обработчик и все понятно и наглядно. Или если нужно чтоб какая-то переменная ну точно всегда была по определенному адресу, вот тогда если будет конфликт адресов, компилятор на это ругнется.
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
Друг Кота
Аватара пользователя
Сообщения: 15615
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

.EQU удобна для описания битовых данных (флаги, линии портов, биты РСФ) ежли оные уже ранее не были определены.
Или для применяемых в программе констант.
Может также использоваться для присвоения данным с ранее определенным именем нового имени (получение разных имен для одни и тех же данных).
Не может быть переопределена далее по тексту программы (без применения .UNDEF), в отличии от .SET, которая позволяет менять значение метки ниже по тексту новой директивой .SET.
8)
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 23
Зарегистрирован: Чт июн 17, 2010 07:40:31
Откуда: Россия

Сообщение Gennadiy »

Честно скажу, я не совсем Вас понимаю, в чем состоит неудобство использования именованной, с помощью данной директивы, переменной в Ассемблере. Возможно это дело привычки. Но на мой взгляд все совсем наоборот. Хотя на вкус и цвет...
Друг Кота
Аватара пользователя
Сообщения: 15615
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Для программы на ассемблере существуют два вида данных:
1. данные (часто называемые "переменными"), которые размещаются в ячейках памяти;
2. данные константного типа, которые не имет фиксированного места размещения (константы, номера позиций бит в регистрах и/или байтах данных, размещенных в ОЗУ/ПЗУ).
Имена-метки для первого типа предпочтительно определять директивами разметки ОЗУ, ПЗУ, РСФ, регистрового банка.
Имена-метки второго типа исключительно удел .EQU или .SET
Дополнительные возможности .EQU - задать дополнительное имя метки данных к уже имеющемуся.
Однако для АВР относительно псевдонимов регистрового файла имеется еще директива .DEF
И их же (регистры регистрового файла) можно переразмечать как область ОЗУ.
Тут уже "свобода творчества" для автора программы.
8)
Друг Кота
Аватара пользователя
Сообщения: 25435
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="Gennadiy",url="/forum/viewtopic.php?p=4531255#p4531255"]Честно скажу, я не совсем Вас понимаю, в чем состоит неудобство использования именованной, с помощью данной директивы, переменной в Ассемблере. Возможно это дело привычки. Но на мой взгляд все совсем наоборот. Хотя на вкус и цвет...[/uquote]
Неудобство состоит в том, что с помощью .equ вы не выделяете память, а просто подставляете число.
Еще одно неудобство в том, что если переменная более 1 байта, то вам придется выдумывать имена для каждого байта, а директивой var: .byte 4 вы выделяете переменной var четыре байта. И при этом Ассемблер с линкером имеет возможность контролировать размещение переменных в памяти. В отличии от...
Ну и обращаясь к нынешней среде разработки Атмела - МПЛАБ Х, при использовании .equ вы не сможете контролировать значения переменной в соответствующих окнах среды. Ибо вы фактически переменную не создали. И даже в Атмел студии мап-файл и шкала заполнения памяти данных останутся пустыми.
akl
Друг Кота
Сообщения: 4450
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

[uquote="КРАМ",url="/forum/viewtopic.php?p=4531699#p4531699"]Неудобство состоит в том, что с помощью .equ вы не выделяете память, а просто подставляете число. Еще одно неудобство в том, что если переменная более 1 байта, то вам придется выдумывать имена для каждого байта...[/uquote] Не нужно забивать память пустой информацией. Ассемблер прекрасно обрабатывает определение ниже без использования памяти

Код: Выделить всё

.equ	Fo=3276909*3	;300'000'033...300'000'003!!!!!!
.
.
.
	LDI	YH,HIGH((200-25)*Fo/1000/300-1)		LDI	YL,LOW((200-25)*Fo/1000/300-1); включить за 25мс до окончания 200мс периода
Друг Кота
Аватара пользователя
Сообщения: 25435
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="akl",url="/forum/viewtopic.php?p=4531817#p4531817"]Ассемблер прекрасно обрабатывает определение ниже без использования памяти[/uquote]Какое это имеет отношение к тому, что я сказал? Я в каком то месте говорил про неиспользование памяти? :facepalm:
Либо вы ничего не поняли, либо не желаете уйти от своих стереотипов.
Модератор
Аватара пользователя
Сообщения: 19058
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

КРАМ писал(а):Я в каком то месте говорил про неиспользование памяти?
вот в этом месте:
КРАМ писал(а):Неудобство состоит в том, что с помощью .equ вы не выделяете память, а просто подставляете число.
и у меня встречный вопрос - зачем, по-твоему, константам выделять память? константа она и потому константа, что ей не нужно выделение памяти.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Друг Кота
Аватара пользователя
Сообщения: 25435
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="Starichok51",url="/forum/viewtopic.php?p=4531845#p4531845"]зачем, по-твоему, константам выделять память?[/uquote]
Присвоение значения адреса метке через .equ является эрзац-методом выделения памяти.
Старичок, внимательно прочтите обсуждение... :facepalm:
Модератор
Аватара пользователя
Сообщения: 19058
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

лично меня этот эрзац устраивает полностью.
мне проще написать
.equ name1 0x100
.equ name2 0x104
этим я выделил для name1 4 байта. и никаких других директив мне не надо.
а если мой подход кому-то не нравится, то скажу, что каждый делает, как ему нравится и как ему удобно.
в ассемблере распределением памяти занимается программист, а не компилятор. и я её (память) распределяю, как мне удобно.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Друг Кота
Аватара пользователя
Сообщения: 25435
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="Starichok51",url="/forum/viewtopic.php?p=4532010#p4532010"]в ассемблере распределением памяти занимается программист, а не компилятор[/uquote]
А никто и не говорил, что директива .byte занимается распределением памяти. Эта директива говорит СРЕДЕ РАЗРАБОТКИ, что речь идет о памяти, а не о константе. Если проект состоит в мигании светодиодом, то вообще по барабану насколько кривой текст и о чем думал погромист во время его написания. Более-менее серьезный проект требует контроля за памятью и для этого есть инструменты в среде разработки.
Если лично вам на это болт положить, то из этого не следует, что и другим это надо делать.
ЗЫ. Две недели назад завершил разбор чужого проекта. Вот его как раз писал любитель equ. Типа вас.
Понять где массив, а где переменная и какая у кого разрядность без поллитра невозможно. Но чувак реально думал о себе много... :music:
Друг Кота
Аватара пользователя
Сообщения: 15615
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Starichok51
Не совсем так...
У Вас просто созданы константы
name1 = 0х100 и name2 = 0x104
далее компилятор будет их подставлять в команды в качестве данных.
Вот, к примеру, один из вариантов моего проекта в плане "шапки распределения ресурсов"(или отдельным файлом ставится в проекте) - в нем все, кроме таблиц в ПЗУ памяти программ:
Спойлер

Код: Выделить всё

;
;         "def_ext_disp.txt"  файл объявленных имен, бит и констант
;
;------------------------------------------------------
; variable definitions
;(таблица обьявленных имен)
;________________________
;таблица обьявленных имен - пользовательские константы
;
 .equ ts_ssl = 40 ; (1,50) константа интервала смены значения атрибута (0,8S)
                  ; для теста в дебаггере =1
 .equ dp_pgk = 190 ; константа предгашения (OCR1A)
 .equ dp_rastr = 4000 ; константа интервала развертки кадра (ICR1)
 .equ dp_maxj = 3990 ; максимальный уровень яркости ШИМ (OCR1B)
 .equ dp_minj = 200 ; минимальный уровень яркости ШИМ (OCR1B)
 .equ dp_lenbuf = 4 ; для сегментного порта 4 для регистрового файла 8
 .equ t_mk_lenpak = 8 ; количество байт в пакете
    ; 4 сегментный код, 2 код яркости, 1 атрибут информации, 1=CRC
 .equ dp_mask = 0b11110111 ; начальная позиция активного анода в строке
 .equ dp_maoff = 0b01111000 ; маска отключения всех анодов
 .equ dp_seg_port = PORTB ; переименование порта вывода сегментов
 .equ dp_anod_port = PORTD ; переименование порта вывода анодов
; .equ dp_reg_port = PORTD ; переименование порта управляющих линий регфайла
 .equ t_mk_port = PORTD ; переименование порта линий межблочного обмена
 .equ dp_AN3 = 6 ; старшая (крайняя правая) позиция дисплея
 .equ dp_AN2 = 5
 .equ dp_AN1 = 4
 .equ dp_AN0 = 3 ; младшая (крайняя левая) позиция дисплея
 .equ t_mk_RxD = 0 ; линия входящих данных программного приемника (PORTD.0 ввод)
 .equ t_mk_Txd = 1 ; линия квитирования программного приемника (PORTD.1 вывод)
; .equ dp_DS0 = n ; линия данных регфайла 0
; .equ dp_DS1 = n ; линия данных регфайла 1
; .equ dp_DS2 = n ; линия данных регфайла 2
; .equ dp_DS3 = n ; линия данных регфайла 3
; .equ dp_DS4 = n ; линия данных регфайла 4
; .equ dp_DS5 = n ; линия данных регфайла 5
; .equ dp_DS6 = n ; линия данных регфайла 6
; .equ dp_DS7 = n ; линия данных регфайла 7
; .equ dp_SH_CP = n ; общая линия строба сопровождения блока регфайлов
; .equ dp_MR = n ; общая линия строба сброса блока регфайлов
; .equ dp_ST_CP = n ; общая линия строба записи в защелку блока регфайлов
  .equ s_A = 0 ; номер сегмента A в знакогенераторе
  .equ s_B = 1 ; номер сегмента B в знакогенераторе
  .equ s_C = 2 ; номер сегмента C в знакогенераторе
  .equ s_D = 3 ; номер сегмента D в знакогенераторе
  .equ s_E = 4 ; номер сегмента E в знакогенераторе
  .equ s_F = 5 ; номер сегмента F в знакогенераторе
  .equ s_G = 6 ; номер сегмента G в знакогенераторе
  .equ s_H = 7 ; номер сегмента H в знакогенераторе
;
;________________________
;таблица обьявленных имен - секция флагов пользователя
;
 .equ dp_exch = 0 ; флаг готовности новых данных в rdbf и rabf
 .equ dp_s_end = 1 ; передаточный флаг "строка окончена"
 .equ dp_darks = 2 ; флаг "интервал на темной стороне"
 .equ netpak = 3 ; флаг "прием пакета" для обхода заголовочной части
               ; участка обработчика байт приемника Т_МК
 .equ netdbu = 4 ; оперативный буфер приема занят
 .equ er_crc = 5 ; флаг "ошибка CRC"
;________________________
;таблица обьявленных имен - переназначение регистров РОН
;
;             принята базовая модель:
; область ограниченного функционала
 .def mfr0 = r0  ; математика и обмен с ПЗУ/самопрограммирование
 .def mfr1 = r1  ; математика и обмен с ПЗУ/самопрограммирование
 .def dp_flags = r2 ; системные флаги (ограниченный функционал)
 .def how_sreg_d = r3  ; быстрый стек для SREG для irq дисплея
 .def how_sreg_n = r4  ; быстрый стек для SREG для irq USART
; .def ifr1=r5  ; системные индексы (ограниченный функционал)
; .def cfr0=r6  ; системные счетчики (ограниченный функционал)
; .def cfr0=r7  ; системные счетчики (ограниченный функционал)
 .def dp_xbuf = r8  ; оперативный буфер сегментов (байтовый режим)
 .def dp_masbu = r9 ; маска текущего активного анода
 .def dp_idx = r10  ; смещение в строке (номер кадра)
 .def dp_cntk = r11  ; счетчик кадров в строке
 .def dp_ftmpl = r12 ; быстрый стек (для r16/tmp0)
 .def dp_ftmph = r13 ; быстрый стек (для r17/tmp1)
 .def dp_ftmxl = r14 ; быстрый стек для Xl
 .def dp_ftmxh = r15 ; быстрый стек для Xh
; область полного функционала
 .def tmp0 = r16 ; рабочий регистр (полный функционал)
 .def tmp1 = r17 ; рабочий регистр (полный функционал)
 .def ts_cntss = r18 ; счетчик строк на шаг смены атрибута (полный функционал)
 .def tmp3 = r19 ; рабочий регистр (полный функционал)
 .def cntb = r20 ; рабочий регистр (полный функционал)
 .def cntw=r21 ; рабочий регистр (полный функционал)
; .def wfr6=r22 ; рабочий регистр (полный функционал)
; .def wfr7=r23 ; рабочий регистр (полный функционал)
 .def bfr0 = r24 ; базовый регистр (полный функционал)
 .def bfr1 = r25 ; базовый регистр (полный функционал)
;     Xl = r26 ; адрес сегмента Х (полный функционал)
;     Xh = r27 ; адрес сегмента Х (полный функционал)
;     Yl = r28 ; адрес сегмента Y (полный функционал)
;     Yh = r29 ; адрес сегмента Y (полный функционал)
;     Zl = r30 ; адрес сегмента Z (полный функционал) ПЗУ/самопрограммирование
;     Zh = r31 ; адрес сегмента Z (полный функционал) ПЗУ/самопрограммирование
; регистры Xh:Xl, Yh:Yl, Zh:Zl определены в дефайне изготовителя и в системе команд
; изменение их имени хотя и возможно, но нежелательно -
; возникает путаница с интегрированной абревиатурой системы команд
;  в случае с "малой моделью" допускающей/достаточной для размещения ВСЕХ
; используемых ВСЕМИ подпрограммами регистров в области СОЗУ регистрового
; файла одновременно (без "подкачки" наборов параметров через ОЗУ)
; рекомендовано переназначение индивидуальных имен регистров
; согласно текущей задачи
;________________________
;таблица обьявленных имен - секция определенных данных (ОЗУ)
;
   .dseg
 dp_datbuf: .byte dp_lenbuf ; буфер отображения: данные (4 позиции)
; младшая позиция в ячейке dp_datbuf, старшая в dp_datbuf+3
 dp_atrbuf: .byte (dp_lenbuf*2) ; буфер отображения: задатчик ШИМ по каждой позиции
 dp_rdbf:   .byte dp_lenbuf ; буфер предобработки данных
 dp_rabf:   .byte (dp_lenbuf*2) ; буфер предобработки задатчика ШИМ
 dp_shaps:  .byte 3 ; значения для dp_cntk, dp_masbu и dp_idx по запуску строки
 dp_cnts:   .byte 1 ; счетчик строк на сдвиг (беглая строка)
 dp_cntb:   .byte 1 ; счетчик бит в байте модуля вывода
;          в файл-расширитель горизонтальной координаты
 dp_cntwf:  .byte 1 ; счетчик байт модуля вывода
;          в файл-расширитель горизонтальной координаты
 net_fsr:   .byte 2 ; указатель адреса в буфере предобработки
;          для pakus
 net_cnt:  .byte 1 ; счетчик байт пакета для pakus
 net_buf:  .byte 8 ; оперативный буфер приема
;
;________________________
;таблица обьявленных имен - секция определенных данных (EEPROM)
;
  .eseg
;________________________
Модератор
Аватара пользователя
Сообщения: 19058
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

BOB51, да, я объявил константы.
но когда я их подставляю в команду, они оказываются адресами в ОЗУ.
КРАМ писал(а):Более-менее серьезный проект требует контроля за памятью
я не кладу болт на распределение памяти - тот пример, который я написал, и есть мой контроль за памятью. обращаясь к памяти по созданным именам я никогда не выйду за пределы имеющейся памяти.
и я не говорил, что другим это надо делать так же. я говорил, что каждый делает, как ему удобно.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Друг Кота
Аватара пользователя
Сообщения: 25435
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="Starichok51",url="/forum/viewtopic.php?p=4532043#p4532043"]как ему удобно.[/uquote]
Нет, каждый делает ГЛУПОСТИ как ему удобно. До тех пор, пока грабли не ударят больно по лбу.
Нет ничего "удобного" в equ против byte. Ну кроме того, что вместо наблюдения за переменными в окне Watch по имени, человек ищет в Memory по адресу, метаясь по листингу от списка переменных к конкретному участку кода.
А так - да, охрененно удобно... :))) :))) :)))
Ответить

Вернуться в «AVR»