Cmp

Как запускается программа на Arduino

Начав выполнение программы, Arduino выполняет ряд рутинных операций по инициализации и настройке среды окружения и только затем приступает к выполнению того самого кода, который  содержится в наших с вами скетчах. Таким образом, ардуино избавляет нас от необходимости помнить все детали архитектуры микропроцессора и сконцентрироваться на стоящей перед нами задаче (это не значит, что мы не должны понимать, что же происходит за кадром, но об этом поговорим в отдельной статье).

Для иллюстрации сказанного приведем фрагмент исходников Arduino, в которых и производится вызов наших функций (файл main.cpp):

int main(void)
{
	init();

	initVariant();

#if defined(USBCON)
	USBDevice.attach();
#endif
	
	setup();
    
	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
        
	return 0;
}

Функция main() – это настоящая точка входа в программу, именно она вызывается первой. Как мы видим, в ней вызываются методы инициализации параметров и среды окружения, а затем и наши void setup() и, уже в цикле – void loop();

По идее, мы можем реализовать другую логику запуска и сделать внутри основного метода несколько функций loop, реализуя многопоточность. Но в данной статье мы не будем этого делать. Более подробно о возможности реализации многопоточности можно прочитать в этой замечательной статье.

Команды сравнения данных

Команды данной группы выполняют сравнение значений числа в вершине стека и операнда, указанного в команде.Команды сравнения данных вещественного типа

Команда Операнды Пояснение Описание
FCOM FUCOM src ST(0) — src Вещественное сравнение
FCOMP FUCOMP src ST(0) — src; TOPSWR+=1; Вещественное сравнение с выталкиванием
FCOMPP FUCOMPP ST(0) — ST(1); TOPSWR+=2; Вещественное сравнение с двойным выталкиванием
FCOMI FUCOMI ST, ST(i) ST(0) — ST(i) Вещественное сравнение c модификацией EFLAGS
FCOMIP FUCOMIP ST, ST(i) ST(0) — ST(i); TOPSWR+=1; Вещественное сравнение c выталкиванием с модификацией EFLAGS
FXAM Анализ ST(0)

Команды сравнения сравнивают значение в вершине стека с операндом. По умолчанию (если операнд не задан) происходит сравнение регистров ST(0) и ST(1). В качестве операнда может быть задана ячейка памяти или регистр. Команда устанавливает биты C0, C2, C3 регистра swr в соответствии с таблицей. Сбрасывает в 0 признак C1 при пустом стеке после выполнения команды.

Условие С3 С2 C0
ST(0) > src
 ST(0) < src 1
 ST(0) = src  1
 Недопустимая операция (#IA)  1 1 1

Особый интерес представляет команда FCOMI (FUCOMI). Она сравнивает содержимое регистра ST(0) со значением операнда ST(i) и устанавливает биты ZF, PF, CF регистра в соответствии с таблицей. Анализ выполнения сравнения осуществляет последующая команда условного перехода (команда центрального процессора).

Условие ZF PF CF Переход
 ST(0) > ST(i)  ja
 ST(0) < ST(i) 1  jb
  ST(0) = ST(i)  1  je
  ST(0) >= ST(i)  *  jae
  ST(0) <= ST(i)  * *  jbe
 Недопустимая операция (#IA)  1  1 1

Команда FXAM проверяет содержимое регистра ST(0) и устанавливает биты C0, C2, C3 регистра swr в соответствии с таблицей. Бит C1 устанавливается равным знаковому биту ST(0).

Класс С3 С2 C0
Неподдерживаемый формат
Нечисло (NaN) 1
Конечное число 1
Бесконечность 1 1
Ноль 1
Пустой регистр 1 1
Ненормированное число 1 1

Команды сравнения данных целого типа

Команда Операнды Пояснение Описание
FICOM src ST(0) — src Cравнение с целым числом src
FICOMP src ST(0) — src; TOPSWR+=1; Cравнение с целым числом src с выталкиванием
FTST ST(0)-0; Анализ ST(0) (сравнение с нулем)

Синтаксис void setup()

Синтаксис функции setup очень прост:

void setup(){

// тут располагаются команды подпрограммы

}

В этом примере слово setup – это название функции. Нужно писать именно так, именно в таком регистре. Слово перед названием описывает  тип возвращаемых данных. В данном случае никаких данных подпрограмма не возвращает, поэтому мы должны указать слово void. Все команды должны размещаться внутри фигурных скобок {}.

Не забывайте ставить фигурные скобки! Потеря хотя бы одной скобки сразу сделает всю программу непонятной для ардуино. Но и лишние скобки тоже не ставьте – это так же приведет к ошибке.

Использование команд перехода

Этот способ вы наверняка уже использовали, сами того не подозревая.
Суть его проста — почти все команды проверяют какие-то флаги. Соответственно, с их помощью можно узнать состояние этих флагов. Правда, некоторые команды перехода проверяют не один, а несколько флагов. Такие команды для нас не подойдут. А вот те, которые проверяют только один флаг — это то, что нам нужно. Вот они:

Таблица 1. Команды, которые можно использовать для проверки флагов.

Команда Условие перехода
JZ, JE ZF = 1
JC, JB, JNAE CF = 1
JS SF = 1
JO OF = 1
JPE, JP PF = 1
JNZ, JNE ZF = 0
JNC, JNB, JAE CF = 0
JNS SF = 0
JNO OF = 0
JPO, JNP PF = 0

Как видно из таблицы, с помощью команд перехода можно проверить почти все основные флаги.

А теперь о том, как это использовать. Поясню на примере:

.model tiny
.code
ORG    100h
	
start:	
  MOV AH, 7
  CMP AH, 7    ;ZF = 1
  JZ  ZF_1
  JMP ZF_0
	
ZF_1:          ;Если ZF = 1, то 
  MOV AH, 1    ;в AH запишем 1
ZF_0:          ;Если ZF = 0, то 
  MOV AH, 0    ;в AH запишем 0
  
  RET

END	start

Если флаг ZF = 1, то мы переходим к метке ZF_1 и записываем в регистр АН число 1. Если флаг ZF = 0, то мы переходим к метке ZF_0 и записываем в регистр АН число 0. Таким образом мы узнаём состояние флага ZF и записываем его в регистр AH.

Цикл в Python с пользовательским начальных и конечных чисел

Если вы не хотите, чтобы последовательность чисел начиналась с 0, вы можете также указать начальное число и конечное значения в функции range, как показано в примере ниже.

# cat for4.py
for i in range(1,6):
 print(i)

В приведенном выше примере:

  • Диапазон (1,6) – Мы определили начальную и конечную величину в функции range.
  • Одна важная вещь, здесь является тот факт, что функция будет начинаться с цифрой «1». Но, кол-во значений будет печататься 5 (а не 6).
  • Если вы хотите, последовательность 1 .. п, то ваш диапазон должен быть: диапазон (1, п + 1).
  • Таким образом, в этом примере, мы хотели последовательность от 1 .. 5 и мы дали диапазон, range(1,6). т.е. конечное значение равно п + 1.

Ниже приведен вывод программы выше

Опять же, обратите внимание, что она начинается с 1 и заканчивается через 5 (а не 6)

# python for4.py
1
2
3
4
5

Рассмотрим команды ассемблера на практическом примере.

С использованием среды разработки TASMED или любого текстового редактора набираем код. Программа, задаст вопрос на английском языке о половой принадлежности (имеется ввиду ваш биологический пол при рождении). Если вы нажмете m (Man), будет выведено приветствие с мужчиной, если w (Woman), то с женщиной, после этого программа прекратит работу. Если будет нажата любая другая клавиша, то программа предположит, что имеет дело с гоблином, не поверит и будет задавать вам вопросы о половой принадлежности, пока вы не ответите верно.

;goblin.asm
.model tiny ; for СОМ
.code ; code segment start
org 100h ; offset in memory = 100h (for COM)

start: main proc
begin:
mov ah,09h
mov dx,offset prompt
int 21h
inpt:
mov ah,01h
int 21h
cmp al,’m’
je mode_man
cmp al,’w’
je mode_woman
call goblin
jmp begin
mode_man:
mov addrs,offset man; указатель на процедуру в addrs
jmp cont
mode_woman:
mov addrs,offset woman; указатель на процедуру в addrs
cont:
call word ptr addrs; косвенный вызов процедуры
mov ax,4c00h
int 21h
main endp

man proc
mov ah,09h
mov dx,offset mes_man
int 21h
ret
man endp

woman proc
mov ah,09h
mov dx,offset mes_womn
int 21h
ret
woman endp

goblin proc
mov ah,09h
mov dx,offset mes_gobl
int 21h
ret
goblin endp

;DATA
addrs dw 0;for procedure adress
prompt db ‘Are you Man or Woman [m/w]? : $’
mes_man db 0Dh,0Ah,»Hello, Strong Man!»,0Dh,0Ah,’$’ ; строка для вывода. Вместо ASCII смвола ‘$’ можно написать машинный код 24h
mes_womn db 0Dh,0Ah,»Hello, Beautyful Woman!»,0Dh,0Ah,’$’ ; строка для вывода
mes_gobl db 0Dh,0Ah,»Hello, Strong and Beautyful GOBLIN!»,0Dh,0Ah,24h ; строка для вывода. 24h = ‘$’ .
len = $ — mes_gobl
end start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

;goblin.asm

.modeltiny; for СОМ

.code; code segment start

org100h; offset in memory = 100h (for COM)

startmainproc

begin

movah,09h

movdx,offsetprompt

int21h

inpt

movah,01h

int21h

cmpal,’m’

jemode_man

cmpal,’w’

jemode_woman

callgoblin

jmpbegin

mode_man

movaddrs,offsetman; указатель на процедуру в addrs

jmpcont

mode_woman

movaddrs,offsetwoman; указатель на процедуру в addrs

cont

callwordptraddrs; косвенный вызов процедуры

movax,4c00h

int21h

mainendp

manproc

movah,09h

movdx,offsetmes_man

int21h

ret

manendp

womanproc

movah,09h

movdx,offsetmes_womn

int21h

ret

womanendp

goblinproc

movah,09h

movdx,offsetmes_gobl

int21h

ret

goblinendp

 
;DATA

addrsdw;for procedure adress

promptdb’Are you Man or Woman [m/w]? : $’

mes_mandb0Dh,0Ah,»Hello, Strong Man!»,0Dh,0Ah,’$’; строка для вывода. Вместо ASCII смвола ‘$’ можно написать машинный код 24h

mes_womndb0Dh,0Ah,»Hello, Beautyful Woman!»,0Dh,0Ah,’$’; строка для вывода

mes_gobldb0Dh,0Ah,»Hello, Strong and Beautyful GOBLIN!»,0Dh,0Ah,24h; строка для вывода. 24h = ‘$’ .

len=$-mes_gobl

endstart

Прыжок без условия

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

В следующем примере мы рассмотрим использование инструкции :

MOV AX, 00 ; инициализируем регистр AX значением 0
MOV BX, 00 ; инициализируем регистр BX значением 0
MOV CX, 01 ; инициализируем регистр CX значением 1
L20:
ADD AX, 01 ; выполняем инкремент регистра AX
ADD BX, AX ; добавляем AX к BX
SHL CX, 1 ; сдвиг влево регистра CX, что, в свою очередь, удваивает значение регистра CX
JMP L20 ; повторно выполняем стейтменты

1
2
3
4
5
6
7
8

MOV  AX,00;инициализируемрегистрAXзначением

MOV  BX,00;инициализируемрегистрBXзначением

MOV  CX,01;инициализируемрегистрCXзначением1

L20

ADD  AX,01;выполняеминкрементрегистраAX

ADD  BX,AX;добавляемAXкBX

SHL  CX,1;сдвигвлеворегистраCX,что,всвоюочередь,удваиваетзначениерегистраCX

JMP  L20;повторновыполняемстейтменты

Команда Loop – просто продолжает цикл

Первая – это сама команда Loop. Все, что она делает, это то, что он продолжает бесконечный цикл.

Как вы видите ниже, следующий пример базовой команды Loop, будет многократно печатать материал между блоком «do» и «end», пока вы не нажмете Ctrl-C

# cat loop1.rb
loop do
  puts "The AndreyEx Blogs"
  puts "Press Ctrl-C to Exit!"
end

Выполните вышеуказанную программу, чтобы проверить ее. Убедитесь, что вы нажимаете Ctrl-C, чтобы выйти из цикла

# ruby loop1.rb
The AndreyEx Blogs
^CPress Ctrl-C to Exit!
loop1.rb:2: Interrupt
    from loop1.rb:1:in `loop'
    from loop1.rb:1

Кроме того, имейте в виду, что для почти любых команд цикла в Ruby вместо «do» и «end» вы также можете указать тело цикла в фигурных скобках {}, как показано ниже.

Следующий пример точно такой же, как и выше, но с использованием фигурных скобок.

# cat loop2.rb
loop {
  puts "The AndreyEx Blogs"
  puts "Press Ctrl-C to Exit!"
}

Предупреждение
Не делайте { на отдельной строке! Если вы это сделаете, вы получите сообщение об ошибке. Следующее неверно, так как { находится на следующей строке после цикла. Он должен быть в той же строке, что и команда loop.

# cat loop2.rb
loop
{
  puts "The AndreyEx Blogs"
  puts "Press Ctrl-C to Exit!"
}

В приведенном выше примере будет выведено следующее сообщение об ошибке.

# ruby loop2.rb
loop2.rb:3: syntax error, unexpected tSTRING_BEG, expecting kDO or '{' or '('
  puts "The AndreyEx Blogs"
        ^
loop2.rb:5: syntax error, unexpected '}', expecting $end
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector