---
# System prepended metadata

title: ВСЕ ЗДЕСЬ

---

# ВСЕ ЗДЕСЬ

## 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          ; Вернуться из подпрограммы
    
```