Мы много сил и времени потратили на изучение того, как встроенная ЭВМ микроконтроллера работает а памятью. Пришло время сделать следующий шаг - начать знакомство с командами, которые собственно и работают с данным хранящимися в памяти.
Однако, перед этим нам нужно немного подробнее разобраться с флагами, или состояниями. Эта информация нам будет часто требоваться и, что бы потом не отвлекаться, начнем с нее.
Нужно отметить, что флаги/статусы являются лишь частью общего понятия "состояние процессора" и еще более объемлющего "состояние машины". Регистр, или даже набор регистров, состояния используется не только для получения информации, но и для управления. Например, для задания приоритета процессора, включения разных режимов управления отображением памяти, управления работой отдельных узлов процессора.
Поэтому разрядность регистров состояния зачастую превышает восемь бит. А сами регистры называются PSW (processor status word), слово состояния процессора, или MSW (machine status word), слово состояния машины.
Однако, мы рассматриваем всего лишь 8 битные микроконтроллеры и здесь все гораздо проще.
Флаги, они же статусы
Давайте немного вспомним, как они называются в разных микроконтроллерах и посмотрим, какую информацию они хранят
Флаг С - перенос/заем
В своем эталонном значении этот флаг означает тоже самое, что всем прекрасно знакомо по школьному сложению и вычитанию столбиком. Когда мы складывали две цифры и результат сложения был больше 9 то мы выполняли перенос. А если вычитаемое было больше уменьшаемого, то приходилось выполнять заем.
Но в нашем случае, когда ЭВМ работает данным размеров в один байт, установленный флаг С означает, что в результат операции занимает более одного байта и возник перенос из старшего разряда, или заем в старший разряд байта
Это пример сложения и вычитания, самых привычных арифметических операций. Важно отметить, что перенос/заем это НЕ ошибка. Этот флаг используется для сложения и вычитания многобайтовых чисел. Точно так же, как мы поступали в школе.
На самом деле, существуют и междуразрядные переносы/заемы. Но их не видно, так специальный флаг существует только для переноса из старшего разряда. О единственном исключении речь пойдет немного позже.
В современных ЭВМ флаг переноса используется не только в арифметических операциях. Так в операциях сдвигов и циклических сдвигов (вращений) содержимое этого флага принимает активное участие в выполнении операции, о чем я подробнее расскажу, когда мы доберемся до этих операций.
Используют этот флаг и программисты, в своих прикладных целях. Так установленный флаг С может означать, что при выполнении процедуры произошла ошибка. Или он используется для хранения передаваемого/возвращаемого значения истина/ложь.
Это очень часто используемый флаг.
Флаг DC или H - перенос между тетрадами
Это то самое единственное исключение, о котором я говорил. Нам доступно состояние переноса/заема внутри байта. А точнее, между его половинами, которые и называются тетрадами (тетра - четыре)
Зачем же понадобился признак переноса внутри байта? Дело в том, что существует специальный формат представления информации, называемый BCD. При этом каждая тетрада хранит одну десятичную цифру. То есть, байт хранит два десятичных разряда. При выполнении арифметических операций над данными в таком формате может возникнуть ситуация, когда содержимое тетрады выходит за диапазон 0-9. Вот эта ситуация и отображается флагами DC или H.
Это редко используемый флаг.
Флаг Z - нулевой результат
Если в результате операции у нас получился байт, в котором все биты нулевые, то будет установлен флаг Z. Важно отметить, что установленный флаг Z вовсе не означает, что результат действительно равен 0! Ведь при этом может быть еще и установлен флаг С, а значит результат вполне может оказаться равным 100000000 (9 разрядов). Флаг Z показывает только то, что все 8 бит байта результата нулевые.
Это часто используемый флаг.
Флаг OV или V - переполнение
Этот флаг имеет смысл только при работе со знаковыми числами. Причем для многобайтовых чисел только при операциях со старшими байтами. И означает он, что знак результата во время операции принял неверное значение. А значит, и весь результат ошибочный. Например, при сложении двух положительных чисел результат получился отрицательным.
Как такое возможно? Что бы понять это, нужно разобраться, как в ЭВМ представляются не просто числа, а числа имеющие знак. То есть, положительные и отрицательные. Самый старший бит байта, если его содержимое считается знаковым, показывает знак числа. При этом отрицательные числа представлены в дополнительном коде.
То есть, для знакового числа выделяется не 8, а всего 7 бит в байте. Если знаковый бит равен 0, то число считается положительным и оставшиеся 7 бит и являются собственно числом. Если знаковый бит равен 1, то число считается отрицательным, при этом его значением является число, которое нужно прибавить к числу в оставшихся семи битах, что бы получился ноль.
Сложно? На самом деле все просто. Давайте посмотрим, как же нам разобраться с числом -59 из примера выше. Инвертируем все разряды нашего числа и получим 00111010. Теперь прибавим единицу и получим 00111011, то есть как раз 59. И наше отрицательное число и будет -59.
Точно так же выполняется и обратное "кодирование". То есть, снова инвертируем все биты и прибавляем 1. Вот так все просто и легко.
А теперь собственно пример с возникновением переполнения
Видите? Мы выполняли сложение двух положительных чисел, но результат отрицательный. На самом деле переполнение это тоже межразрядный перенос/заем. Только перенос возник в знаковый бит, или заем из знакового бита. А если еще точнее, то флаг переполнения устанавливается в ситуации, когда количество переносов в знаковый разряд не равно количеству переносов из знакового разряда. И рассматривать флаг V нужно в совокупности с флагом C.
Еще раз подчеркну, что флаг переноса имеет смысл только при работе со знаковыми числами. Этот флаг используется относительно редко. И в большинстве случаем его установка означает ошибку. Не все микроконтроллеры имеют флаг переполнения, так в PIC (кроме PIC18), этот флаг отсутствует.
Флаг N - отрицательный результат
Этот флаг тоже имеет смысл только в случае работы со знаковыми числами. Фактически, его значение просто равно знаковому биту результата. По большому счету, вместо проверки данного флага мы можем с тем же успехом проверять бит 7 байта(знаковый). Однако, существуют команды условных переходов, которые работают как раз с флагом N и не выполняют дополнительных проверок байта данных.
Данный флаг иногда может использоваться и с беззнаковыми числами, например, вместе с командами сдвигов и циклических сдвигов. Но это нетипичное применение и используется редко. Данный флаг отсутствует в PIC (кроме PIC18), но проблем это не вызывает, в силу специфичности их системы команд.
Довольно часто используемый флаг.
Флаг S - знак
Этот флаг специфичен для AVR. Его значение равно результату операции Исключающее ИЛИ между битами N и V. Используется, например, в командах условных переходов, таких как BRGE (переход если больше или равно) при работе со знаковыми числами.
Флаг Т - хранилище копии
Еще один специфичный для AVR флаг. Используется в командах BLD и BSD позволяющих позволяющих загрузить в заданный бит регистра R0-R31 содержимое флага Т, или сохранить заданный бит регистра в флаге Т.
Заключение
Сегодняшняя статья получилась короткой и легкой. Но она важна для нас, так как почти все команды, которые мы будем изучать в дальнейшем, оказывают влияние на флаги состояния. А флаги оказывают влияние на выполнение некоторых команд. И для понимания нам будут очень нужны эти сведения.
До новых встреч!