# ВСЕ ЗДЕСЬ ## TODO :::danger :watch: - над этим я в процессе работы или нашел какие-то вещи, которые не объяснены :sunglasses: - то, что расписано прям от души, уверен как в своем имени ::: - [x] Вопрос 1 :sunglasses: - [x] Вопрос 2 - [x] Вопрос 3 :sunglasses: - [x] Вопрос 4 :sunglasses: - [x] Вопрос 5 - [X] Вопрос 6 :sunglasses: - [X] Вопрос 7 :sunglasses: - [X] Вопрос 8 - [X] Вопрос 9 - [X] Вопрос 10 :sunglasses: - [x] Вопрос 11 - [ ] Вопрос 12 - [x] Вопрос 13 - [x] Вопрос 14 :sunglasses: - [x] Вопрос 15 :sunglasses: - [x] Вопрос 16 - [x] Вопрос 17 :sunglasses: - [x] Вопрос 18 :sunglasses: - [x] Вопрос 19 - [x] Вопрос 20 - [X] Синтаксис - [x] Задачки ## Полезные ссылки [Учебник по atmega (Скинул Денис) (Недоступен)](https://vk.com/doc347637358_637042757?hash=07LYzGNQwBTHv2FEJynQEz4IQ4qgfYwBJwQPJa83aCL&dl=ldKec3nBjQj6G9MmJL13ysTyGHOEMBeI9vkYlZloTRT) [Даташит на инглише](http://ww1.microchip.com/downloads/en/devicedoc/doc2466.pdf) [Крайне урезанный даташит](http://www.gaw.ru/pdf/Atmel/AVR/atmega16p.pdf) [Сайтик с полезной инфой по avr](http://www.gaw.ru/html.cgi/txt/doc/micros/avr/asm/start.htm) ## Вопросы ### Регистры [1) Регистр признаков SREG](/BhJ3OyD_RIi3lcawKRJbyg) [2) Указатель стека SP + память](/osDeyRaFQwyY3-htFL90LA) [3) Сторожевой регистр WDTCR](/cRBOAvEYSNePy-OvUSFnhw) [4) Регистры ввода вывода DDRX](/NnhJgnTqQDSuP2VcD7nbjw) [5) Регистр таймера/счетчика](/W7htxoJPS_K9EVAzmr4acw) [6) Регистры для последовательного интерфейса SPI](/qTVdGkiDQ9qWkxGaCVK6UQ) [7) Регистры для последовательного интерфейса USART](/gJ3L7hAJQneWndP3Bnl0xQ) [8) Регистр для последовательного интерфейса I2C](/wKSafybVQCaiiVRDRKogkQ) [9) Регистр для работы с АЦП](/wI9ru-dATGuVGcjSfNZvmw) [10) Регистр управления](/o4lQB_CoTcaqSDBL6orfWA) ### Изобразите и опишите архитектуру: :::info :bulb: Ссылки на эти страницы так же есть в вопросах регистров, к которым они относятся ::: [11. Atmega16](/0LisffV8QMmBkLGKOIdvgw) [12. микропроцессора AVR архитектуры](/LErY7GMCTtapTDVOeb962g) [13. системного генератора тактовых частот](/iCv6VxMlTcuQE7yzy0ov6A) [14. Системное управление и сброс](/_gfEPK4JQ_qo_DJhNp7SGg) [15. порта ВВ](/mOXnuCxYSP-OA_Vh5FU9Uw) [16. Таймер и счетчик со сторожевым регистром](/QEqiBwRDTyKwdVh2CG5uog) [17. SPI](/c3KELy6fRWyH9_UnxYCX9g) [18. USART](/BwlGJ88fTHG0MM5dZCP3fg) [19. I2C](/PzkW7zlbSQy_4qCo_F_EyQ) [20. АЦП](/HzYWPqA4QVyVa8iLTkDjWQ) ### Напрямую в вопросах нет, но есть шансы, что спросят :::info :bulb: Ссылки на эти страницы так же есть в вопросах ::: [Прерывания](/Tun8u1j-QJSgYGSeV2K34Q) [Дополнение до 1,2](/Njy2wYD-RpOOpWbiyx16yQ) [Сдвиговые регистры](/_wUCCs6xS3yl7_u7_Ce1tw) [Дуплексная связь](/onA8_sLUSYWhMZUIMEkoZQ) [Prescaller](/xRRZwK1LR42uuuzX0FBAog) [support: Устройство таймера](/ttfdHMD3Rrabf2KNMRe74A) [support: pull-up resistor (подтягивающий резистор)](/YXQMaYXhTwKJK58rGkExlg) ## Код :::info :bulb: тут потом будет инфа по общим командам, по каким-то задачкам. Команды для какого-то конкретного фукнционала есть в вопросах и тут не дублируются ::: ### Алгоритмы Краткие вырезки алгоритмов, которые могут понадобиться везде [Алгоритмы](/TIhoWFWYSXO9AWgway3pkw) ### Задачки ##### Пример задачи №1: Арифметические действия, поиск наименьшего вводится 5 чисел в ROM N = 27 1 + N = 28 3 * N = 81 7 - N = -20 (subi neg) (10 * N) + 2 = 272 (mul adiw) -N + 15 = -12 N - любое число найти наименьшее число любым доступным образом программа должна обнулить данные ROM. После очищения ROMa программа повторяет алгоритм пока все 5 чисел не обнуляться, программа продолжает работать по завершению работы программа выполняет инициализацию ```cp= clr r16 ; очищаем нашу константу, в ней мы будем хранить номер группы = N ldi r16, N ; N = свой номер по порядку, ОБЯЗАТЕЛЬНО ВСТАВИТЬ ВМЕСТО N ЧИСЛО clr r17 ; с r17 по r21 будет работа с числами clr r18 clr r19 clr r20 clr r21 ; число 1 (r17) mov r17, r16 ; R17 = N inc r17 ; R17 = N + 1 ; число 2 (r18) clr r22 ; число счётчик mulR18: add r18, r16 inc r22 cpi r22, 3 brmi mulR18 clr r22 ; число 3 (r19) mov r19, r16 ; R19 = N subi r19, 7 ; R19 = N - 7 neg r19 ; R19 = - N + 7 ; число 4 (r20) mov r20, r16 ; R20 = N adiw r24, 10 ; R24 = 10 muls R20, R24 ; R1:R0 = N * 10 inc r0 inc r0 ; число 5 (r21) mov r21, r16 ; R21 = N subi r21, 15 ; R21 = N - 15 neg r21 ; R21 = -N + 15 compare: ; R17 compare start cp r17, r3 ; Смотрим r17=0 если да переходим к r18 breq M1R18 cp r17, r18 ; ну сравниваем два числа r17 - r18 brpl M1R18 ; если + , то прыгаем к сравнению регистра 18, так как он больше, если нет, идём дальше jmp M2R17 M2R17: cp r19, r3 ; Смотрим r19=0 если да переходим дальше сравнения r17 breq M3R17 cp r17, r19 brpl M1R19 jmp M3R17 M3R17: cp r1, r3 breq r20M4null jmp mxr20bridge r20M4null: ;; если, старший разряд нуль, тогда сравниваем его как обычное число по метке R20null cp r0, r3 brpl m4r17 cp r17, r0 brpl M1R20bridge jmp M4R17 M4R17: cp r21, r3 ; если r21=0 то r17 большее и обнуляем его breq mxR17bridge cp r17, r21 brpl mxr21bridge jmp mxR17bridge ; R17 compare end ; R18 compare start M1R18: cp r18, r3 breq M1R19 cp r19, r3 breq M2R18 cp r18, r19 brpl M2R19 jmp M2R18 M2R18: cp r1, r3 breq r20M5null ;; если, старший разряд нуль, тогда сравниваем его как обычное число по метке R20null jmp mxr20bridge r20M5null: cp r0, r3 brpl m3r18 cp r18, r0 brpl M2R20 jmp M3R18 M3R18: cp r21, r3 brpl mxR18bridge cp r18, r21 brpl mxR21bridge ;; перекидываем на построенный Мишей(гением) мост jmp mxR18bridge ; R18 compare end ; R19 compare start M1R19: cp r19, r3 breq M1R20 cp r19, r18 brpl M2R18 jmp M2R19 M2R19: cp r1, r3 breq r20M8null jmp mxr20bridge r20M8null: ;; если, старший разряд нуль, тогда сравниваем его как обычное число по метке R20null cp r0, r3 breq M3R19 cp r19, r0 brpl M3R20 jmp M3R19 M3R19: cp r21, r0 breq mxR19 cp r19, r21 brpl mxR21bridge jmp mxR19 ; R19 compare end ;; bridges start ;; пояснение, мосты это разработка Гаврилова М.С Кандидат Клоунских Наук. ;; Компилятор иногда не может дотянуться от одной метки до другой, поэтому ему необходим "мост" ;; Так он может дотянуться до "моста", после чего отправиться на необходимую метку M1R18bridge: jmp M1R18 M1R20bridge: jmp M1R20 mxR18bridge: jmp mxr18 ;; это мост, потому-что бранач не мог дотянуться до необходимого места разработка Михаила Гаврилова (гений) mxR17bridge: jmp mxr17 ;; это мост, потому-что бранач не мог дотянуться до необходимого места разработка Михаила Гаврилова (гений) mxr21bridge: jmp mxr21 ;; это мост, потому-что бранач не мог дотянуться до необходимого места разработка Михаила Гаврилова (гений) mxr20bridge: jmp mxr20 ;; это мост, потому-что бранач не мог дотянуться до необходимого места разработка Михаила Гаврилова (гений) ;; bridges end ; R20 compare start M1R20: cp r1, r3 breq R20M1null ;; если, старший разряд нуль, тогда сравниваем его как обычное число по метке R20null jmp mxR20 ;;если, старший разряд не нуль, это число самое большое и на похуичах сразу его чистим R20M1null: cp r0, r3 breq M1R21 cp r18, r3 breq M2R20 cp r0, r18 brpl M1R18bridge jmp M2R20 M2R20: cp r1, r3 breq R20M2null ;; если, старший разряд нуль, тогда сравниваем его как обычное число по метке R20null jmp mxR20bridge ;;если, старший разряд не нуль, это число самое большое и на похуичах сразу его чистим R20M2null: cp r0, r3 breq M1R21 cp r19, r3 breq M3R20 cp r0, r19 brpl M3R19 jmp M3R20 M3R20: cp r1, r3 breq R20M3null ;; если, старший разряд нуль, тогда сравниваем его как обычное число по метке R20null jmp mxR20bridge ;;если, старший разряд не нуль, это число самое большое и на похуичах сразу его чистим R20M3null: cp r0, r3 breq M1R21 cp r21, r3 breq mxr20 cp r0, r21 brpl mxR21 jmp mxR20 ; R20 compare end ; R21 compare start ; регистр 21 всегда сравнивался последним, следовательно, если хоть где-то он оказался больше, то сразу бы обнулился. Сравнивать его необязательно M1R21: cp r21, r3 ;breq cycle jmp mxR21 ; R21 compare end mxR17: clr r17 ; регистр 17 оказался наименьшим, обнуляем его jmp compare ; перемещаемся на сравнение mxR18: clr r18 ; регистр 18 оказался наименьшим, обнуляем его jmp compare ; перемещаемся на сравнение mxR19: clr r19 ; регистр 19 оказался наименьшим, обнуляем его jmp compare ; перемещаемся в сравнении mxR20: ; в падлу писать, тоже самое, только 20 и 21 регистры clr r20 clr r1 clr r0 jmp compare mxr21: clr r21 jmp compare ; AssemblerApplication1.asm ; ; Created: 2/25/2022 8:18:58 AM ; Author : loxdogs ; ; Replace with your application code ``` ##### Пример задачи №2: Деление до сотых вводиться 2 числа в ROM, программа должна уметь делить эти числа, точность деления определяется до сотых. После получения ответа, программа должна зациклиться сама на себя N = 27 ЧР = 2 НЧР = 1 N + Чр / N + НЧР ```cp= ; очищаем регистры r16-r21 для работы с ними clr r16 ; r16 - делимое clr r17 ; r17 - делитель clr r18 ; r18 - частное(целая часть) clr r19 ; r19 - частное(десятичная часть) clr r20 ; r20 - частное(сотая часть) clr r21 ; r21 - остаток clr r22 ; r22 = 0, константа, которая будет равна 10 ldi r22, 10 ldi r16, N ; загружаем номер по списку, вписать свой вместо N ldi r17, N ; сюда тоже загружаем свой номер по списку inc r16 inc r16 ; добавляем "любое" чётное inc r17 ; добавляем "любое" нечётное div: ; начало деления для целого значения cp r16, r3 breq is00 cp r16, r17 brmi div10mul sub r16, r17 inc r18 jmp div div10mul: ;; нам надо один раз умноижть остаток на 10, поэтому создаём переход mul r16, r22 ;; остаток умноженный на 10 записывается в r0 div10: cp r0, r3 breq isX0 cp r0, r17 brmi div100mul sub r0, r17 inc r19 jmp div10 div100mul: mul r0, r22 div100: cp r0, r3 breq isX0 cp r0, r17 brmi end sub r0, r17 inc r20 jmp div100 end: jmp end is00: ;; если остаток 0, тогда дробная часть тоже нуль, загружаем два нуля ldi r19, 0 ldi r20, 0 jmp end isX0: ;; если остаток после десятичной нуль, тогда дальше будут нули... ldi r20, 0 jmp end ``` #### Пример задачи №3: Сортировка при инициализации контролера в роне присутствует массив, отсортировать в порядке возрастания ```cp= ; использую сортировку пузырьком ; как она работает - сначала первый элемент сравниваем со вторым - если второй меньше, то меняем местами ; дальше второй меняем с третьим - и так далее ; вот тут понятнее как работает https://academy.yandex.ru/posts/osnovnye-vidy-sortirovok-i-primery-ikh-realizatsii ldi r16, 12 ; 1 ; тут аналогично закидываем данные в регистры между ними ldi r23, 50 ; 8 ; проверяем, что массив отсортирован isSorted: ; проверяем каждое правое с соседним левым. Если какое-то меньше, то идем сортировать cp r23, r22 brmi checkAndSwap67 ; вызывается 67, а не 78 потому что relative breach out of reach ; тут аналогично сравниваем соседние элементы и вызываем checkAndSwap56|45... cp r17, r16 brmi checkAndSwap12 jmp isSorted ; если отсортировано - зациклить ; checkAndSwapXY меняет местами значения на двух регистрах, если левое больше правого checkAndswap12: cp r17, r16 brmi swap12 ; если правое меньше левого, меняем местами jmp checkAndSwap23 ; swap12: mov r0, r16 mov r16, r17 mov r17, r0 jmp checkAndSwap23 ; тут аналогичные ветки для сравнения 12, 34, 45, 56, 67... ; ------- 78 checkAndswap78: cp r23, r22 brmi swap78 jmp isSorted swap78: mov r0, r22 mov r22, r23 mov r23, r0 jmp isSorted ``` #### Пример задачи №4: Задержка Реализовать программу задержки в 15 циклов, после чего программа переходит в режим ожидания (M1: nop jmp M1) ```cp= clr r18 ; cycle param start: ; cycle body inc r18 cpi r18, N ; do while r18(++) < N brmi start ; do after cycle repeat: jmp repeat ``` #### Пример задачи №5 > [name=Дарья Воронская] А нам точно нужно объяснение для 2 аналогичных задач (типа, 1 найти наименьшее, а это наибольшее)? > Да и мне кажется, что весь поиск наименьшего в 1 задании можно убрать, потому что у нас есть задание на сортировку, которое делает буквально то же самое > > [name=Boyarkin Alexandr] Как минимум одну задачку надо оставить. Вдруг по уловию нельзя будет использовать сортировку > Найти наибольшее число любым доступным образом (аналогично условию первого примера) 1 + N = 28 3 * N = 81 (10 * N) + 2 = 272 ```cp= clr r16 ; очищаем нашу константу, в ней мы будем хранить номер группы = N ldi r16, N ; N = свой номер по порядку, clr r17 ; с r17, r18, r20 будет работа с числами clr r18 clr r20 ; число 1 (r17) mov r17, r16 ; R17 = N inc r17 ; R17 = N + 1 ; число 2 (r18) clr r22 ; число счётчик mulR18: ; не понял, как сравнивать числа состоящие из двух регистров add r18, r16 inc r22 cpi r22, 3 brmi mulR18 clr r22 ; число 3 (r20) mov r20, r16 ; R20 = N adiw r24, 10 ; R24 = 10 muls R20, R24 ; R1:R0 = N * 10 inc r0 inc r0 ; передайте селезнёву, что он хороший челочек compare: ; R17 compare start cp r17, r3 ; Смотрим r17=0 если да переходим к r18 breq M1R18 cp r17, r18 ; ну сравниваем два числа r17 - r18 brpl M2R17 ; если + , то идем по коду, так как r17 больше jmp M1R18 M2R17: cp r1, r3 breq r20M1null ;; если, старший разряд нуль, тогда сравниваем его как обычное число по метке R20null jmp mxr20 r20M1null: cp r0, r3 breq mxr17 cp r17, r0 brpl mxr17 jmp mxr20 ; R17 compare end ; kakaya je eto huyeta ; R18 compare start M1R18: cp r18, r3 breq mxr20 cp r1, r3 breq r20M2null ;; если, старший разряд нуль, тогда сравниваем его как обычное число по метке R20null jmp mxr20 r20M2null: cp r0, r3 breq mxr18 cp r18, r0 brpl mxr18 jmp mxr20 ; R18 compare end ; R19 compare start mxR17: clr r17 ; регистр 17 оказался наименьшим, обнуляем его jmp compare ; перемещаемся на сравнение mxR18: clr r18 ; регистр 18 оказался наименьшим, обнуляем его jmp compare ; перемещаемся на сравнение mxR20: clr r20 clr r1 clr r0 ; регистр 20 оказался наименьшим, обнуляем его jmp compare ; перемещаемся в сравнении ``` #### Пример задачи №6: Чтение из порта ввода, вызов команд При инициализации в ROM находится 3 числа. Программа должна считывать порт в зависимости от значения на порту выполнять след. действия: P/N - номер порта/номер по списку расчитаться по 3 1 - B 2 - C 3 - D 0000 0000 - ничего не происходит 0000 0001 - посчитать сумму 0000 0010 - посчитать произведение 0000 0100 - поиск максимума 0000 1000 - поиск минимума 0001 0000 - рассчитать среднее арифмитическое 0010 0000 - найти среднее 0100 0000 - установить все единицы в регистре 1000 0000 - сбросить регистр примечание: Детектирование логической единицы на каждом пине должно происходить один раз ```cp= ;; created by group of indusi and eskimo ;; start 03.15.22 - mm/dd/yy ;; end 03.29.22 - mm/dd/yy ;; (не)цензурная версия ;; ¯\_(ツ)_/¯ - не знаем, уточнить у Виктора Сергеевича ;; .equ - задаём список констант ;.include "m16def.inc" ; НИХУЯ НЕ РАБОТАЕТ БИБЛИОТЕКА БЛЯТЬ, НАЕБАЛИ ¯\_(ツ)_/¯ ;; уговорите блять селезнёва объяснить людям стек, заебал "relative branch is out of reach" уже .cseg ; ну, он просил оформлять так, мы добавили... ;; задаём port, ddr, pin .equ port = portb ; вместо буквы N надо указать букву своего порта (1 - B / 2 - C / 3 - D) .equ ddr = ddrb ; тоже самое, что и с портом, определяет какие пины на чтение, какие на запись .equ pin = pinb ; тоже самое, что и с портом, только не знаем, зачем он нужен¯\_(ツ)_/¯ ;; commands start .equ void = 0b00000000 ;(0 ) при отсутствии сигналов на пин, мы ничего не делаем .equ plus = 0b00000001 ;(1 ) при сигнале на пин 1, мы складываем все числа .equ mult = 0b00000010 ;(2 ) при сигнале на пин 2, мы умножаем все числа(придумать способ умножения) .equ maxi = 0b00000100 ;(4 ) при сигнале на пин 3, мы находим максимальное число .equ mini = 0b00001000 ;(8 ) при сигнале на пин 4, мы находим минимальное число .equ aver = 0b00010000 ;(16 ) при сигнале на пин 5, мы находим среднее арифмитическое .equ midl = 0b00100000 ;(32 ) при сигнале на пин 6, мы находим среднее число .equ onee = 0b01000000 ;(64 ) при сигнале на пин 7, мы устанавливаем все единицы в регистре .equ drop = 0b10000000 ;(128) при сигнале на пин 8, мы сбрасываем регистр ;; commands end ;; variables definition start .def zero = r3 ; zero - регистр, который мы определили для сравнения с 0 .def cmnd = r16 ; cmnd - регистр, который отвечает за команду .def temp = r17 ; temp - регистр, который отвечает за всякую хуйню .def num1 = r18 ; num1 - регистр, в который мы записываем "случайное" число .def num2 = r19 ; num2 - регистр, в который мы записываем "случайное" число .def num3 = r20 ; num3 - регистр, в который мы записываем "случайное" число .def res1 = r21 ; res1 - регистр, в который мы записываем результат вычислений. При сложнии это нижний байт. При умножении - это нижний байт. При сравнении чисел это самое маленькое число. .def res2 = r22 ; res2 - регистр, в который мы записываем результат вычислений. При сложнии это старший байт байт. При умножении - это средний байт. При сравнении чисел это среднее число. .def res3 = r23 ; res3 - регистр, в который мы записываем результат вычислений. При сложнии не учавствует. При умножении - это средний байт. При сравнении чисел это среднее число. ;; variables definition end ; out ddr, 0b00000000 - задаём везде 0, так как все пины ; подача сигнала ldi cmnd, void ; загружаем в регистр команд команду 0b00000000, так как нам надо, чтобы все пины в ddr были на чтение ;; port reading out ddr, cmnd ; ddrb - 00000000 - работает на чтение ;; command set start ldi cmnd, maxi ; тут мы выбираем, какая команда будет дальше по коду(якобы пришло напряжение на пин.) out port, cmnd ; загружаем в порт эту команду ;; comand set end ;; nums ;; загружаем числа в регистры в 16 системе ldi num1, 0x05 ; загружаем в num1 число ldi num2, 0x02 ; загружаем в num2 число ldi num3, 0x04 ; загружаем в num3 число ;; code starts ;; plus sbis port, 0 ; если на пине 0 есть 1, тогда пропускаем jmp M1 jmp M1 ; прыгаем на следующую команду, если на пине 0 есть 0 M0: add res1, num1 ; складываем в res1(нижний байт) num1 -> res1 = num1 add res1, num2 ; добавляем к res1(нижний байт) num2 -> res1 = num1 + num2(остаток от их сложения) brcs carry ; проверяем, случилось ли переполнение, если да, то прыгаем на carry jmp stp carry: ; попадаем сюда, если случилось переполнение (num1+num2>255) clc ; очищаем флаг переполнения inc res2 ; повышаем старший байт на 1 add res1, num3 ; добавляем к res1(нижний байт) num3 = res1 = остаток от (num1 + num2) + num3 brcs carry2 ; проверяем на переполнение, если это так, от прыгаем на carry2 jmp stp ; если переполнения нет, то идём к следующему шагу(step) carry2: ; попадаем сюда, если произошло последнее возможное переполнение clc ; очищаем флаг переполнения inc res2 ; повышаем старший байт stp: ; вычисления закончены, отправляемся на задержку cpi cmnd, aver breq M2 jmp timeDelay ;; mult команда работает, но если после первого умножения число будет храниться в двух регистрах, то считает неправильно... (неисправимо на данный момент) M1: sbis port, 1 ; если на пине 1 есть 1, тогда пропускаем jmp M2 jmp M2 ; прыгаем на следующую команду, если на пине 1 есть 0 mult1: ; умножение первого числа ; brvs poshelN ; на случай, если произойдёт УЛЬТРА переполнение, тогда отправляемся в poshelN cp num2, zero ; сравниваем, осталось ли во втором множителе ещё чего умножать breq mult2 ; если во втором множителе уже 0, тогда идём умножать последнее число add res1, num1 ; если не так, тогда складываем в нижний байт число num1 brcs carry1m ; если у нас переполнение, отправляемся в carry1m dec num2 ; так как умножение это цикл, то уменьшаем счётчик(множитель) jmp mult1 ; повторяем цикл carry1m: ; если переполнение в нижнем байте cp num2, zero ; сравниваем, есть ли что-то во множителе или надо идти по второму множителю brne num2cp ; если это множитель не равен нулю, тогда идём в num2cp jmp num3cp ; если равен, тогда идём в num3cp num2cp: ; цикл в котором мы решаем переполнение с младшим байтом dec num2 clc inc res2 brcs carry2m jmp mult1 num3cp: ; цикл, в котором решаем переполнение со средним байтом dec num3 clc inc res2 brcs carry2m jmp mult3 mult2: ; умножение второго множителя, промежуточная стадия ; brvs poshelN ; на случай, если произойдёт УЛЬТРА переполнение, тогда отправляемся в poshelN mov num1, res1 ; так как после умножения, у нас новый множитель(уже какой-то по счёту), надо его назначить dec num3 ; так как это цикл в цикле, надо число циклов снизить на один... вроде, иначе ответ ровно на цикл больше лол))) mult3: ; умножение второго множителя cp num3, zero ; короче, тоже самое, только с другим множителем, нечего тут дописывать уже... breq M5 ; ЕБУЧИЙ "RELATIVE BRANCH IS OUT OF REACH", короче, оно должно перемещать на TimeDelay, но ты пососёшь, если будешь делать так. Правильно timedelay, неправильно, это отправлять на ближайшую возможную метку, чтобы код просто сам дошёл до timeDelay, но это только в теории. Код надо либо перелопатить, либо пойти нахуй, я выбираю второе add res1, num1 brcs carry1m dec num3 jmp mult3 carry2m: ; переполнение среднего байта, решение clc inc res3 jmp mult1 ;; maxi - нахождение максимального числа ;; ради экономии рабочего времени нахождение максимума, минимума и среднего это один и тот же алгоритм сортировки, ;; все числа записываются в res, где и происходит сортировка (как по массиву) M2: sbis port, 2 jmp M3 sort: ;; инициализация чисел в res и переход на основной цикл сортировки mov res1, num1 ;; переписываем значения из переменных num в переменные res до начала сортировки mov res2, num2 mov res3, num3 jmp isSorted isSorted: ;; проверка, что числа отсортированы. Если какие-то два не отсортированы, меняет их местами и снова проверяет всё по новой cp res3, res2 ;; сравниваем правое число со средним brmi swap23 ;; среднее больше - меняем cp res2, res1 ;; сравниваем левое число с правым brmi swap12 ;; левое больше - меняем jmp timeDelay ;; правое больше или равно среднего, а среднее больше или равно левого. Отсортировано, на задержку swap23: ;; меняем местами правое и среднее числа mov temp, res3 ;; я надеюсь не нужно комментировать перекид из одной переменной в другую, ну типа, этож очевидно mov res3, res2 mov res2, temp jmp isSorted swap12: ;; меняем местами среднее и левое числа mov temp, res1 mov res1, res2 mov res2, temp jmp isSorted ;; mini - нахождение минимального числа M3: sbis port, 3 jmp M4 jmp sort ;; aver - нахождение среднего арифмитического M4: sbis port, 4 jmp M5 jmp M0 stpA: ; вычисления закончены, идём считать среднее арифмитическое(где temp - примерное целое значение) cpi res1, 3 ; смотрим, можем ли мы ещё из суммы(меньшего байта) вычесть 3(так как всегда ищем ср.Ар. трёх чисел) brpl bigger ; если можем, то прыгаем на bigger jmp smaller ; если не можем, то отправляемся в smaller bigger: ; тут вычитаем из суммы(меньшего байта) три subi res1, 3 inc temp ; повышем кол-во целых на 1 jmp stpA ; идём на повтор smaller: ; если мы не можем вычесть из меньшего байта, тогда смотрим, есть ли ещё что-то в старшем байте cp res2, zero breq End; если ничего нет, тогда заканчиваем алгоритм, ответ в temp jmp notEnd; если есть, тогда занимаем один и продолжаем алгоритм notEnd: dec res2; занимаем один ldi res1, 0x7f; выгружаем значение 127(потому что 0xff не работает и считается как -127) jmp stpA; идем на повторение end: jmp poshelN ;; midl - нахождение среднего числа M5: sbis port, 5 jmp M6 jmp sort ;; onee - установка единиц на регистрах результата(я не совсем понял, что Селезнёв имел ввиду, но думаю напишет, если что-то неправильно) M6: sbis port, 6 jmp M7 ldi res1, 0b11111111 ldi res2, 0b11111111 ldi res3, 0b11111111 ;; drop - сбросить значение на регистре M7: sbis port, 7 jmp timeDelay ;; очищение основных регистров clr res1 clr res2 clr res3 jmp timeDelay poshelN: ;; poshelN - обозначние ошибки(fatalError) jmp poshelN ;; code ends timeDelay: ;; задержка в развитии на 3 секунды clr r29 clr r30 clr r31 ldi r31, 12 M8: inc r29 brne M8 inc r30 brne M8 dec r31 slp: jmp slp ;; режим ожидания, после задержки ``` #### Пример задачи №7 Считывается порт. Такой же как и в задании 6 с 0 по 4 пин задаётся число которое надо записать в регистр общего назначения после чего 5, 6, 7 пином выполняются след. действия: 5 - увеличение разряда числа 6 - уменьшение разряда числа 7 - записать значение в свободный RON 5,6,7 пин выполняются после 5 секундной задержки ```cp= ;; created by group of indusi ;; start 04.03.22 - mm/dd/yy ;; end 04.03.22 - mm/dd/yy ;; (не)цензурная версия ;; ¯\_(ツ)_/¯ - не знаем, уточнить у Виктора Сергеевича ;; .equ - задаём список констант ;.include "m16def.inc" ; НИХУЯ НЕ РАБОТАЕТ БИБЛИОТЕКА БЛЯТЬ, НАЕБАЛИ ¯\_(ツ)_/¯ ;; lsr - logical shift right (смещение битов вправо) (уменьшить число в 2 раза) ;; lsl - logical shift left (смещение битов влево) (увеличить число в 2 раза) .cseg ; ну, он просил оформлять так, мы добавили... ;; задаём port, ddr, pin .equ port = portb ; вместо буквы N надо указать букву своего порта (1 - B / 2 - C / 3 - D) .equ ddr = ddrb ; тоже самое, что и с портом, определяет какие пины на чтение, какие на запись .equ pin = pinb ; тоже самое, что и с портом, только не знаем, зачем он нужен¯\_(ツ)_/¯ ;; variables definition start .def cmnd = r16 ; cmnd - регистр, который отвечает за команду .def temp = r17 ; temp - регистр, который отвечает за всякую хуйню .def res1 = r18 ; res1 - регистр, в который мы записываем результат работы программы. ;; variables definition end ; подача сигнала ldi cmnd, 0b00000000 ; загружаем в регистр команд команду 0b00000000, так как нам надо, чтобы все пины в ddr были на чтение ;; port reading out ddr, cmnd ; ddrb - 00000000 - работает на чтение ;; command set start ldi cmnd, 0b11001111 out port, cmnd ; загружаем в порт эту команду ;; comand set end ;; задержка в развитии на 3 секунды(лень делать на пять) clr r29 clr r30 clr r31 ldi r31, 12 M18: inc r29 brne M18 inc r30 brne M18 dec r31 ;; загружаем в temp задание из порта in temp, port cbr temp, 0b11100000;; очищаем 5-7 биты, чтобы осталось только число, которое задавали через порт m1: sbis port, 5 ;; увеличиваем разряд числа (не сказано, чтобы число осталось тем же самым) jmp m2 lsl temp lsl temp M2: sbis port, 6 ;; уменьшаем разряд числа (не сказано, чтобы число осталось тем же самым) jmp M3 lsr temp lsr temp M3: sbis port, 7 ;; записываем число в регистр jmp timeDelay mov res1, temp timeDelay: ;; задержка в развитии на 3 секунды(лень делать на пять) clr r29 clr r30 clr r31 ldi r31, 12 M8: inc r29 brne M8 inc r30 brne M8 dec r31 slp: jmp slp ;; режим ожидания, после задержки ``` ### Команды :::info Описанных ниже команд достаточно, чтобы решать задачки на любые манипуляции с РОН (арифметические действия, массивы, сортировка). А всякого рода задачки из последних месяцев мы не решим :crying_cat_face: ::: :::warning :-1: Всратости :scream: 1. Команда inc не изменяет флаг C. Значения остальных флагов: Z = 1, S = 0, V = 0, N = 0 2. команда sub Rd, Rx изменяет флаги так: C = 1 если |Rx| > |Rd| 3. Я не записывал любые косвенные команды, не понимаю их, да и вроде не просили ::: всратые команды, которые скорее всего не пригодятся, и которые я так и не понял: > [name=Дарья Воронская] Ля, adiw походу все же нужен ```cp= ; сложить 10 с парой регистров [rx, rx+1] adiw rx, 10 ; сравнить значение регистров с учетом переноса. cpc Rd, Rx ; дробное умножение fmul, fmuls, fmulsu lpm ``` #### Прерывания ```cp= .org <Вставь номер вектора прерывания> jmp <Вставь ветку для обработчика прерываний> ; Пример для ацп .org 0x01C jmp calculate calculate: ; получили результат reti ``` #### Директивы Грубо говоря, названия для переменных ```cp= .equ name = const; завести константу .def name Rx; обозвать регистр ``` #### Загрузка данных ```cp= ; загрузить значение. Не во все регистры можно загрузить значение таким образом ldi Rx, Rd ; Загрузить в РОН значение по адресу SRAM lds Rx, $ff00 ; загрузить в адрес SRAM значение из РОН sts $ff00, Rx ; поместить в регистр Rd значение регистра Rx. Иногда это единственный способ поместить в некоторые регистры значение mov Rd, Rx ; считать значение с порта в РОН in Rx, P ; закинуть значение в порт с РОН out P, rx ; очистить бит const в регистре ввода/вывода cbi P, const ; очистить бит const в РОН cbr Rx, const ; установить бит const в регистре ввода/вывода sbi P, const ; установить бит const в РОН sbr Rx, const ; очистить РОН clr Rx ``` #### Арифметика ```cp= ; Rd = Rd + Rx. После этой команды sreg меняется add Rd, Rx ; Сложение с переносом (add with carry); Rd = Rd + Rx + SREG:C. ; Например, если Rd = 2, Rx = 4, C = 1, то Rd = 2+4+1=7 adc Rd, Rx ; вычесть. Значение в Rd. Читай всратости sub Rd, Rx subi Rd, const ; вычесть с переносом. Rd = Rd - Rx - C sbc Rd, Rx sbci Rd, const ; увеличить значение в РОН на 1. Читай всратости inc Rx ; уменьшить значение в РОН на 1. SREG меняется адекватно dec Rx ; беззнаковое умножение. ; из умножения 2 восьмибитных чисел получится 16 битное, которое будет храниться в регистрах R1 (старший байт), R0 (младший байт). SREG:C Устанавливается если установлен бит 15 результата, в ином случае очищается mul Rd, Rx ; знаковое умножение muls Rd, Rx ; умножение беззнакового со знаковым mulsu Rd, Rx ``` #### Битовые операции ```cp= ; очистить бит const в регистре ввода/вывода cbi P, const ; очистить бит const в РОН cbr Rx, const ; сдвиг всех битов регистра вправо; 7 бит не изменяется. 0 заносится в SREG:C. ; например 10011001. C = 0 -> 10001100. C = 1 -> 10000110. C = 0. ; Эта команда эффективно делит значение дополнения до двух (число записанное с указанием знака) на два, без изменения знака asr Rx ; битовые сдвиг влево; Бит 7 сдвигается в C, Бит 0 = 0 ; Другими словами является умножением беззнакового числа на два lsl Rx ; битовые сдвиг вправо; Бит 0 сдвигается в C, Бит 7 = 0 ; Другими словами является делением беззнакового числа на два lsr Rx ; сдвинуть влево через перенос. В бит 0 идет С. Бит 7 сдвигается в С rol Rx ; сдвинуть вправо через перенос. В бит 7 идет С. Бит 0 сдвигается в С ror Rx ; поменять местами ниблы (полубайты) swap Rx ``` #### Дополнения ```cp= ; выполнить дополнение до еденицы ; Другими словами - меняет все 0 на 1 и все 1 на 0. ; C = 1, V = 0; N = 7 бит com Rx ; выполнить дополнение до 2 (выделяет бит для отрицательности) ; Число 80 (1010000) не меняется neg Rx ``` #### Сравнения ```cp= ; сравнить значение Rd с регистром/константой. Эквивалентно sub только никуда не записывается результат. cp Rd, Rx сpi Rd, const ; сравнить значения двух регистров, и пропустить следующую команду, если они равны cpse Rd, Rx ; пропустить следующую команду, если бит в регистре IO очищен sbic P, const ; пропустить следующую команду, если бит в регистре IO установлен sbis P, const ; пропустить следующую команду, если бит в РОН очищен sbrc P, const ; пропустить следующую команду, если бит в РОН установлен sbrs P, const ; подразрядное умножение. Rd = Rd&Rx (коньюкция) = И and Rd, Rx ; подрязрядное умножение с константой; Rd = Rd&const andi Rd, 10 ; подразрядное сложение. Rd = Rd + Rx (дезьюкция) = ИЛИ or Rd, Rx ; подразрядное сложение с константой; Rd = Rd + const (дезьюкция) = ИЛИ ori Rd, 10 ; выполнить xor на каждом бите Rd, Rx. Записать в Rd ; например eor 1001, 1010 = 0011 eor Rd, Rx ; Проверить на 0 или минус. Аналогичен and Rx, Rx tst Rx ``` #### Переходы **jmp br_name** - безусловный переход на ветку **br<XY>** - условный переход на ветку. [Читай тут](/BhJ3OyD_RIi3lcawKRJbyg) #### Функции **call func_name** - вызвать функцию **ret** - окончание фукнции **reti** - вернуться из прерывания ```cp= mov r16, r0 ; Копировать r0 в r16 call check ; Вызвать подпрограмму nop ; Продолжать (пустая операция) . . . check: cpi r16, $42 ; Проверить содержит ли r16 заданное значение breq error ; Перейти если содержит ret ; Вернуться из подпрограммы ```